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,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 Note that this call checks for the existence of C<filename>. This
555 stops you from specifying other types of drive which are supported
556 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
557 the general C<guestfs_config> call instead.");
559 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
561 "add qemu parameters",
563 This can be used to add arbitrary qemu command line parameters
564 of the form C<-param value>. Actually it's not quite arbitrary - we
565 prevent you from setting some parameters which would interfere with
566 parameters that we use.
568 The first character of C<param> string must be a C<-> (dash).
570 C<value> can be NULL.");
572 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
574 "set the qemu binary",
576 Set the qemu binary that we will use.
578 The default is chosen when the library was compiled by the
581 You can also override this by setting the C<LIBGUESTFS_QEMU>
582 environment variable.
584 Setting C<qemu> to C<NULL> restores the default qemu binary.
586 Note that you should call this function as early as possible
587 after creating the handle. This is because some pre-launch
588 operations depend on testing qemu features (by running C<qemu -help>).
589 If the qemu binary changes, we don't retest features, and
590 so you might see inconsistent results. Using the environment
591 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
592 the qemu binary at the same time as the handle is created.");
594 ("get_qemu", (RConstString "qemu", []), -1, [],
595 [InitNone, Always, TestRun (
597 "get the qemu binary",
599 Return the current qemu binary.
601 This is always non-NULL. If it wasn't set already, then this will
602 return the default qemu binary name.");
604 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
606 "set the search path",
608 Set the path that libguestfs searches for kernel and initrd.img.
610 The default is C<$libdir/guestfs> unless overridden by setting
611 C<LIBGUESTFS_PATH> environment variable.
613 Setting C<path> to C<NULL> restores the default path.");
615 ("get_path", (RConstString "path", []), -1, [],
616 [InitNone, Always, TestRun (
618 "get the search path",
620 Return the current search path.
622 This is always non-NULL. If it wasn't set already, then this will
623 return the default path.");
625 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
627 "add options to kernel command line",
629 This function is used to add additional options to the
630 guest kernel command line.
632 The default is C<NULL> unless overridden by setting
633 C<LIBGUESTFS_APPEND> environment variable.
635 Setting C<append> to C<NULL> means I<no> additional options
636 are passed (libguestfs always adds a few of its own).");
638 ("get_append", (RConstOptString "append", []), -1, [],
639 (* This cannot be tested with the current framework. The
640 * function can return NULL in normal operations, which the
641 * test framework interprets as an error.
644 "get the additional kernel options",
646 Return the additional kernel options which are added to the
647 guest kernel command line.
649 If C<NULL> then no options are added.");
651 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655 If C<autosync> is true, this enables autosync. Libguestfs will make a
656 best effort attempt to run C<guestfs_umount_all> followed by
657 C<guestfs_sync> when the handle is closed
658 (also if the program exits without closing handles).
660 This is disabled by default (except in guestfish where it is
661 enabled by default).");
663 ("get_autosync", (RBool "autosync", []), -1, [],
664 [InitNone, Always, TestRun (
665 [["get_autosync"]])],
668 Get the autosync flag.");
670 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
676 Verbose messages are disabled unless the environment variable
677 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
679 ("get_verbose", (RBool "verbose", []), -1, [],
683 This returns the verbose messages flag.");
685 ("is_ready", (RBool "ready", []), -1, [],
686 [InitNone, Always, TestOutputTrue (
688 "is ready to accept commands",
690 This returns true iff this handle is ready to accept commands
691 (in the C<READY> state).
693 For more information on states, see L<guestfs(3)>.");
695 ("is_config", (RBool "config", []), -1, [],
696 [InitNone, Always, TestOutputFalse (
698 "is in configuration state",
700 This returns true iff this handle is being configured
701 (in the C<CONFIG> state).
703 For more information on states, see L<guestfs(3)>.");
705 ("is_launching", (RBool "launching", []), -1, [],
706 [InitNone, Always, TestOutputFalse (
707 [["is_launching"]])],
708 "is launching subprocess",
710 This returns true iff this handle is launching the subprocess
711 (in the C<LAUNCHING> state).
713 For more information on states, see L<guestfs(3)>.");
715 ("is_busy", (RBool "busy", []), -1, [],
716 [InitNone, Always, TestOutputFalse (
718 "is busy processing a command",
720 This returns true iff this handle is busy processing a command
721 (in the C<BUSY> state).
723 For more information on states, see L<guestfs(3)>.");
725 ("get_state", (RInt "state", []), -1, [],
727 "get the current state",
729 This returns the current state as an opaque integer. This is
730 only useful for printing debug and internal error messages.
732 For more information on states, see L<guestfs(3)>.");
734 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
735 [InitNone, Always, TestOutputInt (
736 [["set_memsize"; "500"];
737 ["get_memsize"]], 500)],
738 "set memory allocated to the qemu subprocess",
740 This sets the memory size in megabytes allocated to the
741 qemu subprocess. This only has any effect if called before
744 You can also change this by setting the environment
745 variable C<LIBGUESTFS_MEMSIZE> before the handle is
748 For more information on the architecture of libguestfs,
749 see L<guestfs(3)>.");
751 ("get_memsize", (RInt "memsize", []), -1, [],
752 [InitNone, Always, TestOutputIntOp (
753 [["get_memsize"]], ">=", 256)],
754 "get memory allocated to the qemu subprocess",
756 This gets the memory size in megabytes allocated to the
759 If C<guestfs_set_memsize> was not called
760 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
761 then this returns the compiled-in default value for memsize.
763 For more information on the architecture of libguestfs,
764 see L<guestfs(3)>.");
766 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
767 [InitNone, Always, TestOutputIntOp (
768 [["get_pid"]], ">=", 1)],
769 "get PID of qemu subprocess",
771 Return the process ID of the qemu subprocess. If there is no
772 qemu subprocess, then this will return an error.
774 This is an internal call used for debugging and testing.");
776 ("version", (RStruct ("version", "version"), []), -1, [],
777 [InitNone, Always, TestOutputStruct (
778 [["version"]], [CompareWithInt ("major", 1)])],
779 "get the library version number",
781 Return the libguestfs version number that the program is linked
784 Note that because of dynamic linking this is not necessarily
785 the version of libguestfs that you compiled against. You can
786 compile the program, and then at runtime dynamically link
787 against a completely different C<libguestfs.so> library.
789 This call was added in version C<1.0.58>. In previous
790 versions of libguestfs there was no way to get the version
791 number. From C code you can use ELF weak linking tricks to find out if
792 this symbol exists (if it doesn't, then it's an earlier version).
794 The call returns a structure with four elements. The first
795 three (C<major>, C<minor> and C<release>) are numbers and
796 correspond to the usual version triplet. The fourth element
797 (C<extra>) is a string and is normally empty, but may be
798 used for distro-specific information.
800 To construct the original version string:
801 C<$major.$minor.$release$extra>
803 I<Note:> Don't use this call to test for availability
804 of features. Distro backports makes this unreliable. Use
805 C<guestfs_available> instead.");
807 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
808 [InitNone, Always, TestOutputTrue (
809 [["set_selinux"; "true"];
811 "set SELinux enabled or disabled at appliance boot",
813 This sets the selinux flag that is passed to the appliance
814 at boot time. The default is C<selinux=0> (disabled).
816 Note that if SELinux is enabled, it is always in
817 Permissive mode (C<enforcing=0>).
819 For more information on the architecture of libguestfs,
820 see L<guestfs(3)>.");
822 ("get_selinux", (RBool "selinux", []), -1, [],
824 "get SELinux enabled flag",
826 This returns the current setting of the selinux flag which
827 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
829 For more information on the architecture of libguestfs,
830 see L<guestfs(3)>.");
832 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
833 [InitNone, Always, TestOutputFalse (
834 [["set_trace"; "false"];
836 "enable or disable command traces",
838 If the command trace flag is set to 1, then commands are
839 printed on stdout before they are executed in a format
840 which is very similar to the one used by guestfish. In
841 other words, you can run a program with this enabled, and
842 you will get out a script which you can feed to guestfish
843 to perform the same set of actions.
845 If you want to trace C API calls into libguestfs (and
846 other libraries) then possibly a better way is to use
847 the external ltrace(1) command.
849 Command traces are disabled unless the environment variable
850 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
852 ("get_trace", (RBool "trace", []), -1, [],
854 "get command trace enabled flag",
856 Return the command trace flag.");
858 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
859 [InitNone, Always, TestOutputFalse (
860 [["set_direct"; "false"];
862 "enable or disable direct appliance mode",
864 If the direct appliance mode flag is enabled, then stdin and
865 stdout are passed directly through to the appliance once it
868 One consequence of this is that log messages aren't caught
869 by the library and handled by C<guestfs_set_log_message_callback>,
870 but go straight to stdout.
872 You probably don't want to use this unless you know what you
875 The default is disabled.");
877 ("get_direct", (RBool "direct", []), -1, [],
879 "get direct appliance mode flag",
881 Return the direct appliance mode flag.");
883 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
884 [InitNone, Always, TestOutputTrue (
885 [["set_recovery_proc"; "true"];
886 ["get_recovery_proc"]])],
887 "enable or disable the recovery process",
889 If this is called with the parameter C<false> then
890 C<guestfs_launch> does not create a recovery process. The
891 purpose of the recovery process is to stop runaway qemu
892 processes in the case where the main program aborts abruptly.
894 This only has any effect if called before C<guestfs_launch>,
895 and the default is true.
897 About the only time when you would want to disable this is
898 if the main process will fork itself into the background
899 (\"daemonize\" itself). In this case the recovery process
900 thinks that the main program has disappeared and so kills
901 qemu, which is not very helpful.");
903 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
905 "get recovery process enabled flag",
907 Return the recovery process enabled flag.");
909 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
911 "add a drive specifying the QEMU block emulation to use",
913 This is the same as C<guestfs_add_drive> but it allows you
914 to specify the QEMU interface emulation to use at run time.");
916 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918 "add a drive read-only specifying the QEMU block emulation to use",
920 This is the same as C<guestfs_add_drive_ro> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
925 (* daemon_functions are any functions which cause some action
926 * to take place in the daemon.
929 let daemon_functions = [
930 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
931 [InitEmpty, Always, TestOutput (
932 [["part_disk"; "/dev/sda"; "mbr"];
933 ["mkfs"; "ext2"; "/dev/sda1"];
934 ["mount"; "/dev/sda1"; "/"];
935 ["write_file"; "/new"; "new file contents"; "0"];
936 ["cat"; "/new"]], "new file contents")],
937 "mount a guest disk at a position in the filesystem",
939 Mount a guest disk at a position in the filesystem. Block devices
940 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
941 the guest. If those block devices contain partitions, they will have
942 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
945 The rules are the same as for L<mount(2)>: A filesystem must
946 first be mounted on C</> before others can be mounted. Other
947 filesystems can only be mounted on directories which already
950 The mounted filesystem is writable, if we have sufficient permissions
951 on the underlying device.
953 The filesystem options C<sync> and C<noatime> are set with this
954 call, in order to improve reliability.");
956 ("sync", (RErr, []), 2, [],
957 [ InitEmpty, Always, TestRun [["sync"]]],
958 "sync disks, writes are flushed through to the disk image",
960 This syncs the disk, so that any writes are flushed through to the
961 underlying disk image.
963 You should always call this if you have modified a disk image, before
964 closing the handle.");
966 ("touch", (RErr, [Pathname "path"]), 3, [],
967 [InitBasicFS, Always, TestOutputTrue (
969 ["exists"; "/new"]])],
970 "update file timestamps or create a new file",
972 Touch acts like the L<touch(1)> command. It can be used to
973 update the timestamps on a file, or, if the file does not exist,
974 to create a new zero-length file.");
976 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
977 [InitISOFS, Always, TestOutput (
978 [["cat"; "/known-2"]], "abcdef\n")],
979 "list the contents of a file",
981 Return the contents of the file named C<path>.
983 Note that this function cannot correctly handle binary files
984 (specifically, files containing C<\\0> character which is treated
985 as end of string). For those you need to use the C<guestfs_read_file>
986 or C<guestfs_download> functions which have a more complex interface.");
988 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
989 [], (* XXX Tricky to test because it depends on the exact format
990 * of the 'ls -l' command, which changes between F10 and F11.
992 "list the files in a directory (long format)",
994 List the files in C<directory> (relative to the root directory,
995 there is no cwd) in the format of 'ls -la'.
997 This command is mostly useful for interactive sessions. It
998 is I<not> intended that you try to parse the output string.");
1000 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1001 [InitBasicFS, Always, TestOutputList (
1003 ["touch"; "/newer"];
1004 ["touch"; "/newest"];
1005 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1006 "list the files in a directory",
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd). The '.' and '..' entries are not returned, but
1010 hidden files are shown.
1012 This command is mostly useful for interactive sessions. Programs
1013 should probably use C<guestfs_readdir> instead.");
1015 ("list_devices", (RStringList "devices", []), 7, [],
1016 [InitEmpty, Always, TestOutputListOfDevices (
1017 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1018 "list the block devices",
1020 List all the block devices.
1022 The full block device names are returned, eg. C</dev/sda>");
1024 ("list_partitions", (RStringList "partitions", []), 8, [],
1025 [InitBasicFS, Always, TestOutputListOfDevices (
1026 [["list_partitions"]], ["/dev/sda1"]);
1027 InitEmpty, Always, TestOutputListOfDevices (
1028 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1029 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1030 "list the partitions",
1032 List all the partitions detected on all block devices.
1034 The full partition device names are returned, eg. C</dev/sda1>
1036 This does not return logical volumes. For that you will need to
1037 call C<guestfs_lvs>.");
1039 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1040 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1041 [["pvs"]], ["/dev/sda1"]);
1042 InitEmpty, Always, TestOutputListOfDevices (
1043 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044 ["pvcreate"; "/dev/sda1"];
1045 ["pvcreate"; "/dev/sda2"];
1046 ["pvcreate"; "/dev/sda3"];
1047 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048 "list the LVM physical volumes (PVs)",
1050 List all the physical volumes detected. This is the equivalent
1051 of the L<pvs(8)> command.
1053 This returns a list of just the device names that contain
1054 PVs (eg. C</dev/sda2>).
1056 See also C<guestfs_pvs_full>.");
1058 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1059 [InitBasicFSonLVM, Always, TestOutputList (
1061 InitEmpty, Always, TestOutputList (
1062 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1063 ["pvcreate"; "/dev/sda1"];
1064 ["pvcreate"; "/dev/sda2"];
1065 ["pvcreate"; "/dev/sda3"];
1066 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1067 ["vgcreate"; "VG2"; "/dev/sda3"];
1068 ["vgs"]], ["VG1"; "VG2"])],
1069 "list the LVM volume groups (VGs)",
1071 List all the volumes groups detected. This is the equivalent
1072 of the L<vgs(8)> command.
1074 This returns a list of just the volume group names that were
1075 detected (eg. C<VolGroup00>).
1077 See also C<guestfs_vgs_full>.");
1079 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1080 [InitBasicFSonLVM, Always, TestOutputList (
1081 [["lvs"]], ["/dev/VG/LV"]);
1082 InitEmpty, Always, TestOutputList (
1083 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1084 ["pvcreate"; "/dev/sda1"];
1085 ["pvcreate"; "/dev/sda2"];
1086 ["pvcreate"; "/dev/sda3"];
1087 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1088 ["vgcreate"; "VG2"; "/dev/sda3"];
1089 ["lvcreate"; "LV1"; "VG1"; "50"];
1090 ["lvcreate"; "LV2"; "VG1"; "50"];
1091 ["lvcreate"; "LV3"; "VG2"; "50"];
1092 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1093 "list the LVM logical volumes (LVs)",
1095 List all the logical volumes detected. This is the equivalent
1096 of the L<lvs(8)> command.
1098 This returns a list of the logical volume device names
1099 (eg. C</dev/VolGroup00/LogVol00>).
1101 See also C<guestfs_lvs_full>.");
1103 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1104 [], (* XXX how to test? *)
1105 "list the LVM physical volumes (PVs)",
1107 List all the physical volumes detected. This is the equivalent
1108 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1110 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1111 [], (* XXX how to test? *)
1112 "list the LVM volume groups (VGs)",
1114 List all the volumes groups detected. This is the equivalent
1115 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1117 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1118 [], (* XXX how to test? *)
1119 "list the LVM logical volumes (LVs)",
1121 List all the logical volumes detected. This is the equivalent
1122 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1124 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1125 [InitISOFS, Always, TestOutputList (
1126 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1127 InitISOFS, Always, TestOutputList (
1128 [["read_lines"; "/empty"]], [])],
1129 "read file as lines",
1131 Return the contents of the file named C<path>.
1133 The file contents are returned as a list of lines. Trailing
1134 C<LF> and C<CRLF> character sequences are I<not> returned.
1136 Note that this function cannot correctly handle binary files
1137 (specifically, files containing C<\\0> character which is treated
1138 as end of line). For those you need to use the C<guestfs_read_file>
1139 function which has a more complex interface.");
1141 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1142 [], (* XXX Augeas code needs tests. *)
1143 "create a new Augeas handle",
1145 Create a new Augeas handle for editing configuration files.
1146 If there was any previous Augeas handle associated with this
1147 guestfs session, then it is closed.
1149 You must call this before using any other C<guestfs_aug_*>
1152 C<root> is the filesystem root. C<root> must not be NULL,
1155 The flags are the same as the flags defined in
1156 E<lt>augeas.hE<gt>, the logical I<or> of the following
1161 =item C<AUG_SAVE_BACKUP> = 1
1163 Keep the original file with a C<.augsave> extension.
1165 =item C<AUG_SAVE_NEWFILE> = 2
1167 Save changes into a file with extension C<.augnew>, and
1168 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1170 =item C<AUG_TYPE_CHECK> = 4
1172 Typecheck lenses (can be expensive).
1174 =item C<AUG_NO_STDINC> = 8
1176 Do not use standard load path for modules.
1178 =item C<AUG_SAVE_NOOP> = 16
1180 Make save a no-op, just record what would have been changed.
1182 =item C<AUG_NO_LOAD> = 32
1184 Do not load the tree in C<guestfs_aug_init>.
1188 To close the handle, you can call C<guestfs_aug_close>.
1190 To find out more about Augeas, see L<http://augeas.net/>.");
1192 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1193 [], (* XXX Augeas code needs tests. *)
1194 "close the current Augeas handle",
1196 Close the current Augeas handle and free up any resources
1197 used by it. After calling this, you have to call
1198 C<guestfs_aug_init> again before you can use any other
1199 Augeas functions.");
1201 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1202 [], (* XXX Augeas code needs tests. *)
1203 "define an Augeas variable",
1205 Defines an Augeas variable C<name> whose value is the result
1206 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1209 On success this returns the number of nodes in C<expr>, or
1210 C<0> if C<expr> evaluates to something which is not a nodeset.");
1212 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1213 [], (* XXX Augeas code needs tests. *)
1214 "define an Augeas node",
1216 Defines a variable C<name> whose value is the result of
1219 If C<expr> evaluates to an empty nodeset, a node is created,
1220 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1221 C<name> will be the nodeset containing that single node.
1223 On success this returns a pair containing the
1224 number of nodes in the nodeset, and a boolean flag
1225 if a node was created.");
1227 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1228 [], (* XXX Augeas code needs tests. *)
1229 "look up the value of an Augeas path",
1231 Look up the value associated with C<path>. If C<path>
1232 matches exactly one node, the C<value> is returned.");
1234 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1235 [], (* XXX Augeas code needs tests. *)
1236 "set Augeas path to value",
1238 Set the value associated with C<path> to C<value>.");
1240 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1241 [], (* XXX Augeas code needs tests. *)
1242 "insert a sibling Augeas node",
1244 Create a new sibling C<label> for C<path>, inserting it into
1245 the tree before or after C<path> (depending on the boolean
1248 C<path> must match exactly one existing node in the tree, and
1249 C<label> must be a label, ie. not contain C</>, C<*> or end
1250 with a bracketed index C<[N]>.");
1252 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1253 [], (* XXX Augeas code needs tests. *)
1254 "remove an Augeas path",
1256 Remove C<path> and all of its children.
1258 On success this returns the number of entries which were removed.");
1260 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1261 [], (* XXX Augeas code needs tests. *)
1264 Move the node C<src> to C<dest>. C<src> must match exactly
1265 one node. C<dest> is overwritten if it exists.");
1267 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1268 [], (* XXX Augeas code needs tests. *)
1269 "return Augeas nodes which match augpath",
1271 Returns a list of paths which match the path expression C<path>.
1272 The returned paths are sufficiently qualified so that they match
1273 exactly one node in the current tree.");
1275 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1276 [], (* XXX Augeas code needs tests. *)
1277 "write all pending Augeas changes to disk",
1279 This writes all pending changes to disk.
1281 The flags which were passed to C<guestfs_aug_init> affect exactly
1282 how files are saved.");
1284 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1285 [], (* XXX Augeas code needs tests. *)
1286 "load files into the tree",
1288 Load files into the tree.
1290 See C<aug_load> in the Augeas documentation for the full gory
1293 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1294 [], (* XXX Augeas code needs tests. *)
1295 "list Augeas nodes under augpath",
1297 This is just a shortcut for listing C<guestfs_aug_match>
1298 C<path/*> and sorting the resulting nodes into alphabetical order.");
1300 ("rm", (RErr, [Pathname "path"]), 29, [],
1301 [InitBasicFS, Always, TestRun
1304 InitBasicFS, Always, TestLastFail
1306 InitBasicFS, Always, TestLastFail
1311 Remove the single file C<path>.");
1313 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1314 [InitBasicFS, Always, TestRun
1317 InitBasicFS, Always, TestLastFail
1318 [["rmdir"; "/new"]];
1319 InitBasicFS, Always, TestLastFail
1321 ["rmdir"; "/new"]]],
1322 "remove a directory",
1324 Remove the single directory C<path>.");
1326 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1327 [InitBasicFS, Always, TestOutputFalse
1329 ["mkdir"; "/new/foo"];
1330 ["touch"; "/new/foo/bar"];
1332 ["exists"; "/new"]]],
1333 "remove a file or directory recursively",
1335 Remove the file or directory C<path>, recursively removing the
1336 contents if its a directory. This is like the C<rm -rf> shell
1339 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1340 [InitBasicFS, Always, TestOutputTrue
1342 ["is_dir"; "/new"]];
1343 InitBasicFS, Always, TestLastFail
1344 [["mkdir"; "/new/foo/bar"]]],
1345 "create a directory",
1347 Create a directory named C<path>.");
1349 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1350 [InitBasicFS, Always, TestOutputTrue
1351 [["mkdir_p"; "/new/foo/bar"];
1352 ["is_dir"; "/new/foo/bar"]];
1353 InitBasicFS, Always, TestOutputTrue
1354 [["mkdir_p"; "/new/foo/bar"];
1355 ["is_dir"; "/new/foo"]];
1356 InitBasicFS, Always, TestOutputTrue
1357 [["mkdir_p"; "/new/foo/bar"];
1358 ["is_dir"; "/new"]];
1359 (* Regression tests for RHBZ#503133: *)
1360 InitBasicFS, Always, TestRun
1362 ["mkdir_p"; "/new"]];
1363 InitBasicFS, Always, TestLastFail
1365 ["mkdir_p"; "/new"]]],
1366 "create a directory and parents",
1368 Create a directory named C<path>, creating any parent directories
1369 as necessary. This is like the C<mkdir -p> shell command.");
1371 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1372 [], (* XXX Need stat command to test *)
1375 Change the mode (permissions) of C<path> to C<mode>. Only
1376 numeric modes are supported.
1378 I<Note>: When using this command from guestfish, C<mode>
1379 by default would be decimal, unless you prefix it with
1380 C<0> to get octal, ie. use C<0700> not C<700>.");
1382 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1383 [], (* XXX Need stat command to test *)
1384 "change file owner and group",
1386 Change the file owner to C<owner> and group to C<group>.
1388 Only numeric uid and gid are supported. If you want to use
1389 names, you will need to locate and parse the password file
1390 yourself (Augeas support makes this relatively easy).");
1392 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1393 [InitISOFS, Always, TestOutputTrue (
1394 [["exists"; "/empty"]]);
1395 InitISOFS, Always, TestOutputTrue (
1396 [["exists"; "/directory"]])],
1397 "test if file or directory exists",
1399 This returns C<true> if and only if there is a file, directory
1400 (or anything) with the given C<path> name.
1402 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1404 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1405 [InitISOFS, Always, TestOutputTrue (
1406 [["is_file"; "/known-1"]]);
1407 InitISOFS, Always, TestOutputFalse (
1408 [["is_file"; "/directory"]])],
1409 "test if file exists",
1411 This returns C<true> if and only if there is a file
1412 with the given C<path> name. Note that it returns false for
1413 other objects like directories.
1415 See also C<guestfs_stat>.");
1417 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1418 [InitISOFS, Always, TestOutputFalse (
1419 [["is_dir"; "/known-3"]]);
1420 InitISOFS, Always, TestOutputTrue (
1421 [["is_dir"; "/directory"]])],
1422 "test if file exists",
1424 This returns C<true> if and only if there is a directory
1425 with the given C<path> name. Note that it returns false for
1426 other objects like files.
1428 See also C<guestfs_stat>.");
1430 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1431 [InitEmpty, Always, TestOutputListOfDevices (
1432 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1433 ["pvcreate"; "/dev/sda1"];
1434 ["pvcreate"; "/dev/sda2"];
1435 ["pvcreate"; "/dev/sda3"];
1436 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1437 "create an LVM physical volume",
1439 This creates an LVM physical volume on the named C<device>,
1440 where C<device> should usually be a partition name such
1443 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1444 [InitEmpty, Always, TestOutputList (
1445 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446 ["pvcreate"; "/dev/sda1"];
1447 ["pvcreate"; "/dev/sda2"];
1448 ["pvcreate"; "/dev/sda3"];
1449 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1450 ["vgcreate"; "VG2"; "/dev/sda3"];
1451 ["vgs"]], ["VG1"; "VG2"])],
1452 "create an LVM volume group",
1454 This creates an LVM volume group called C<volgroup>
1455 from the non-empty list of physical volumes C<physvols>.");
1457 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1458 [InitEmpty, Always, TestOutputList (
1459 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1460 ["pvcreate"; "/dev/sda1"];
1461 ["pvcreate"; "/dev/sda2"];
1462 ["pvcreate"; "/dev/sda3"];
1463 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1464 ["vgcreate"; "VG2"; "/dev/sda3"];
1465 ["lvcreate"; "LV1"; "VG1"; "50"];
1466 ["lvcreate"; "LV2"; "VG1"; "50"];
1467 ["lvcreate"; "LV3"; "VG2"; "50"];
1468 ["lvcreate"; "LV4"; "VG2"; "50"];
1469 ["lvcreate"; "LV5"; "VG2"; "50"];
1471 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1472 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1473 "create an LVM volume group",
1475 This creates an LVM volume group called C<logvol>
1476 on the volume group C<volgroup>, with C<size> megabytes.");
1478 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1479 [InitEmpty, Always, TestOutput (
1480 [["part_disk"; "/dev/sda"; "mbr"];
1481 ["mkfs"; "ext2"; "/dev/sda1"];
1482 ["mount_options"; ""; "/dev/sda1"; "/"];
1483 ["write_file"; "/new"; "new file contents"; "0"];
1484 ["cat"; "/new"]], "new file contents")],
1485 "make a filesystem",
1487 This creates a filesystem on C<device> (usually a partition
1488 or LVM logical volume). The filesystem type is C<fstype>, for
1491 ("sfdisk", (RErr, [Device "device";
1492 Int "cyls"; Int "heads"; Int "sectors";
1493 StringList "lines"]), 43, [DangerWillRobinson],
1495 "create partitions on a block device",
1497 This is a direct interface to the L<sfdisk(8)> program for creating
1498 partitions on block devices.
1500 C<device> should be a block device, for example C</dev/sda>.
1502 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1503 and sectors on the device, which are passed directly to sfdisk as
1504 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1505 of these, then the corresponding parameter is omitted. Usually for
1506 'large' disks, you can just pass C<0> for these, but for small
1507 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1508 out the right geometry and you will need to tell it.
1510 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1511 information refer to the L<sfdisk(8)> manpage.
1513 To create a single partition occupying the whole disk, you would
1514 pass C<lines> as a single element list, when the single element being
1515 the string C<,> (comma).
1517 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1518 C<guestfs_part_init>");
1520 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1521 [InitBasicFS, Always, TestOutput (
1522 [["write_file"; "/new"; "new file contents"; "0"];
1523 ["cat"; "/new"]], "new file contents");
1524 InitBasicFS, Always, TestOutput (
1525 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1526 ["cat"; "/new"]], "\nnew file contents\n");
1527 InitBasicFS, Always, TestOutput (
1528 [["write_file"; "/new"; "\n\n"; "0"];
1529 ["cat"; "/new"]], "\n\n");
1530 InitBasicFS, Always, TestOutput (
1531 [["write_file"; "/new"; ""; "0"];
1532 ["cat"; "/new"]], "");
1533 InitBasicFS, Always, TestOutput (
1534 [["write_file"; "/new"; "\n\n\n"; "0"];
1535 ["cat"; "/new"]], "\n\n\n");
1536 InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "\n"; "0"];
1538 ["cat"; "/new"]], "\n")],
1541 This call creates a file called C<path>. The contents of the
1542 file is the string C<content> (which can contain any 8 bit data),
1543 with length C<size>.
1545 As a special case, if C<size> is C<0>
1546 then the length is calculated using C<strlen> (so in this case
1547 the content cannot contain embedded ASCII NULs).
1549 I<NB.> Owing to a bug, writing content containing ASCII NUL
1550 characters does I<not> work, even if the length is specified.
1551 We hope to resolve this bug in a future version. In the meantime
1552 use C<guestfs_upload>.");
1554 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1555 [InitEmpty, Always, TestOutputListOfDevices (
1556 [["part_disk"; "/dev/sda"; "mbr"];
1557 ["mkfs"; "ext2"; "/dev/sda1"];
1558 ["mount_options"; ""; "/dev/sda1"; "/"];
1559 ["mounts"]], ["/dev/sda1"]);
1560 InitEmpty, Always, TestOutputList (
1561 [["part_disk"; "/dev/sda"; "mbr"];
1562 ["mkfs"; "ext2"; "/dev/sda1"];
1563 ["mount_options"; ""; "/dev/sda1"; "/"];
1566 "unmount a filesystem",
1568 This unmounts the given filesystem. The filesystem may be
1569 specified either by its mountpoint (path) or the device which
1570 contains the filesystem.");
1572 ("mounts", (RStringList "devices", []), 46, [],
1573 [InitBasicFS, Always, TestOutputListOfDevices (
1574 [["mounts"]], ["/dev/sda1"])],
1575 "show mounted filesystems",
1577 This returns the list of currently mounted filesystems. It returns
1578 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1580 Some internal mounts are not shown.
1582 See also: C<guestfs_mountpoints>");
1584 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1585 [InitBasicFS, Always, TestOutputList (
1588 (* check that umount_all can unmount nested mounts correctly: *)
1589 InitEmpty, Always, TestOutputList (
1590 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1591 ["mkfs"; "ext2"; "/dev/sda1"];
1592 ["mkfs"; "ext2"; "/dev/sda2"];
1593 ["mkfs"; "ext2"; "/dev/sda3"];
1594 ["mount_options"; ""; "/dev/sda1"; "/"];
1596 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1597 ["mkdir"; "/mp1/mp2"];
1598 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1599 ["mkdir"; "/mp1/mp2/mp3"];
1602 "unmount all filesystems",
1604 This unmounts all mounted filesystems.
1606 Some internal mounts are not unmounted by this call.");
1608 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1610 "remove all LVM LVs, VGs and PVs",
1612 This command removes all LVM logical volumes, volume groups
1613 and physical volumes.");
1615 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1616 [InitISOFS, Always, TestOutput (
1617 [["file"; "/empty"]], "empty");
1618 InitISOFS, Always, TestOutput (
1619 [["file"; "/known-1"]], "ASCII text");
1620 InitISOFS, Always, TestLastFail (
1621 [["file"; "/notexists"]])],
1622 "determine file type",
1624 This call uses the standard L<file(1)> command to determine
1625 the type or contents of the file. This also works on devices,
1626 for example to find out whether a partition contains a filesystem.
1628 This call will also transparently look inside various types
1631 The exact command which runs is C<file -zbsL path>. Note in
1632 particular that the filename is not prepended to the output
1633 (the C<-b> option).");
1635 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1636 [InitBasicFS, Always, TestOutput (
1637 [["upload"; "test-command"; "/test-command"];
1638 ["chmod"; "0o755"; "/test-command"];
1639 ["command"; "/test-command 1"]], "Result1");
1640 InitBasicFS, Always, TestOutput (
1641 [["upload"; "test-command"; "/test-command"];
1642 ["chmod"; "0o755"; "/test-command"];
1643 ["command"; "/test-command 2"]], "Result2\n");
1644 InitBasicFS, Always, TestOutput (
1645 [["upload"; "test-command"; "/test-command"];
1646 ["chmod"; "0o755"; "/test-command"];
1647 ["command"; "/test-command 3"]], "\nResult3");
1648 InitBasicFS, Always, TestOutput (
1649 [["upload"; "test-command"; "/test-command"];
1650 ["chmod"; "0o755"; "/test-command"];
1651 ["command"; "/test-command 4"]], "\nResult4\n");
1652 InitBasicFS, Always, TestOutput (
1653 [["upload"; "test-command"; "/test-command"];
1654 ["chmod"; "0o755"; "/test-command"];
1655 ["command"; "/test-command 5"]], "\nResult5\n\n");
1656 InitBasicFS, Always, TestOutput (
1657 [["upload"; "test-command"; "/test-command"];
1658 ["chmod"; "0o755"; "/test-command"];
1659 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1660 InitBasicFS, Always, TestOutput (
1661 [["upload"; "test-command"; "/test-command"];
1662 ["chmod"; "0o755"; "/test-command"];
1663 ["command"; "/test-command 7"]], "");
1664 InitBasicFS, Always, TestOutput (
1665 [["upload"; "test-command"; "/test-command"];
1666 ["chmod"; "0o755"; "/test-command"];
1667 ["command"; "/test-command 8"]], "\n");
1668 InitBasicFS, Always, TestOutput (
1669 [["upload"; "test-command"; "/test-command"];
1670 ["chmod"; "0o755"; "/test-command"];
1671 ["command"; "/test-command 9"]], "\n\n");
1672 InitBasicFS, Always, TestOutput (
1673 [["upload"; "test-command"; "/test-command"];
1674 ["chmod"; "0o755"; "/test-command"];
1675 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1676 InitBasicFS, Always, TestOutput (
1677 [["upload"; "test-command"; "/test-command"];
1678 ["chmod"; "0o755"; "/test-command"];
1679 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1680 InitBasicFS, Always, TestLastFail (
1681 [["upload"; "test-command"; "/test-command"];
1682 ["chmod"; "0o755"; "/test-command"];
1683 ["command"; "/test-command"]])],
1684 "run a command from the guest filesystem",
1686 This call runs a command from the guest filesystem. The
1687 filesystem must be mounted, and must contain a compatible
1688 operating system (ie. something Linux, with the same
1689 or compatible processor architecture).
1691 The single parameter is an argv-style list of arguments.
1692 The first element is the name of the program to run.
1693 Subsequent elements are parameters. The list must be
1694 non-empty (ie. must contain a program name). Note that
1695 the command runs directly, and is I<not> invoked via
1696 the shell (see C<guestfs_sh>).
1698 The return value is anything printed to I<stdout> by
1701 If the command returns a non-zero exit status, then
1702 this function returns an error message. The error message
1703 string is the content of I<stderr> from the command.
1705 The C<$PATH> environment variable will contain at least
1706 C</usr/bin> and C</bin>. If you require a program from
1707 another location, you should provide the full path in the
1710 Shared libraries and data files required by the program
1711 must be available on filesystems which are mounted in the
1712 correct places. It is the caller's responsibility to ensure
1713 all filesystems that are needed are mounted at the right
1716 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1717 [InitBasicFS, Always, TestOutputList (
1718 [["upload"; "test-command"; "/test-command"];
1719 ["chmod"; "0o755"; "/test-command"];
1720 ["command_lines"; "/test-command 1"]], ["Result1"]);
1721 InitBasicFS, Always, TestOutputList (
1722 [["upload"; "test-command"; "/test-command"];
1723 ["chmod"; "0o755"; "/test-command"];
1724 ["command_lines"; "/test-command 2"]], ["Result2"]);
1725 InitBasicFS, Always, TestOutputList (
1726 [["upload"; "test-command"; "/test-command"];
1727 ["chmod"; "0o755"; "/test-command"];
1728 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1729 InitBasicFS, Always, TestOutputList (
1730 [["upload"; "test-command"; "/test-command"];
1731 ["chmod"; "0o755"; "/test-command"];
1732 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1733 InitBasicFS, Always, TestOutputList (
1734 [["upload"; "test-command"; "/test-command"];
1735 ["chmod"; "0o755"; "/test-command"];
1736 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1737 InitBasicFS, Always, TestOutputList (
1738 [["upload"; "test-command"; "/test-command"];
1739 ["chmod"; "0o755"; "/test-command"];
1740 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1741 InitBasicFS, Always, TestOutputList (
1742 [["upload"; "test-command"; "/test-command"];
1743 ["chmod"; "0o755"; "/test-command"];
1744 ["command_lines"; "/test-command 7"]], []);
1745 InitBasicFS, Always, TestOutputList (
1746 [["upload"; "test-command"; "/test-command"];
1747 ["chmod"; "0o755"; "/test-command"];
1748 ["command_lines"; "/test-command 8"]], [""]);
1749 InitBasicFS, Always, TestOutputList (
1750 [["upload"; "test-command"; "/test-command"];
1751 ["chmod"; "0o755"; "/test-command"];
1752 ["command_lines"; "/test-command 9"]], ["";""]);
1753 InitBasicFS, Always, TestOutputList (
1754 [["upload"; "test-command"; "/test-command"];
1755 ["chmod"; "0o755"; "/test-command"];
1756 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1757 InitBasicFS, Always, TestOutputList (
1758 [["upload"; "test-command"; "/test-command"];
1759 ["chmod"; "0o755"; "/test-command"];
1760 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1761 "run a command, returning lines",
1763 This is the same as C<guestfs_command>, but splits the
1764 result into a list of lines.
1766 See also: C<guestfs_sh_lines>");
1768 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1769 [InitISOFS, Always, TestOutputStruct (
1770 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1771 "get file information",
1773 Returns file information for the given C<path>.
1775 This is the same as the C<stat(2)> system call.");
1777 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1778 [InitISOFS, Always, TestOutputStruct (
1779 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1780 "get file information for a symbolic link",
1782 Returns file information for the given C<path>.
1784 This is the same as C<guestfs_stat> except that if C<path>
1785 is a symbolic link, then the link is stat-ed, not the file it
1788 This is the same as the C<lstat(2)> system call.");
1790 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1791 [InitISOFS, Always, TestOutputStruct (
1792 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1793 "get file system statistics",
1795 Returns file system statistics for any mounted file system.
1796 C<path> should be a file or directory in the mounted file system
1797 (typically it is the mount point itself, but it doesn't need to be).
1799 This is the same as the C<statvfs(2)> system call.");
1801 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1803 "get ext2/ext3/ext4 superblock details",
1805 This returns the contents of the ext2, ext3 or ext4 filesystem
1806 superblock on C<device>.
1808 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1809 manpage for more details. The list of fields returned isn't
1810 clearly defined, and depends on both the version of C<tune2fs>
1811 that libguestfs was built against, and the filesystem itself.");
1813 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1814 [InitEmpty, Always, TestOutputTrue (
1815 [["blockdev_setro"; "/dev/sda"];
1816 ["blockdev_getro"; "/dev/sda"]])],
1817 "set block device to read-only",
1819 Sets the block device named C<device> to read-only.
1821 This uses the L<blockdev(8)> command.");
1823 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1824 [InitEmpty, Always, TestOutputFalse (
1825 [["blockdev_setrw"; "/dev/sda"];
1826 ["blockdev_getro"; "/dev/sda"]])],
1827 "set block device to read-write",
1829 Sets the block device named C<device> to read-write.
1831 This uses the L<blockdev(8)> command.");
1833 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1834 [InitEmpty, Always, TestOutputTrue (
1835 [["blockdev_setro"; "/dev/sda"];
1836 ["blockdev_getro"; "/dev/sda"]])],
1837 "is block device set to read-only",
1839 Returns a boolean indicating if the block device is read-only
1840 (true if read-only, false if not).
1842 This uses the L<blockdev(8)> command.");
1844 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1845 [InitEmpty, Always, TestOutputInt (
1846 [["blockdev_getss"; "/dev/sda"]], 512)],
1847 "get sectorsize of block device",
1849 This returns the size of sectors on a block device.
1850 Usually 512, but can be larger for modern devices.
1852 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 This uses the L<blockdev(8)> command.");
1857 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1858 [InitEmpty, Always, TestOutputInt (
1859 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1860 "get blocksize of block device",
1862 This returns the block size of a device.
1864 (Note this is different from both I<size in blocks> and
1865 I<filesystem block size>).
1867 This uses the L<blockdev(8)> command.");
1869 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1871 "set blocksize of block device",
1873 This sets the block size of a device.
1875 (Note this is different from both I<size in blocks> and
1876 I<filesystem block size>).
1878 This uses the L<blockdev(8)> command.");
1880 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1881 [InitEmpty, Always, TestOutputInt (
1882 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1883 "get total size of device in 512-byte sectors",
1885 This returns the size of the device in units of 512-byte sectors
1886 (even if the sectorsize isn't 512 bytes ... weird).
1888 See also C<guestfs_blockdev_getss> for the real sector size of
1889 the device, and C<guestfs_blockdev_getsize64> for the more
1890 useful I<size in bytes>.
1892 This uses the L<blockdev(8)> command.");
1894 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1895 [InitEmpty, Always, TestOutputInt (
1896 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1897 "get total size of device in bytes",
1899 This returns the size of the device in bytes.
1901 See also C<guestfs_blockdev_getsz>.
1903 This uses the L<blockdev(8)> command.");
1905 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1906 [InitEmpty, Always, TestRun
1907 [["blockdev_flushbufs"; "/dev/sda"]]],
1908 "flush device buffers",
1910 This tells the kernel to flush internal buffers associated
1913 This uses the L<blockdev(8)> command.");
1915 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1916 [InitEmpty, Always, TestRun
1917 [["blockdev_rereadpt"; "/dev/sda"]]],
1918 "reread partition table",
1920 Reread the partition table on C<device>.
1922 This uses the L<blockdev(8)> command.");
1924 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1925 [InitBasicFS, Always, TestOutput (
1926 (* Pick a file from cwd which isn't likely to change. *)
1927 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1928 ["checksum"; "md5"; "/COPYING.LIB"]],
1929 Digest.to_hex (Digest.file "COPYING.LIB"))],
1930 "upload a file from the local machine",
1932 Upload local file C<filename> to C<remotefilename> on the
1935 C<filename> can also be a named pipe.
1937 See also C<guestfs_download>.");
1939 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1940 [InitBasicFS, Always, TestOutput (
1941 (* Pick a file from cwd which isn't likely to change. *)
1942 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1944 ["upload"; "testdownload.tmp"; "/upload"];
1945 ["checksum"; "md5"; "/upload"]],
1946 Digest.to_hex (Digest.file "COPYING.LIB"))],
1947 "download a file to the local machine",
1949 Download file C<remotefilename> and save it as C<filename>
1950 on the local machine.
1952 C<filename> can also be a named pipe.
1954 See also C<guestfs_upload>, C<guestfs_cat>.");
1956 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1957 [InitISOFS, Always, TestOutput (
1958 [["checksum"; "crc"; "/known-3"]], "2891671662");
1959 InitISOFS, Always, TestLastFail (
1960 [["checksum"; "crc"; "/notexists"]]);
1961 InitISOFS, Always, TestOutput (
1962 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1963 InitISOFS, Always, TestOutput (
1964 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1965 InitISOFS, Always, TestOutput (
1966 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1967 InitISOFS, Always, TestOutput (
1968 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1969 InitISOFS, Always, TestOutput (
1970 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1971 InitISOFS, Always, TestOutput (
1972 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1973 "compute MD5, SHAx or CRC checksum of file",
1975 This call computes the MD5, SHAx or CRC checksum of the
1978 The type of checksum to compute is given by the C<csumtype>
1979 parameter which must have one of the following values:
1985 Compute the cyclic redundancy check (CRC) specified by POSIX
1986 for the C<cksum> command.
1990 Compute the MD5 hash (using the C<md5sum> program).
1994 Compute the SHA1 hash (using the C<sha1sum> program).
1998 Compute the SHA224 hash (using the C<sha224sum> program).
2002 Compute the SHA256 hash (using the C<sha256sum> program).
2006 Compute the SHA384 hash (using the C<sha384sum> program).
2010 Compute the SHA512 hash (using the C<sha512sum> program).
2014 The checksum is returned as a printable string.");
2016 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2017 [InitBasicFS, Always, TestOutput (
2018 [["tar_in"; "../images/helloworld.tar"; "/"];
2019 ["cat"; "/hello"]], "hello\n")],
2020 "unpack tarfile to directory",
2022 This command uploads and unpacks local file C<tarfile> (an
2023 I<uncompressed> tar file) into C<directory>.
2025 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2027 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2029 "pack directory into tarfile",
2031 This command packs the contents of C<directory> and downloads
2032 it to local file C<tarfile>.
2034 To download a compressed tarball, use C<guestfs_tgz_out>.");
2036 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2037 [InitBasicFS, Always, TestOutput (
2038 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2039 ["cat"; "/hello"]], "hello\n")],
2040 "unpack compressed tarball to directory",
2042 This command uploads and unpacks local file C<tarball> (a
2043 I<gzip compressed> tar file) into C<directory>.
2045 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2047 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2049 "pack directory into compressed tarball",
2051 This command packs the contents of C<directory> and downloads
2052 it to local file C<tarball>.
2054 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2056 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2057 [InitBasicFS, Always, TestLastFail (
2059 ["mount_ro"; "/dev/sda1"; "/"];
2060 ["touch"; "/new"]]);
2061 InitBasicFS, Always, TestOutput (
2062 [["write_file"; "/new"; "data"; "0"];
2064 ["mount_ro"; "/dev/sda1"; "/"];
2065 ["cat"; "/new"]], "data")],
2066 "mount a guest disk, read-only",
2068 This is the same as the C<guestfs_mount> command, but it
2069 mounts the filesystem with the read-only (I<-o ro>) flag.");
2071 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2073 "mount a guest disk with mount options",
2075 This is the same as the C<guestfs_mount> command, but it
2076 allows you to set the mount options as for the
2077 L<mount(8)> I<-o> flag.");
2079 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2081 "mount a guest disk with mount options and vfstype",
2083 This is the same as the C<guestfs_mount> command, but it
2084 allows you to set both the mount options and the vfstype
2085 as for the L<mount(8)> I<-o> and I<-t> flags.");
2087 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2089 "debugging and internals",
2091 The C<guestfs_debug> command exposes some internals of
2092 C<guestfsd> (the guestfs daemon) that runs inside the
2095 There is no comprehensive help for this command. You have
2096 to look at the file C<daemon/debug.c> in the libguestfs source
2097 to find out what you can do.");
2099 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2100 [InitEmpty, Always, TestOutputList (
2101 [["part_disk"; "/dev/sda"; "mbr"];
2102 ["pvcreate"; "/dev/sda1"];
2103 ["vgcreate"; "VG"; "/dev/sda1"];
2104 ["lvcreate"; "LV1"; "VG"; "50"];
2105 ["lvcreate"; "LV2"; "VG"; "50"];
2106 ["lvremove"; "/dev/VG/LV1"];
2107 ["lvs"]], ["/dev/VG/LV2"]);
2108 InitEmpty, Always, TestOutputList (
2109 [["part_disk"; "/dev/sda"; "mbr"];
2110 ["pvcreate"; "/dev/sda1"];
2111 ["vgcreate"; "VG"; "/dev/sda1"];
2112 ["lvcreate"; "LV1"; "VG"; "50"];
2113 ["lvcreate"; "LV2"; "VG"; "50"];
2114 ["lvremove"; "/dev/VG"];
2116 InitEmpty, Always, TestOutputList (
2117 [["part_disk"; "/dev/sda"; "mbr"];
2118 ["pvcreate"; "/dev/sda1"];
2119 ["vgcreate"; "VG"; "/dev/sda1"];
2120 ["lvcreate"; "LV1"; "VG"; "50"];
2121 ["lvcreate"; "LV2"; "VG"; "50"];
2122 ["lvremove"; "/dev/VG"];
2124 "remove an LVM logical volume",
2126 Remove an LVM logical volume C<device>, where C<device> is
2127 the path to the LV, such as C</dev/VG/LV>.
2129 You can also remove all LVs in a volume group by specifying
2130 the VG name, C</dev/VG>.");
2132 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2133 [InitEmpty, Always, TestOutputList (
2134 [["part_disk"; "/dev/sda"; "mbr"];
2135 ["pvcreate"; "/dev/sda1"];
2136 ["vgcreate"; "VG"; "/dev/sda1"];
2137 ["lvcreate"; "LV1"; "VG"; "50"];
2138 ["lvcreate"; "LV2"; "VG"; "50"];
2141 InitEmpty, Always, TestOutputList (
2142 [["part_disk"; "/dev/sda"; "mbr"];
2143 ["pvcreate"; "/dev/sda1"];
2144 ["vgcreate"; "VG"; "/dev/sda1"];
2145 ["lvcreate"; "LV1"; "VG"; "50"];
2146 ["lvcreate"; "LV2"; "VG"; "50"];
2149 "remove an LVM volume group",
2151 Remove an LVM volume group C<vgname>, (for example C<VG>).
2153 This also forcibly removes all logical volumes in the volume
2156 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2157 [InitEmpty, Always, TestOutputListOfDevices (
2158 [["part_disk"; "/dev/sda"; "mbr"];
2159 ["pvcreate"; "/dev/sda1"];
2160 ["vgcreate"; "VG"; "/dev/sda1"];
2161 ["lvcreate"; "LV1"; "VG"; "50"];
2162 ["lvcreate"; "LV2"; "VG"; "50"];
2164 ["pvremove"; "/dev/sda1"];
2166 InitEmpty, Always, TestOutputListOfDevices (
2167 [["part_disk"; "/dev/sda"; "mbr"];
2168 ["pvcreate"; "/dev/sda1"];
2169 ["vgcreate"; "VG"; "/dev/sda1"];
2170 ["lvcreate"; "LV1"; "VG"; "50"];
2171 ["lvcreate"; "LV2"; "VG"; "50"];
2173 ["pvremove"; "/dev/sda1"];
2175 InitEmpty, Always, TestOutputListOfDevices (
2176 [["part_disk"; "/dev/sda"; "mbr"];
2177 ["pvcreate"; "/dev/sda1"];
2178 ["vgcreate"; "VG"; "/dev/sda1"];
2179 ["lvcreate"; "LV1"; "VG"; "50"];
2180 ["lvcreate"; "LV2"; "VG"; "50"];
2182 ["pvremove"; "/dev/sda1"];
2184 "remove an LVM physical volume",
2186 This wipes a physical volume C<device> so that LVM will no longer
2189 The implementation uses the C<pvremove> command which refuses to
2190 wipe physical volumes that contain any volume groups, so you have
2191 to remove those first.");
2193 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2194 [InitBasicFS, Always, TestOutput (
2195 [["set_e2label"; "/dev/sda1"; "testlabel"];
2196 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2197 "set the ext2/3/4 filesystem label",
2199 This sets the ext2/3/4 filesystem label of the filesystem on
2200 C<device> to C<label>. Filesystem labels are limited to
2203 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2204 to return the existing label on a filesystem.");
2206 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2208 "get the ext2/3/4 filesystem label",
2210 This returns the ext2/3/4 filesystem label of the filesystem on
2213 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2214 (let uuid = uuidgen () in
2215 [InitBasicFS, Always, TestOutput (
2216 [["set_e2uuid"; "/dev/sda1"; uuid];
2217 ["get_e2uuid"; "/dev/sda1"]], uuid);
2218 InitBasicFS, Always, TestOutput (
2219 [["set_e2uuid"; "/dev/sda1"; "clear"];
2220 ["get_e2uuid"; "/dev/sda1"]], "");
2221 (* We can't predict what UUIDs will be, so just check the commands run. *)
2222 InitBasicFS, Always, TestRun (
2223 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2224 InitBasicFS, Always, TestRun (
2225 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2226 "set the ext2/3/4 filesystem UUID",
2228 This sets the ext2/3/4 filesystem UUID of the filesystem on
2229 C<device> to C<uuid>. The format of the UUID and alternatives
2230 such as C<clear>, C<random> and C<time> are described in the
2231 L<tune2fs(8)> manpage.
2233 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2234 to return the existing UUID of a filesystem.");
2236 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2238 "get the ext2/3/4 filesystem UUID",
2240 This returns the ext2/3/4 filesystem UUID of the filesystem on
2243 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2244 [InitBasicFS, Always, TestOutputInt (
2245 [["umount"; "/dev/sda1"];
2246 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2247 InitBasicFS, Always, TestOutputInt (
2248 [["umount"; "/dev/sda1"];
2249 ["zero"; "/dev/sda1"];
2250 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2251 "run the filesystem checker",
2253 This runs the filesystem checker (fsck) on C<device> which
2254 should have filesystem type C<fstype>.
2256 The returned integer is the status. See L<fsck(8)> for the
2257 list of status codes from C<fsck>.
2265 Multiple status codes can be summed together.
2269 A non-zero return code can mean \"success\", for example if
2270 errors have been corrected on the filesystem.
2274 Checking or repairing NTFS volumes is not supported
2279 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2281 ("zero", (RErr, [Device "device"]), 85, [],
2282 [InitBasicFS, Always, TestOutput (
2283 [["umount"; "/dev/sda1"];
2284 ["zero"; "/dev/sda1"];
2285 ["file"; "/dev/sda1"]], "data")],
2286 "write zeroes to the device",
2288 This command writes zeroes over the first few blocks of C<device>.
2290 How many blocks are zeroed isn't specified (but it's I<not> enough
2291 to securely wipe the device). It should be sufficient to remove
2292 any partition tables, filesystem superblocks and so on.
2294 See also: C<guestfs_scrub_device>.");
2296 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2297 (* Test disabled because grub-install incompatible with virtio-blk driver.
2298 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2300 [InitBasicFS, Disabled, TestOutputTrue (
2301 [["grub_install"; "/"; "/dev/sda1"];
2302 ["is_dir"; "/boot"]])],
2305 This command installs GRUB (the Grand Unified Bootloader) on
2306 C<device>, with the root directory being C<root>.");
2308 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2309 [InitBasicFS, Always, TestOutput (
2310 [["write_file"; "/old"; "file content"; "0"];
2311 ["cp"; "/old"; "/new"];
2312 ["cat"; "/new"]], "file content");
2313 InitBasicFS, Always, TestOutputTrue (
2314 [["write_file"; "/old"; "file content"; "0"];
2315 ["cp"; "/old"; "/new"];
2316 ["is_file"; "/old"]]);
2317 InitBasicFS, Always, TestOutput (
2318 [["write_file"; "/old"; "file content"; "0"];
2320 ["cp"; "/old"; "/dir/new"];
2321 ["cat"; "/dir/new"]], "file content")],
2324 This copies a file from C<src> to C<dest> where C<dest> is
2325 either a destination filename or destination directory.");
2327 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2328 [InitBasicFS, Always, TestOutput (
2329 [["mkdir"; "/olddir"];
2330 ["mkdir"; "/newdir"];
2331 ["write_file"; "/olddir/file"; "file content"; "0"];
2332 ["cp_a"; "/olddir"; "/newdir"];
2333 ["cat"; "/newdir/olddir/file"]], "file content")],
2334 "copy a file or directory recursively",
2336 This copies a file or directory from C<src> to C<dest>
2337 recursively using the C<cp -a> command.");
2339 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2340 [InitBasicFS, Always, TestOutput (
2341 [["write_file"; "/old"; "file content"; "0"];
2342 ["mv"; "/old"; "/new"];
2343 ["cat"; "/new"]], "file content");
2344 InitBasicFS, Always, TestOutputFalse (
2345 [["write_file"; "/old"; "file content"; "0"];
2346 ["mv"; "/old"; "/new"];
2347 ["is_file"; "/old"]])],
2350 This moves a file from C<src> to C<dest> where C<dest> is
2351 either a destination filename or destination directory.");
2353 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2354 [InitEmpty, Always, TestRun (
2355 [["drop_caches"; "3"]])],
2356 "drop kernel page cache, dentries and inodes",
2358 This instructs the guest kernel to drop its page cache,
2359 and/or dentries and inode caches. The parameter C<whattodrop>
2360 tells the kernel what precisely to drop, see
2361 L<http://linux-mm.org/Drop_Caches>
2363 Setting C<whattodrop> to 3 should drop everything.
2365 This automatically calls L<sync(2)> before the operation,
2366 so that the maximum guest memory is freed.");
2368 ("dmesg", (RString "kmsgs", []), 91, [],
2369 [InitEmpty, Always, TestRun (
2371 "return kernel messages",
2373 This returns the kernel messages (C<dmesg> output) from
2374 the guest kernel. This is sometimes useful for extended
2375 debugging of problems.
2377 Another way to get the same information is to enable
2378 verbose messages with C<guestfs_set_verbose> or by setting
2379 the environment variable C<LIBGUESTFS_DEBUG=1> before
2380 running the program.");
2382 ("ping_daemon", (RErr, []), 92, [],
2383 [InitEmpty, Always, TestRun (
2384 [["ping_daemon"]])],
2385 "ping the guest daemon",
2387 This is a test probe into the guestfs daemon running inside
2388 the qemu subprocess. Calling this function checks that the
2389 daemon responds to the ping message, without affecting the daemon
2390 or attached block device(s) in any other way.");
2392 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2393 [InitBasicFS, Always, TestOutputTrue (
2394 [["write_file"; "/file1"; "contents of a file"; "0"];
2395 ["cp"; "/file1"; "/file2"];
2396 ["equal"; "/file1"; "/file2"]]);
2397 InitBasicFS, Always, TestOutputFalse (
2398 [["write_file"; "/file1"; "contents of a file"; "0"];
2399 ["write_file"; "/file2"; "contents of another file"; "0"];
2400 ["equal"; "/file1"; "/file2"]]);
2401 InitBasicFS, Always, TestLastFail (
2402 [["equal"; "/file1"; "/file2"]])],
2403 "test if two files have equal contents",
2405 This compares the two files C<file1> and C<file2> and returns
2406 true if their content is exactly equal, or false otherwise.
2408 The external L<cmp(1)> program is used for the comparison.");
2410 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2411 [InitISOFS, Always, TestOutputList (
2412 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2413 InitISOFS, Always, TestOutputList (
2414 [["strings"; "/empty"]], [])],
2415 "print the printable strings in a file",
2417 This runs the L<strings(1)> command on a file and returns
2418 the list of printable strings found.");
2420 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2421 [InitISOFS, Always, TestOutputList (
2422 [["strings_e"; "b"; "/known-5"]], []);
2423 InitBasicFS, Disabled, TestOutputList (
2424 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2425 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2426 "print the printable strings in a file",
2428 This is like the C<guestfs_strings> command, but allows you to
2429 specify the encoding.
2431 See the L<strings(1)> manpage for the full list of encodings.
2433 Commonly useful encodings are C<l> (lower case L) which will
2434 show strings inside Windows/x86 files.
2436 The returned strings are transcoded to UTF-8.");
2438 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2439 [InitISOFS, Always, TestOutput (
2440 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2441 (* Test for RHBZ#501888c2 regression which caused large hexdump
2442 * commands to segfault.
2444 InitISOFS, Always, TestRun (
2445 [["hexdump"; "/100krandom"]])],
2446 "dump a file in hexadecimal",
2448 This runs C<hexdump -C> on the given C<path>. The result is
2449 the human-readable, canonical hex dump of the file.");
2451 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2452 [InitNone, Always, TestOutput (
2453 [["part_disk"; "/dev/sda"; "mbr"];
2454 ["mkfs"; "ext3"; "/dev/sda1"];
2455 ["mount_options"; ""; "/dev/sda1"; "/"];
2456 ["write_file"; "/new"; "test file"; "0"];
2457 ["umount"; "/dev/sda1"];
2458 ["zerofree"; "/dev/sda1"];
2459 ["mount_options"; ""; "/dev/sda1"; "/"];
2460 ["cat"; "/new"]], "test file")],
2461 "zero unused inodes and disk blocks on ext2/3 filesystem",
2463 This runs the I<zerofree> program on C<device>. This program
2464 claims to zero unused inodes and disk blocks on an ext2/3
2465 filesystem, thus making it possible to compress the filesystem
2468 You should B<not> run this program if the filesystem is
2471 It is possible that using this program can damage the filesystem
2472 or data on the filesystem.");
2474 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2476 "resize an LVM physical volume",
2478 This resizes (expands or shrinks) an existing LVM physical
2479 volume to match the new size of the underlying device.");
2481 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2482 Int "cyls"; Int "heads"; Int "sectors";
2483 String "line"]), 99, [DangerWillRobinson],
2485 "modify a single partition on a block device",
2487 This runs L<sfdisk(8)> option to modify just the single
2488 partition C<n> (note: C<n> counts from 1).
2490 For other parameters, see C<guestfs_sfdisk>. You should usually
2491 pass C<0> for the cyls/heads/sectors parameters.
2493 See also: C<guestfs_part_add>");
2495 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2497 "display the partition table",
2499 This displays the partition table on C<device>, in the
2500 human-readable output of the L<sfdisk(8)> command. It is
2501 not intended to be parsed.
2503 See also: C<guestfs_part_list>");
2505 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2507 "display the kernel geometry",
2509 This displays the kernel's idea of the geometry of C<device>.
2511 The result is in human-readable format, and not designed to
2514 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2516 "display the disk geometry from the partition table",
2518 This displays the disk geometry of C<device> read from the
2519 partition table. Especially in the case where the underlying
2520 block device has been resized, this can be different from the
2521 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2523 The result is in human-readable format, and not designed to
2526 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2528 "activate or deactivate all volume groups",
2530 This command activates or (if C<activate> is false) deactivates
2531 all logical volumes in all volume groups.
2532 If activated, then they are made known to the
2533 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2534 then those devices disappear.
2536 This command is the same as running C<vgchange -a y|n>");
2538 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2540 "activate or deactivate some volume groups",
2542 This command activates or (if C<activate> is false) deactivates
2543 all logical volumes in the listed volume groups C<volgroups>.
2544 If activated, then they are made known to the
2545 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2546 then those devices disappear.
2548 This command is the same as running C<vgchange -a y|n volgroups...>
2550 Note that if C<volgroups> is an empty list then B<all> volume groups
2551 are activated or deactivated.");
2553 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2554 [InitNone, Always, TestOutput (
2555 [["part_disk"; "/dev/sda"; "mbr"];
2556 ["pvcreate"; "/dev/sda1"];
2557 ["vgcreate"; "VG"; "/dev/sda1"];
2558 ["lvcreate"; "LV"; "VG"; "10"];
2559 ["mkfs"; "ext2"; "/dev/VG/LV"];
2560 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2561 ["write_file"; "/new"; "test content"; "0"];
2563 ["lvresize"; "/dev/VG/LV"; "20"];
2564 ["e2fsck_f"; "/dev/VG/LV"];
2565 ["resize2fs"; "/dev/VG/LV"];
2566 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2567 ["cat"; "/new"]], "test content")],
2568 "resize an LVM logical volume",
2570 This resizes (expands or shrinks) an existing LVM logical
2571 volume to C<mbytes>. When reducing, data in the reduced part
2574 ("resize2fs", (RErr, [Device "device"]), 106, [],
2575 [], (* lvresize tests this *)
2576 "resize an ext2/ext3 filesystem",
2578 This resizes an ext2 or ext3 filesystem to match the size of
2579 the underlying device.
2581 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2582 on the C<device> before calling this command. For unknown reasons
2583 C<resize2fs> sometimes gives an error about this and sometimes not.
2584 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2585 calling this function.");
2587 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2588 [InitBasicFS, Always, TestOutputList (
2589 [["find"; "/"]], ["lost+found"]);
2590 InitBasicFS, Always, TestOutputList (
2594 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2595 InitBasicFS, Always, TestOutputList (
2596 [["mkdir_p"; "/a/b/c"];
2597 ["touch"; "/a/b/c/d"];
2598 ["find"; "/a/b/"]], ["c"; "c/d"])],
2599 "find all files and directories",
2601 This command lists out all files and directories, recursively,
2602 starting at C<directory>. It is essentially equivalent to
2603 running the shell command C<find directory -print> but some
2604 post-processing happens on the output, described below.
2606 This returns a list of strings I<without any prefix>. Thus
2607 if the directory structure was:
2613 then the returned list from C<guestfs_find> C</tmp> would be
2621 If C<directory> is not a directory, then this command returns
2624 The returned list is sorted.
2626 See also C<guestfs_find0>.");
2628 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2629 [], (* lvresize tests this *)
2630 "check an ext2/ext3 filesystem",
2632 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2633 filesystem checker on C<device>, noninteractively (C<-p>),
2634 even if the filesystem appears to be clean (C<-f>).
2636 This command is only needed because of C<guestfs_resize2fs>
2637 (q.v.). Normally you should use C<guestfs_fsck>.");
2639 ("sleep", (RErr, [Int "secs"]), 109, [],
2640 [InitNone, Always, TestRun (
2642 "sleep for some seconds",
2644 Sleep for C<secs> seconds.");
2646 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2647 [InitNone, Always, TestOutputInt (
2648 [["part_disk"; "/dev/sda"; "mbr"];
2649 ["mkfs"; "ntfs"; "/dev/sda1"];
2650 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2651 InitNone, Always, TestOutputInt (
2652 [["part_disk"; "/dev/sda"; "mbr"];
2653 ["mkfs"; "ext2"; "/dev/sda1"];
2654 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2655 "probe NTFS volume",
2657 This command runs the L<ntfs-3g.probe(8)> command which probes
2658 an NTFS C<device> for mountability. (Not all NTFS volumes can
2659 be mounted read-write, and some cannot be mounted at all).
2661 C<rw> is a boolean flag. Set it to true if you want to test
2662 if the volume can be mounted read-write. Set it to false if
2663 you want to test if the volume can be mounted read-only.
2665 The return value is an integer which C<0> if the operation
2666 would succeed, or some non-zero value documented in the
2667 L<ntfs-3g.probe(8)> manual page.");
2669 ("sh", (RString "output", [String "command"]), 111, [],
2670 [], (* XXX needs tests *)
2671 "run a command via the shell",
2673 This call runs a command from the guest filesystem via the
2676 This is like C<guestfs_command>, but passes the command to:
2678 /bin/sh -c \"command\"
2680 Depending on the guest's shell, this usually results in
2681 wildcards being expanded, shell expressions being interpolated
2684 All the provisos about C<guestfs_command> apply to this call.");
2686 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2687 [], (* XXX needs tests *)
2688 "run a command via the shell returning lines",
2690 This is the same as C<guestfs_sh>, but splits the result
2691 into a list of lines.
2693 See also: C<guestfs_command_lines>");
2695 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2696 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2697 * code in stubs.c, since all valid glob patterns must start with "/".
2698 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2700 [InitBasicFS, Always, TestOutputList (
2701 [["mkdir_p"; "/a/b/c"];
2702 ["touch"; "/a/b/c/d"];
2703 ["touch"; "/a/b/c/e"];
2704 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2705 InitBasicFS, Always, TestOutputList (
2706 [["mkdir_p"; "/a/b/c"];
2707 ["touch"; "/a/b/c/d"];
2708 ["touch"; "/a/b/c/e"];
2709 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710 InitBasicFS, Always, TestOutputList (
2711 [["mkdir_p"; "/a/b/c"];
2712 ["touch"; "/a/b/c/d"];
2713 ["touch"; "/a/b/c/e"];
2714 ["glob_expand"; "/a/*/x/*"]], [])],
2715 "expand a wildcard path",
2717 This command searches for all the pathnames matching
2718 C<pattern> according to the wildcard expansion rules
2721 If no paths match, then this returns an empty list
2722 (note: not an error).
2724 It is just a wrapper around the C L<glob(3)> function
2725 with flags C<GLOB_MARK|GLOB_BRACE>.
2726 See that manual page for more details.");
2728 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2729 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2730 [["scrub_device"; "/dev/sdc"]])],
2731 "scrub (securely wipe) a device",
2733 This command writes patterns over C<device> to make data retrieval
2736 It is an interface to the L<scrub(1)> program. See that
2737 manual page for more details.");
2739 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2740 [InitBasicFS, Always, TestRun (
2741 [["write_file"; "/file"; "content"; "0"];
2742 ["scrub_file"; "/file"]])],
2743 "scrub (securely wipe) a file",
2745 This command writes patterns over a file to make data retrieval
2748 The file is I<removed> after scrubbing.
2750 It is an interface to the L<scrub(1)> program. See that
2751 manual page for more details.");
2753 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2754 [], (* XXX needs testing *)
2755 "scrub (securely wipe) free space",
2757 This command creates the directory C<dir> and then fills it
2758 with files until the filesystem is full, and scrubs the files
2759 as for C<guestfs_scrub_file>, and deletes them.
2760 The intention is to scrub any free space on the partition
2763 It is an interface to the L<scrub(1)> program. See that
2764 manual page for more details.");
2766 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2767 [InitBasicFS, Always, TestRun (
2769 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2770 "create a temporary directory",
2772 This command creates a temporary directory. The
2773 C<template> parameter should be a full pathname for the
2774 temporary directory name with the final six characters being
2777 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2778 the second one being suitable for Windows filesystems.
2780 The name of the temporary directory that was created
2783 The temporary directory is created with mode 0700
2784 and is owned by root.
2786 The caller is responsible for deleting the temporary
2787 directory and its contents after use.
2789 See also: L<mkdtemp(3)>");
2791 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2792 [InitISOFS, Always, TestOutputInt (
2793 [["wc_l"; "/10klines"]], 10000)],
2794 "count lines in a file",
2796 This command counts the lines in a file, using the
2797 C<wc -l> external command.");
2799 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2800 [InitISOFS, Always, TestOutputInt (
2801 [["wc_w"; "/10klines"]], 10000)],
2802 "count words in a file",
2804 This command counts the words in a file, using the
2805 C<wc -w> external command.");
2807 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2808 [InitISOFS, Always, TestOutputInt (
2809 [["wc_c"; "/100kallspaces"]], 102400)],
2810 "count characters in a file",
2812 This command counts the characters in a file, using the
2813 C<wc -c> external command.");
2815 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2816 [InitISOFS, Always, TestOutputList (
2817 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2818 "return first 10 lines of a file",
2820 This command returns up to the first 10 lines of a file as
2821 a list of strings.");
2823 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2824 [InitISOFS, Always, TestOutputList (
2825 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2826 InitISOFS, Always, TestOutputList (
2827 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2828 InitISOFS, Always, TestOutputList (
2829 [["head_n"; "0"; "/10klines"]], [])],
2830 "return first N lines of a file",
2832 If the parameter C<nrlines> is a positive number, this returns the first
2833 C<nrlines> lines of the file C<path>.
2835 If the parameter C<nrlines> is a negative number, this returns lines
2836 from the file C<path>, excluding the last C<nrlines> lines.
2838 If the parameter C<nrlines> is zero, this returns an empty list.");
2840 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2841 [InitISOFS, Always, TestOutputList (
2842 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2843 "return last 10 lines of a file",
2845 This command returns up to the last 10 lines of a file as
2846 a list of strings.");
2848 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2849 [InitISOFS, Always, TestOutputList (
2850 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2851 InitISOFS, Always, TestOutputList (
2852 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2853 InitISOFS, Always, TestOutputList (
2854 [["tail_n"; "0"; "/10klines"]], [])],
2855 "return last N lines of a file",
2857 If the parameter C<nrlines> is a positive number, this returns the last
2858 C<nrlines> lines of the file C<path>.
2860 If the parameter C<nrlines> is a negative number, this returns lines
2861 from the file C<path>, starting with the C<-nrlines>th line.
2863 If the parameter C<nrlines> is zero, this returns an empty list.");
2865 ("df", (RString "output", []), 125, [],
2866 [], (* XXX Tricky to test because it depends on the exact format
2867 * of the 'df' command and other imponderables.
2869 "report file system disk space usage",
2871 This command runs the C<df> command to report disk space used.
2873 This command is mostly useful for interactive sessions. It
2874 is I<not> intended that you try to parse the output string.
2875 Use C<statvfs> from programs.");
2877 ("df_h", (RString "output", []), 126, [],
2878 [], (* XXX Tricky to test because it depends on the exact format
2879 * of the 'df' command and other imponderables.
2881 "report file system disk space usage (human readable)",
2883 This command runs the C<df -h> command to report disk space used
2884 in human-readable format.
2886 This command is mostly useful for interactive sessions. It
2887 is I<not> intended that you try to parse the output string.
2888 Use C<statvfs> from programs.");
2890 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2891 [InitISOFS, Always, TestOutputInt (
2892 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2893 "estimate file space usage",
2895 This command runs the C<du -s> command to estimate file space
2898 C<path> can be a file or a directory. If C<path> is a directory
2899 then the estimate includes the contents of the directory and all
2900 subdirectories (recursively).
2902 The result is the estimated size in I<kilobytes>
2903 (ie. units of 1024 bytes).");
2905 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2906 [InitISOFS, Always, TestOutputList (
2907 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2908 "list files in an initrd",
2910 This command lists out files contained in an initrd.
2912 The files are listed without any initial C</> character. The
2913 files are listed in the order they appear (not necessarily
2914 alphabetical). Directory names are listed as separate items.
2916 Old Linux kernels (2.4 and earlier) used a compressed ext2
2917 filesystem as initrd. We I<only> support the newer initramfs
2918 format (compressed cpio files).");
2920 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2922 "mount a file using the loop device",
2924 This command lets you mount C<file> (a filesystem image
2925 in a file) on a mount point. It is entirely equivalent to
2926 the command C<mount -o loop file mountpoint>.");
2928 ("mkswap", (RErr, [Device "device"]), 130, [],
2929 [InitEmpty, Always, TestRun (
2930 [["part_disk"; "/dev/sda"; "mbr"];
2931 ["mkswap"; "/dev/sda1"]])],
2932 "create a swap partition",
2934 Create a swap partition on C<device>.");
2936 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2937 [InitEmpty, Always, TestRun (
2938 [["part_disk"; "/dev/sda"; "mbr"];
2939 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2940 "create a swap partition with a label",
2942 Create a swap partition on C<device> with label C<label>.
2944 Note that you cannot attach a swap label to a block device
2945 (eg. C</dev/sda>), just to a partition. This appears to be
2946 a limitation of the kernel or swap tools.");
2948 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2949 (let uuid = uuidgen () in
2950 [InitEmpty, Always, TestRun (
2951 [["part_disk"; "/dev/sda"; "mbr"];
2952 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2953 "create a swap partition with an explicit UUID",
2955 Create a swap partition on C<device> with UUID C<uuid>.");
2957 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2958 [InitBasicFS, Always, TestOutputStruct (
2959 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2960 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2961 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2962 InitBasicFS, Always, TestOutputStruct (
2963 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2964 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2965 "make block, character or FIFO devices",
2967 This call creates block or character special devices, or
2968 named pipes (FIFOs).
2970 The C<mode> parameter should be the mode, using the standard
2971 constants. C<devmajor> and C<devminor> are the
2972 device major and minor numbers, only used when creating block
2973 and character special devices.");
2975 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2976 [InitBasicFS, Always, TestOutputStruct (
2977 [["mkfifo"; "0o777"; "/node"];
2978 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2979 "make FIFO (named pipe)",
2981 This call creates a FIFO (named pipe) called C<path> with
2982 mode C<mode>. It is just a convenient wrapper around
2983 C<guestfs_mknod>.");
2985 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2986 [InitBasicFS, Always, TestOutputStruct (
2987 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2988 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2989 "make block device node",
2991 This call creates a block device node called C<path> with
2992 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2993 It is just a convenient wrapper around C<guestfs_mknod>.");
2995 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2996 [InitBasicFS, Always, TestOutputStruct (
2997 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2998 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2999 "make char device node",
3001 This call creates a char device node called C<path> with
3002 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3003 It is just a convenient wrapper around C<guestfs_mknod>.");
3005 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3006 [], (* XXX umask is one of those stateful things that we should
3007 * reset between each test.
3009 "set file mode creation mask (umask)",
3011 This function sets the mask used for creating new files and
3012 device nodes to C<mask & 0777>.
3014 Typical umask values would be C<022> which creates new files
3015 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3016 C<002> which creates new files with permissions like
3017 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3019 The default umask is C<022>. This is important because it
3020 means that directories and device nodes will be created with
3021 C<0644> or C<0755> mode even if you specify C<0777>.
3023 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3025 This call returns the previous umask.");
3027 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3029 "read directories entries",
3031 This returns the list of directory entries in directory C<dir>.
3033 All entries in the directory are returned, including C<.> and
3034 C<..>. The entries are I<not> sorted, but returned in the same
3035 order as the underlying filesystem.
3037 Also this call returns basic file type information about each
3038 file. The C<ftyp> field will contain one of the following characters:
3076 The L<readdir(3)> returned a C<d_type> field with an
3081 This function is primarily intended for use by programs. To
3082 get a simple list of names, use C<guestfs_ls>. To get a printable
3083 directory for human consumption, use C<guestfs_ll>.");
3085 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3087 "create partitions on a block device",
3089 This is a simplified interface to the C<guestfs_sfdisk>
3090 command, where partition sizes are specified in megabytes
3091 only (rounded to the nearest cylinder) and you don't need
3092 to specify the cyls, heads and sectors parameters which
3093 were rarely if ever used anyway.
3095 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3096 and C<guestfs_part_disk>");
3098 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3100 "determine file type inside a compressed file",
3102 This command runs C<file> after first decompressing C<path>
3105 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3107 Since 1.0.63, use C<guestfs_file> instead which can now
3108 process compressed files.");
3110 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3112 "list extended attributes of a file or directory",
3114 This call lists the extended attributes of the file or directory
3117 At the system call level, this is a combination of the
3118 L<listxattr(2)> and L<getxattr(2)> calls.
3120 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3122 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3124 "list extended attributes of a file or directory",
3126 This is the same as C<guestfs_getxattrs>, but if C<path>
3127 is a symbolic link, then it returns the extended attributes
3128 of the link itself.");
3130 ("setxattr", (RErr, [String "xattr";
3131 String "val"; Int "vallen"; (* will be BufferIn *)
3132 Pathname "path"]), 143, [Optional "linuxxattrs"],
3134 "set extended attribute of a file or directory",
3136 This call sets the extended attribute named C<xattr>
3137 of the file C<path> to the value C<val> (of length C<vallen>).
3138 The value is arbitrary 8 bit data.
3140 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3142 ("lsetxattr", (RErr, [String "xattr";
3143 String "val"; Int "vallen"; (* will be BufferIn *)
3144 Pathname "path"]), 144, [Optional "linuxxattrs"],
3146 "set extended attribute of a file or directory",
3148 This is the same as C<guestfs_setxattr>, but if C<path>
3149 is a symbolic link, then it sets an extended attribute
3150 of the link itself.");
3152 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3154 "remove extended attribute of a file or directory",
3156 This call removes the extended attribute named C<xattr>
3157 of the file C<path>.
3159 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3161 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3163 "remove extended attribute of a file or directory",
3165 This is the same as C<guestfs_removexattr>, but if C<path>
3166 is a symbolic link, then it removes an extended attribute
3167 of the link itself.");
3169 ("mountpoints", (RHashtable "mps", []), 147, [],
3173 This call is similar to C<guestfs_mounts>. That call returns
3174 a list of devices. This one returns a hash table (map) of
3175 device name to directory where the device is mounted.");
3177 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3178 (* This is a special case: while you would expect a parameter
3179 * of type "Pathname", that doesn't work, because it implies
3180 * NEED_ROOT in the generated calling code in stubs.c, and
3181 * this function cannot use NEED_ROOT.
3184 "create a mountpoint",
3186 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3187 specialized calls that can be used to create extra mountpoints
3188 before mounting the first filesystem.
3190 These calls are I<only> necessary in some very limited circumstances,
3191 mainly the case where you want to mount a mix of unrelated and/or
3192 read-only filesystems together.
3194 For example, live CDs often contain a \"Russian doll\" nest of
3195 filesystems, an ISO outer layer, with a squashfs image inside, with
3196 an ext2/3 image inside that. You can unpack this as follows
3199 add-ro Fedora-11-i686-Live.iso
3202 mkmountpoint /squash
3205 mount-loop /cd/LiveOS/squashfs.img /squash
3206 mount-loop /squash/LiveOS/ext3fs.img /ext3
3208 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3210 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3212 "remove a mountpoint",
3214 This calls removes a mountpoint that was previously created
3215 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3216 for full details.");
3218 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3219 [InitISOFS, Always, TestOutputBuffer (
3220 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3223 This calls returns the contents of the file C<path> as a
3226 Unlike C<guestfs_cat>, this function can correctly
3227 handle files that contain embedded ASCII NUL characters.
3228 However unlike C<guestfs_download>, this function is limited
3229 in the total size of file that can be handled.");
3231 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3232 [InitISOFS, Always, TestOutputList (
3233 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3234 InitISOFS, Always, TestOutputList (
3235 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3236 "return lines matching a pattern",
3238 This calls the external C<grep> program and returns the
3241 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3242 [InitISOFS, Always, TestOutputList (
3243 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3244 "return lines matching a pattern",
3246 This calls the external C<egrep> program and returns the
3249 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3250 [InitISOFS, Always, TestOutputList (
3251 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3252 "return lines matching a pattern",
3254 This calls the external C<fgrep> program and returns the
3257 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3258 [InitISOFS, Always, TestOutputList (
3259 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3260 "return lines matching a pattern",
3262 This calls the external C<grep -i> program and returns the
3265 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3266 [InitISOFS, Always, TestOutputList (
3267 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3268 "return lines matching a pattern",
3270 This calls the external C<egrep -i> program and returns the
3273 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3274 [InitISOFS, Always, TestOutputList (
3275 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3276 "return lines matching a pattern",
3278 This calls the external C<fgrep -i> program and returns the
3281 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3282 [InitISOFS, Always, TestOutputList (
3283 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3284 "return lines matching a pattern",
3286 This calls the external C<zgrep> program and returns the
3289 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3290 [InitISOFS, Always, TestOutputList (
3291 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3292 "return lines matching a pattern",
3294 This calls the external C<zegrep> program and returns the
3297 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3298 [InitISOFS, Always, TestOutputList (
3299 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3300 "return lines matching a pattern",
3302 This calls the external C<zfgrep> program and returns the
3305 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3306 [InitISOFS, Always, TestOutputList (
3307 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3308 "return lines matching a pattern",
3310 This calls the external C<zgrep -i> program and returns the
3313 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3314 [InitISOFS, Always, TestOutputList (
3315 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3316 "return lines matching a pattern",
3318 This calls the external C<zegrep -i> program and returns the
3321 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3322 [InitISOFS, Always, TestOutputList (
3323 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3324 "return lines matching a pattern",
3326 This calls the external C<zfgrep -i> program and returns the
3329 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3330 [InitISOFS, Always, TestOutput (
3331 [["realpath"; "/../directory"]], "/directory")],
3332 "canonicalized absolute pathname",
3334 Return the canonicalized absolute pathname of C<path>. The
3335 returned path has no C<.>, C<..> or symbolic link path elements.");
3337 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3338 [InitBasicFS, Always, TestOutputStruct (
3341 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3342 "create a hard link",
3344 This command creates a hard link using the C<ln> command.");
3346 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3347 [InitBasicFS, Always, TestOutputStruct (
3350 ["ln_f"; "/a"; "/b"];
3351 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3352 "create a hard link",
3354 This command creates a hard link using the C<ln -f> command.
3355 The C<-f> option removes the link (C<linkname>) if it exists already.");
3357 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3358 [InitBasicFS, Always, TestOutputStruct (
3360 ["ln_s"; "a"; "/b"];
3361 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3362 "create a symbolic link",
3364 This command creates a symbolic link using the C<ln -s> command.");
3366 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3367 [InitBasicFS, Always, TestOutput (
3368 [["mkdir_p"; "/a/b"];
3369 ["touch"; "/a/b/c"];
3370 ["ln_sf"; "../d"; "/a/b/c"];
3371 ["readlink"; "/a/b/c"]], "../d")],
3372 "create a symbolic link",
3374 This command creates a symbolic link using the C<ln -sf> command,
3375 The C<-f> option removes the link (C<linkname>) if it exists already.");
3377 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3378 [] (* XXX tested above *),
3379 "read the target of a symbolic link",
3381 This command reads the target of a symbolic link.");
3383 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3384 [InitBasicFS, Always, TestOutputStruct (
3385 [["fallocate"; "/a"; "1000000"];
3386 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3387 "preallocate a file in the guest filesystem",
3389 This command preallocates a file (containing zero bytes) named
3390 C<path> of size C<len> bytes. If the file exists already, it
3393 Do not confuse this with the guestfish-specific
3394 C<alloc> command which allocates a file in the host and
3395 attaches it as a device.");
3397 ("swapon_device", (RErr, [Device "device"]), 170, [],
3398 [InitPartition, Always, TestRun (
3399 [["mkswap"; "/dev/sda1"];
3400 ["swapon_device"; "/dev/sda1"];
3401 ["swapoff_device"; "/dev/sda1"]])],
3402 "enable swap on device",
3404 This command enables the libguestfs appliance to use the
3405 swap device or partition named C<device>. The increased
3406 memory is made available for all commands, for example
3407 those run using C<guestfs_command> or C<guestfs_sh>.
3409 Note that you should not swap to existing guest swap
3410 partitions unless you know what you are doing. They may
3411 contain hibernation information, or other information that
3412 the guest doesn't want you to trash. You also risk leaking
3413 information about the host to the guest this way. Instead,
3414 attach a new host device to the guest and swap on that.");
3416 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3417 [], (* XXX tested by swapon_device *)
3418 "disable swap on device",
3420 This command disables the libguestfs appliance swap
3421 device or partition named C<device>.
3422 See C<guestfs_swapon_device>.");
3424 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3425 [InitBasicFS, Always, TestRun (
3426 [["fallocate"; "/swap"; "8388608"];
3427 ["mkswap_file"; "/swap"];
3428 ["swapon_file"; "/swap"];
3429 ["swapoff_file"; "/swap"]])],
3430 "enable swap on file",
3432 This command enables swap to a file.
3433 See C<guestfs_swapon_device> for other notes.");
3435 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3436 [], (* XXX tested by swapon_file *)
3437 "disable swap on file",
3439 This command disables the libguestfs appliance swap on file.");
3441 ("swapon_label", (RErr, [String "label"]), 174, [],
3442 [InitEmpty, Always, TestRun (
3443 [["part_disk"; "/dev/sdb"; "mbr"];
3444 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3445 ["swapon_label"; "swapit"];
3446 ["swapoff_label"; "swapit"];
3447 ["zero"; "/dev/sdb"];
3448 ["blockdev_rereadpt"; "/dev/sdb"]])],
3449 "enable swap on labeled swap partition",
3451 This command enables swap to a labeled swap partition.
3452 See C<guestfs_swapon_device> for other notes.");
3454 ("swapoff_label", (RErr, [String "label"]), 175, [],
3455 [], (* XXX tested by swapon_label *)
3456 "disable swap on labeled swap partition",
3458 This command disables the libguestfs appliance swap on
3459 labeled swap partition.");
3461 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3462 (let uuid = uuidgen () in
3463 [InitEmpty, Always, TestRun (
3464 [["mkswap_U"; uuid; "/dev/sdb"];
3465 ["swapon_uuid"; uuid];
3466 ["swapoff_uuid"; uuid]])]),
3467 "enable swap on swap partition by UUID",
3469 This command enables swap to a swap partition with the given UUID.
3470 See C<guestfs_swapon_device> for other notes.");
3472 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3473 [], (* XXX tested by swapon_uuid *)
3474 "disable swap on swap partition by UUID",
3476 This command disables the libguestfs appliance swap partition
3477 with the given UUID.");
3479 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3480 [InitBasicFS, Always, TestRun (
3481 [["fallocate"; "/swap"; "8388608"];
3482 ["mkswap_file"; "/swap"]])],
3483 "create a swap file",
3487 This command just writes a swap file signature to an existing
3488 file. To create the file itself, use something like C<guestfs_fallocate>.");
3490 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3491 [InitISOFS, Always, TestRun (
3492 [["inotify_init"; "0"]])],
3493 "create an inotify handle",
3495 This command creates a new inotify handle.
3496 The inotify subsystem can be used to notify events which happen to
3497 objects in the guest filesystem.
3499 C<maxevents> is the maximum number of events which will be
3500 queued up between calls to C<guestfs_inotify_read> or
3501 C<guestfs_inotify_files>.
3502 If this is passed as C<0>, then the kernel (or previously set)
3503 default is used. For Linux 2.6.29 the default was 16384 events.
3504 Beyond this limit, the kernel throws away events, but records
3505 the fact that it threw them away by setting a flag
3506 C<IN_Q_OVERFLOW> in the returned structure list (see
3507 C<guestfs_inotify_read>).
3509 Before any events are generated, you have to add some
3510 watches to the internal watch list. See:
3511 C<guestfs_inotify_add_watch>,
3512 C<guestfs_inotify_rm_watch> and
3513 C<guestfs_inotify_watch_all>.
3515 Queued up events should be read periodically by calling
3516 C<guestfs_inotify_read>
3517 (or C<guestfs_inotify_files> which is just a helpful
3518 wrapper around C<guestfs_inotify_read>). If you don't
3519 read the events out often enough then you risk the internal
3522 The handle should be closed after use by calling
3523 C<guestfs_inotify_close>. This also removes any
3524 watches automatically.
3526 See also L<inotify(7)> for an overview of the inotify interface
3527 as exposed by the Linux kernel, which is roughly what we expose
3528 via libguestfs. Note that there is one global inotify handle
3529 per libguestfs instance.");
3531 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3532 [InitBasicFS, Always, TestOutputList (
3533 [["inotify_init"; "0"];
3534 ["inotify_add_watch"; "/"; "1073741823"];
3537 ["inotify_files"]], ["a"; "b"])],
3538 "add an inotify watch",
3540 Watch C<path> for the events listed in C<mask>.
3542 Note that if C<path> is a directory then events within that
3543 directory are watched, but this does I<not> happen recursively
3544 (in subdirectories).
3546 Note for non-C or non-Linux callers: the inotify events are
3547 defined by the Linux kernel ABI and are listed in
3548 C</usr/include/sys/inotify.h>.");
3550 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3552 "remove an inotify watch",
3554 Remove a previously defined inotify watch.
3555 See C<guestfs_inotify_add_watch>.");
3557 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3559 "return list of inotify events",
3561 Return the complete queue of events that have happened
3562 since the previous read call.
3564 If no events have happened, this returns an empty list.
3566 I<Note>: In order to make sure that all events have been
3567 read, you must call this function repeatedly until it
3568 returns an empty list. The reason is that the call will
3569 read events up to the maximum appliance-to-host message
3570 size and leave remaining events in the queue.");
3572 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3574 "return list of watched files that had events",
3576 This function is a helpful wrapper around C<guestfs_inotify_read>
3577 which just returns a list of pathnames of objects that were
3578 touched. The returned pathnames are sorted and deduplicated.");
3580 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3582 "close the inotify handle",
3584 This closes the inotify handle which was previously
3585 opened by inotify_init. It removes all watches, throws
3586 away any pending events, and deallocates all resources.");
3588 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3590 "set SELinux security context",
3592 This sets the SELinux security context of the daemon
3593 to the string C<context>.
3595 See the documentation about SELINUX in L<guestfs(3)>.");
3597 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3599 "get SELinux security context",
3601 This gets the SELinux security context of the daemon.
3603 See the documentation about SELINUX in L<guestfs(3)>,
3604 and C<guestfs_setcon>");
3606 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3607 [InitEmpty, Always, TestOutput (
3608 [["part_disk"; "/dev/sda"; "mbr"];
3609 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3610 ["mount_options"; ""; "/dev/sda1"; "/"];
3611 ["write_file"; "/new"; "new file contents"; "0"];
3612 ["cat"; "/new"]], "new file contents")],
3613 "make a filesystem with block size",
3615 This call is similar to C<guestfs_mkfs>, but it allows you to
3616 control the block size of the resulting filesystem. Supported
3617 block sizes depend on the filesystem type, but typically they
3618 are C<1024>, C<2048> or C<4096> only.");
3620 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3621 [InitEmpty, Always, TestOutput (
3622 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3623 ["mke2journal"; "4096"; "/dev/sda1"];
3624 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3625 ["mount_options"; ""; "/dev/sda2"; "/"];
3626 ["write_file"; "/new"; "new file contents"; "0"];
3627 ["cat"; "/new"]], "new file contents")],
3628 "make ext2/3/4 external journal",
3630 This creates an ext2 external journal on C<device>. It is equivalent
3633 mke2fs -O journal_dev -b blocksize device");
3635 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3636 [InitEmpty, Always, TestOutput (
3637 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3638 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3639 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3640 ["mount_options"; ""; "/dev/sda2"; "/"];
3641 ["write_file"; "/new"; "new file contents"; "0"];
3642 ["cat"; "/new"]], "new file contents")],
3643 "make ext2/3/4 external journal with label",
3645 This creates an ext2 external journal on C<device> with label C<label>.");
3647 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3648 (let uuid = uuidgen () in
3649 [InitEmpty, Always, TestOutput (
3650 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3651 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3652 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3653 ["mount_options"; ""; "/dev/sda2"; "/"];
3654 ["write_file"; "/new"; "new file contents"; "0"];
3655 ["cat"; "/new"]], "new file contents")]),
3656 "make ext2/3/4 external journal with UUID",
3658 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3660 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3662 "make ext2/3/4 filesystem with external journal",
3664 This creates an ext2/3/4 filesystem on C<device> with
3665 an external journal on C<journal>. It is equivalent
3668 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3670 See also C<guestfs_mke2journal>.");
3672 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3674 "make ext2/3/4 filesystem with external journal",
3676 This creates an ext2/3/4 filesystem on C<device> with
3677 an external journal on the journal labeled C<label>.
3679 See also C<guestfs_mke2journal_L>.");
3681 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3683 "make ext2/3/4 filesystem with external journal",
3685 This creates an ext2/3/4 filesystem on C<device> with
3686 an external journal on the journal with UUID C<uuid>.
3688 See also C<guestfs_mke2journal_U>.");
3690 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3691 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3692 "load a kernel module",
3694 This loads a kernel module in the appliance.
3696 The kernel module must have been whitelisted when libguestfs
3697 was built (see C<appliance/kmod.whitelist.in> in the source).");
3699 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3700 [InitNone, Always, TestOutput (
3701 [["echo_daemon"; "This is a test"]], "This is a test"
3703 "echo arguments back to the client",
3705 This command concatenate the list of C<words> passed with single spaces between
3706 them and returns the resulting string.
3708 You can use this command to test the connection through to the daemon.
3710 See also C<guestfs_ping_daemon>.");
3712 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3713 [], (* There is a regression test for this. *)
3714 "find all files and directories, returning NUL-separated list",
3716 This command lists out all files and directories, recursively,
3717 starting at C<directory>, placing the resulting list in the
3718 external file called C<files>.
3720 This command works the same way as C<guestfs_find> with the
3721 following exceptions:
3727 The resulting list is written to an external file.
3731 Items (filenames) in the result are separated
3732 by C<\\0> characters. See L<find(1)> option I<-print0>.
3736 This command is not limited in the number of names that it
3741 The result list is not sorted.
3745 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3746 [InitISOFS, Always, TestOutput (
3747 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3748 InitISOFS, Always, TestOutput (
3749 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3750 InitISOFS, Always, TestOutput (
3751 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3752 InitISOFS, Always, TestLastFail (
3753 [["case_sensitive_path"; "/Known-1/"]]);
3754 InitBasicFS, Always, TestOutput (
3756 ["mkdir"; "/a/bbb"];
3757 ["touch"; "/a/bbb/c"];
3758 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3759 InitBasicFS, Always, TestOutput (
3761 ["mkdir"; "/a/bbb"];
3762 ["touch"; "/a/bbb/c"];
3763 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3764 InitBasicFS, Always, TestLastFail (
3766 ["mkdir"; "/a/bbb"];
3767 ["touch"; "/a/bbb/c"];
3768 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3769 "return true path on case-insensitive filesystem",
3771 This can be used to resolve case insensitive paths on
3772 a filesystem which is case sensitive. The use case is
3773 to resolve paths which you have read from Windows configuration
3774 files or the Windows Registry, to the true path.
3776 The command handles a peculiarity of the Linux ntfs-3g
3777 filesystem driver (and probably others), which is that although
3778 the underlying filesystem is case-insensitive, the driver
3779 exports the filesystem to Linux as case-sensitive.
3781 One consequence of this is that special directories such
3782 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3783 (or other things) depending on the precise details of how
3784 they were created. In Windows itself this would not be
3787 Bug or feature? You decide:
3788 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3790 This function resolves the true case of each element in the
3791 path and returns the case-sensitive path.
3793 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3794 might return C<\"/WINDOWS/system32\"> (the exact return value
3795 would depend on details of how the directories were originally
3796 created under Windows).
3799 This function does not handle drive names, backslashes etc.
3801 See also C<guestfs_realpath>.");
3803 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3804 [InitBasicFS, Always, TestOutput (
3805 [["vfs_type"; "/dev/sda1"]], "ext2")],
3806 "get the Linux VFS type corresponding to a mounted device",
3808 This command gets the block device type corresponding to
3809 a mounted device called C<device>.
3811 Usually the result is the name of the Linux VFS module that
3812 is used to mount this device (probably determined automatically
3813 if you used the C<guestfs_mount> call).");
3815 ("truncate", (RErr, [Pathname "path"]), 199, [],
3816 [InitBasicFS, Always, TestOutputStruct (
3817 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3818 ["truncate"; "/test"];
3819 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3820 "truncate a file to zero size",
3822 This command truncates C<path> to a zero-length file. The
3823 file must exist already.");
3825 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3826 [InitBasicFS, Always, TestOutputStruct (
3827 [["touch"; "/test"];
3828 ["truncate_size"; "/test"; "1000"];
3829 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3830 "truncate a file to a particular size",
3832 This command truncates C<path> to size C<size> bytes. The file
3833 must exist already. If the file is smaller than C<size> then
3834 the file is extended to the required size with null bytes.");
3836 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3837 [InitBasicFS, Always, TestOutputStruct (
3838 [["touch"; "/test"];
3839 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3840 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3841 "set timestamp of a file with nanosecond precision",
3843 This command sets the timestamps of a file with nanosecond
3846 C<atsecs, atnsecs> are the last access time (atime) in secs and
3847 nanoseconds from the epoch.
3849 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3850 secs and nanoseconds from the epoch.
3852 If the C<*nsecs> field contains the special value C<-1> then
3853 the corresponding timestamp is set to the current time. (The
3854 C<*secs> field is ignored in this case).
3856 If the C<*nsecs> field contains the special value C<-2> then
3857 the corresponding timestamp is left unchanged. (The
3858 C<*secs> field is ignored in this case).");
3860 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3861 [InitBasicFS, Always, TestOutputStruct (
3862 [["mkdir_mode"; "/test"; "0o111"];
3863 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3864 "create a directory with a particular mode",
3866 This command creates a directory, setting the initial permissions
3867 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3869 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3871 "change file owner and group",
3873 Change the file owner to C<owner> and group to C<group>.
3874 This is like C<guestfs_chown> but if C<path> is a symlink then
3875 the link itself is changed, not the target.
3877 Only numeric uid and gid are supported. If you want to use
3878 names, you will need to locate and parse the password file
3879 yourself (Augeas support makes this relatively easy).");
3881 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3883 "lstat on multiple files",
3885 This call allows you to perform the C<guestfs_lstat> operation
3886 on multiple files, where all files are in the directory C<path>.
3887 C<names> is the list of files from this directory.
3889 On return you get a list of stat structs, with a one-to-one
3890 correspondence to the C<names> list. If any name did not exist
3891 or could not be lstat'd, then the C<ino> field of that structure
3894 This call is intended for programs that want to efficiently
3895 list a directory contents without making many round-trips.
3896 See also C<guestfs_lxattrlist> for a similarly efficient call
3897 for getting extended attributes. Very long directory listings
3898 might cause the protocol message size to be exceeded, causing
3899 this call to fail. The caller must split up such requests
3900 into smaller groups of names.");
3902 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3904 "lgetxattr on multiple files",
3906 This call allows you to get the extended attributes
3907 of multiple files, where all files are in the directory C<path>.
3908 C<names> is the list of files from this directory.
3910 On return you get a flat list of xattr structs which must be
3911 interpreted sequentially. The first xattr struct always has a zero-length
3912 C<attrname>. C<attrval> in this struct is zero-length
3913 to indicate there was an error doing C<lgetxattr> for this
3914 file, I<or> is a C string which is a decimal number
3915 (the number of following attributes for this file, which could
3916 be C<\"0\">). Then after the first xattr struct are the
3917 zero or more attributes for the first named file.
3918 This repeats for the second and subsequent files.
3920 This call is intended for programs that want to efficiently
3921 list a directory contents without making many round-trips.
3922 See also C<guestfs_lstatlist> for a similarly efficient call
3923 for getting standard stats. Very long directory listings
3924 might cause the protocol message size to be exceeded, causing
3925 this call to fail. The caller must split up such requests
3926 into smaller groups of names.");
3928 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3930 "readlink on multiple files",
3932 This call allows you to do a C<readlink> operation
3933 on multiple files, where all files are in the directory C<path>.
3934 C<names> is the list of files from this directory.
3936 On return you get a list of strings, with a one-to-one
3937 correspondence to the C<names> list. Each string is the
3938 value of the symbol link.
3940 If the C<readlink(2)> operation fails on any name, then
3941 the corresponding result string is the empty string C<\"\">.
3942 However the whole operation is completed even if there
3943 were C<readlink(2)> errors, and so you can call this
3944 function with names where you don't know if they are
3945 symbolic links already (albeit slightly less efficient).
3947 This call is intended for programs that want to efficiently
3948 list a directory contents without making many round-trips.
3949 Very long directory listings might cause the protocol
3950 message size to be exceeded, causing
3951 this call to fail. The caller must split up such requests
3952 into smaller groups of names.");
3954 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3955 [InitISOFS, Always, TestOutputBuffer (
3956 [["pread"; "/known-4"; "1"; "3"]], "\n");
3957 InitISOFS, Always, TestOutputBuffer (
3958 [["pread"; "/empty"; "0"; "100"]], "")],
3959 "read part of a file",
3961 This command lets you read part of a file. It reads C<count>
3962 bytes of the file, starting at C<offset>, from file C<path>.
3964 This may read fewer bytes than requested. For further details
3965 see the L<pread(2)> system call.");
3967 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3968 [InitEmpty, Always, TestRun (
3969 [["part_init"; "/dev/sda"; "gpt"]])],
3970 "create an empty partition table",
3972 This creates an empty partition table on C<device> of one of the
3973 partition types listed below. Usually C<parttype> should be
3974 either C<msdos> or C<gpt> (for large disks).
3976 Initially there are no partitions. Following this, you should
3977 call C<guestfs_part_add> for each partition required.
3979 Possible values for C<parttype> are:
3983 =item B<efi> | B<gpt>
3985 Intel EFI / GPT partition table.
3987 This is recommended for >= 2 TB partitions that will be accessed
3988 from Linux and Intel-based Mac OS X. It also has limited backwards
3989 compatibility with the C<mbr> format.
3991 =item B<mbr> | B<msdos>
3993 The standard PC \"Master Boot Record\" (MBR) format used
3994 by MS-DOS and Windows. This partition type will B<only> work
3995 for device sizes up to 2 TB. For large disks we recommend
4000 Other partition table types that may work but are not
4009 =item B<amiga> | B<rdb>
4011 Amiga \"Rigid Disk Block\" format.
4019 DASD, used on IBM mainframes.
4027 Old Mac partition format. Modern Macs use C<gpt>.
4031 NEC PC-98 format, common in Japan apparently.
4039 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4040 [InitEmpty, Always, TestRun (
4041 [["part_init"; "/dev/sda"; "mbr"];
4042 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4043 InitEmpty, Always, TestRun (
4044 [["part_init"; "/dev/sda"; "gpt"];
4045 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4046 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4047 InitEmpty, Always, TestRun (
4048 [["part_init"; "/dev/sda"; "mbr"];
4049 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4050 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4051 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4052 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4053 "add a partition to the device",
4055 This command adds a partition to C<device>. If there is no partition
4056 table on the device, call C<guestfs_part_init> first.
4058 The C<prlogex> parameter is the type of partition. Normally you
4059 should pass C<p> or C<primary> here, but MBR partition tables also
4060 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4063 C<startsect> and C<endsect> are the start and end of the partition
4064 in I<sectors>. C<endsect> may be negative, which means it counts
4065 backwards from the end of the disk (C<-1> is the last sector).
4067 Creating a partition which covers the whole disk is not so easy.
4068 Use C<guestfs_part_disk> to do that.");
4070 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4071 [InitEmpty, Always, TestRun (
4072 [["part_disk"; "/dev/sda"; "mbr"]]);
4073 InitEmpty, Always, TestRun (
4074 [["part_disk"; "/dev/sda"; "gpt"]])],
4075 "partition whole disk with a single primary partition",
4077 This command is simply a combination of C<guestfs_part_init>
4078 followed by C<guestfs_part_add> to create a single primary partition
4079 covering the whole disk.
4081 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4082 but other possible values are described in C<guestfs_part_init>.");
4084 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4085 [InitEmpty, Always, TestRun (
4086 [["part_disk"; "/dev/sda"; "mbr"];
4087 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4088 "make a partition bootable",
4090 This sets the bootable flag on partition numbered C<partnum> on
4091 device C<device>. Note that partitions are numbered from 1.
4093 The bootable flag is used by some PC BIOSes to determine which
4094 partition to boot from. It is by no means universally recognized,
4095 and in any case if your operating system installed a boot
4096 sector on the device itself, then that takes precedence.");
4098 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4099 [InitEmpty, Always, TestRun (
4100 [["part_disk"; "/dev/sda"; "gpt"];
4101 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4102 "set partition name",
4104 This sets the partition name on partition numbered C<partnum> on
4105 device C<device>. Note that partitions are numbered from 1.
4107 The partition name can only be set on certain types of partition
4108 table. This works on C<gpt> but not on C<mbr> partitions.");
4110 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4111 [], (* XXX Add a regression test for this. *)
4112 "list partitions on a device",
4114 This command parses the partition table on C<device> and
4115 returns the list of partitions found.
4117 The fields in the returned structure are:
4123 Partition number, counting from 1.
4127 Start of the partition I<in bytes>. To get sectors you have to
4128 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4132 End of the partition in bytes.
4136 Size of the partition in bytes.
4140 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4141 [InitEmpty, Always, TestOutput (
4142 [["part_disk"; "/dev/sda"; "gpt"];
4143 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4144 "get the partition table type",
4146 This command examines the partition table on C<device> and
4147 returns the partition table type (format) being used.
4149 Common return values include: C<msdos> (a DOS/Windows style MBR
4150 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4151 values are possible, although unusual. See C<guestfs_part_init>
4154 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4155 [InitBasicFS, Always, TestOutputBuffer (
4156 [["fill"; "0x63"; "10"; "/test"];
4157 ["read_file"; "/test"]], "cccccccccc")],
4158 "fill a file with octets",
4160 This command creates a new file called C<path>. The initial
4161 content of the file is C<len> octets of C<c>, where C<c>
4162 must be a number in the range C<[0..255]>.
4164 To fill a file with zero bytes (sparsely), it is
4165 much more efficient to use C<guestfs_truncate_size>.");
4167 ("available", (RErr, [StringList "groups"]), 216, [],
4168 [InitNone, Always, TestRun [["available"; ""]]],
4169 "test availability of some parts of the API",
4171 This command is used to check the availability of some
4172 groups of functionality in the appliance, which not all builds of
4173 the libguestfs appliance will be able to provide.
4175 The libguestfs groups, and the functions that those
4176 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4178 The argument C<groups> is a list of group names, eg:
4179 C<[\"inotify\", \"augeas\"]> would check for the availability of
4180 the Linux inotify functions and Augeas (configuration file
4183 The command returns no error if I<all> requested groups are available.
4185 It fails with an error if one or more of the requested
4186 groups is unavailable in the appliance.
4188 If an unknown group name is included in the
4189 list of groups then an error is always returned.
4197 You must call C<guestfs_launch> before calling this function.
4199 The reason is because we don't know what groups are
4200 supported by the appliance/daemon until it is running and can
4205 If a group of functions is available, this does not necessarily
4206 mean that they will work. You still have to check for errors
4207 when calling individual API functions even if they are
4212 It is usually the job of distro packagers to build
4213 complete functionality into the libguestfs appliance.
4214 Upstream libguestfs, if built from source with all
4215 requirements satisfied, will support everything.
4219 This call was added in version C<1.0.80>. In previous
4220 versions of libguestfs all you could do would be to speculatively
4221 execute a command to find out if the daemon implemented it.
4222 See also C<guestfs_version>.
4226 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4227 [InitBasicFS, Always, TestOutputBuffer (
4228 [["write_file"; "/src"; "hello, world"; "0"];
4229 ["dd"; "/src"; "/dest"];
4230 ["read_file"; "/dest"]], "hello, world")],
4231 "copy from source to destination using dd",
4233 This command copies from one source device or file C<src>
4234 to another destination device or file C<dest>. Normally you
4235 would use this to copy to or from a device or partition, for
4236 example to duplicate a filesystem.
4238 If the destination is a device, it must be as large or larger
4239 than the source file or device, otherwise the copy will fail.
4240 This command cannot do partial copies.");
4242 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4243 [InitBasicFS, Always, TestOutputInt (
4244 [["write_file"; "/file"; "hello, world"; "0"];
4245 ["filesize"; "/file"]], 12)],
4246 "return the size of the file in bytes",
4248 This command returns the size of C<file> in bytes.
4250 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4251 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4252 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4254 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4255 [InitBasicFSonLVM, Always, TestOutputList (
4256 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4257 ["lvs"]], ["/dev/VG/LV2"])],
4258 "rename an LVM logical volume",
4260 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4262 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4263 [InitBasicFSonLVM, Always, TestOutputList (
4265 ["vg_activate"; "false"; "VG"];
4266 ["vgrename"; "VG"; "VG2"];
4267 ["vg_activate"; "true"; "VG2"];
4268 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4269 ["vgs"]], ["VG2"])],
4270 "rename an LVM volume group",
4272 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4274 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4275 [InitISOFS, Always, TestOutputBuffer (
4276 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4277 "list the contents of a single file in an initrd",
4279 This command unpacks the file C<filename> from the initrd file
4280 called C<initrdpath>. The filename must be given I<without> the
4281 initial C</> character.
4283 For example, in guestfish you could use the following command
4284 to examine the boot script (usually called C</init>)
4285 contained in a Linux initrd or initramfs image:
4287 initrd-cat /boot/initrd-<version>.img init
4289 See also C<guestfs_initrd_list>.");
4293 let all_functions = non_daemon_functions @ daemon_functions
4295 (* In some places we want the functions to be displayed sorted
4296 * alphabetically, so this is useful:
4298 let all_functions_sorted =
4299 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4300 compare n1 n2) all_functions
4302 (* Field types for structures. *)
4304 | FChar (* C 'char' (really, a 7 bit byte). *)
4305 | FString (* nul-terminated ASCII string, NOT NULL. *)
4306 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4311 | FBytes (* Any int measure that counts bytes. *)
4312 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4313 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4315 (* Because we generate extra parsing code for LVM command line tools,
4316 * we have to pull out the LVM columns separately here.
4326 "pv_attr", FString (* XXX *);
4327 "pv_pe_count", FInt64;
4328 "pv_pe_alloc_count", FInt64;
4331 "pv_mda_count", FInt64;
4332 "pv_mda_free", FBytes;
4333 (* Not in Fedora 10:
4334 "pv_mda_size", FBytes;
4341 "vg_attr", FString (* XXX *);
4344 "vg_sysid", FString;
4345 "vg_extent_size", FBytes;
4346 "vg_extent_count", FInt64;
4347 "vg_free_count", FInt64;
4352 "snap_count", FInt64;
4355 "vg_mda_count", FInt64;
4356 "vg_mda_free", FBytes;
4357 (* Not in Fedora 10:
4358 "vg_mda_size", FBytes;
4364 "lv_attr", FString (* XXX *);
4367 "lv_kernel_major", FInt64;
4368 "lv_kernel_minor", FInt64;
4370 "seg_count", FInt64;
4372 "snap_percent", FOptPercent;
4373 "copy_percent", FOptPercent;
4376 "mirror_log", FString;
4380 (* Names and fields in all structures (in RStruct and RStructList)
4384 (* The old RIntBool return type, only ever used for aug_defnode. Do
4385 * not use this struct in any new code.
4388 "i", FInt32; (* for historical compatibility *)
4389 "b", FInt32; (* for historical compatibility *)
4392 (* LVM PVs, VGs, LVs. *)
4393 "lvm_pv", lvm_pv_cols;
4394 "lvm_vg", lvm_vg_cols;
4395 "lvm_lv", lvm_lv_cols;
4397 (* Column names and types from stat structures.
4398 * NB. Can't use things like 'st_atime' because glibc header files
4399 * define some of these as macros. Ugh.
4430 (* Column names in dirent structure. *)
4433 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4438 (* Version numbers. *)
4446 (* Extended attribute. *)
4448 "attrname", FString;
4452 (* Inotify events. *)
4456 "in_cookie", FUInt32;
4460 (* Partition table entry. *)
4463 "part_start", FBytes;
4465 "part_size", FBytes;
4467 ] (* end of structs *)
4469 (* Ugh, Java has to be different ..
4470 * These names are also used by the Haskell bindings.
4472 let java_structs = [
4473 "int_bool", "IntBool";
4478 "statvfs", "StatVFS";
4480 "version", "Version";
4482 "inotify_event", "INotifyEvent";
4483 "partition", "Partition";
4486 (* What structs are actually returned. *)
4487 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4489 (* Returns a list of RStruct/RStructList structs that are returned
4490 * by any function. Each element of returned list is a pair:
4492 * (structname, RStructOnly)
4493 * == there exists function which returns RStruct (_, structname)
4494 * (structname, RStructListOnly)
4495 * == there exists function which returns RStructList (_, structname)
4496 * (structname, RStructAndList)
4497 * == there are functions returning both RStruct (_, structname)
4498 * and RStructList (_, structname)
4500 let rstructs_used_by functions =
4501 (* ||| is a "logical OR" for rstructs_used_t *)
4505 | _, RStructAndList -> RStructAndList
4506 | RStructOnly, RStructListOnly
4507 | RStructListOnly, RStructOnly -> RStructAndList
4508 | RStructOnly, RStructOnly -> RStructOnly
4509 | RStructListOnly, RStructListOnly -> RStructListOnly
4512 let h = Hashtbl.create 13 in
4514 (* if elem->oldv exists, update entry using ||| operator,
4515 * else just add elem->newv to the hash
4517 let update elem newv =
4518 try let oldv = Hashtbl.find h elem in
4519 Hashtbl.replace h elem (newv ||| oldv)
4520 with Not_found -> Hashtbl.add h elem newv
4524 fun (_, style, _, _, _, _, _) ->
4525 match fst style with
4526 | RStruct (_, structname) -> update structname RStructOnly
4527 | RStructList (_, structname) -> update structname RStructListOnly
4531 (* return key->values as a list of (key,value) *)
4532 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4534 (* Used for testing language bindings. *)
4536 | CallString of string
4537 | CallOptString of string option
4538 | CallStringList of string list
4540 | CallInt64 of int64
4543 (* Used to memoize the result of pod2text. *)
4544 let pod2text_memo_filename = "src/.pod2text.data"
4545 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4547 let chan = open_in pod2text_memo_filename in
4548 let v = input_value chan in
4552 _ -> Hashtbl.create 13
4553 let pod2text_memo_updated () =
4554 let chan = open_out pod2text_memo_filename in
4555 output_value chan pod2text_memo;
4558 (* Useful functions.
4559 * Note we don't want to use any external OCaml libraries which
4560 * makes this a bit harder than it should be.
4562 module StringMap = Map.Make (String)
4564 let failwithf fs = ksprintf failwith fs
4566 let unique = let i = ref 0 in fun () -> incr i; !i
4568 let replace_char s c1 c2 =
4569 let s2 = String.copy s in
4570 let r = ref false in
4571 for i = 0 to String.length s2 - 1 do
4572 if String.unsafe_get s2 i = c1 then (
4573 String.unsafe_set s2 i c2;
4577 if not !r then s else s2
4581 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4583 let triml ?(test = isspace) str =
4585 let n = ref (String.length str) in
4586 while !n > 0 && test str.[!i]; do
4591 else String.sub str !i !n
4593 let trimr ?(test = isspace) str =
4594 let n = ref (String.length str) in
4595 while !n > 0 && test str.[!n-1]; do
4598 if !n = String.length str then str
4599 else String.sub str 0 !n
4601 let trim ?(test = isspace) str =
4602 trimr ~test (triml ~test str)
4604 let rec find s sub =
4605 let len = String.length s in
4606 let sublen = String.length sub in
4608 if i <= len-sublen then (
4610 if j < sublen then (
4611 if s.[i+j] = sub.[j] then loop2 (j+1)
4617 if r = -1 then loop (i+1) else r
4623 let rec replace_str s s1 s2 =
4624 let len = String.length s in
4625 let sublen = String.length s1 in
4626 let i = find s s1 in
4629 let s' = String.sub s 0 i in
4630 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4631 s' ^ s2 ^ replace_str s'' s1 s2
4634 let rec string_split sep str =
4635 let len = String.length str in
4636 let seplen = String.length sep in
4637 let i = find str sep in
4638 if i = -1 then [str]
4640 let s' = String.sub str 0 i in
4641 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4642 s' :: string_split sep s''
4645 let files_equal n1 n2 =
4646 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4647 match Sys.command cmd with
4650 | i -> failwithf "%s: failed with error code %d" cmd i
4652 let rec filter_map f = function
4656 | Some y -> y :: filter_map f xs
4657 | None -> filter_map f xs
4659 let rec find_map f = function
4660 | [] -> raise Not_found
4664 | None -> find_map f xs
4667 let rec loop i = function
4669 | x :: xs -> f i x; loop (i+1) xs
4674 let rec loop i = function
4676 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4680 let count_chars c str =
4681 let count = ref 0 in
4682 for i = 0 to String.length str - 1 do
4683 if c = String.unsafe_get str i then incr count
4687 let name_of_argt = function
4688 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4689 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4690 | FileIn n | FileOut n -> n
4692 let java_name_of_struct typ =
4693 try List.assoc typ java_structs
4696 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4698 let cols_of_struct typ =
4699 try List.assoc typ structs
4701 failwithf "cols_of_struct: unknown struct %s" typ
4703 let seq_of_test = function
4704 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4705 | TestOutputListOfDevices (s, _)
4706 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4707 | TestOutputTrue s | TestOutputFalse s
4708 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4709 | TestOutputStruct (s, _)
4710 | TestLastFail s -> s
4712 (* Handling for function flags. *)
4713 let protocol_limit_warning =
4714 "Because of the message protocol, there is a transfer limit
4715 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4717 let danger_will_robinson =
4718 "B<This command is dangerous. Without careful use you
4719 can easily destroy all your data>."
4721 let deprecation_notice flags =
4724 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4726 sprintf "This function is deprecated.
4727 In new code, use the C<%s> call instead.
4729 Deprecated functions will not be removed from the API, but the
4730 fact that they are deprecated indicates that there are problems
4731 with correct use of these functions." alt in
4736 (* Create list of optional groups. *)
4738 let h = Hashtbl.create 13 in
4740 fun (name, _, _, flags, _, _, _) ->
4744 let names = try Hashtbl.find h group with Not_found -> [] in
4745 Hashtbl.replace h group (name :: names)
4749 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4752 fun group -> group, List.sort compare (Hashtbl.find h group)
4754 List.sort (fun x y -> compare (fst x) (fst y)) groups
4756 (* Check function names etc. for consistency. *)
4757 let check_functions () =
4758 let contains_uppercase str =
4759 let len = String.length str in
4761 if i >= len then false
4764 if c >= 'A' && c <= 'Z' then true
4771 (* Check function names. *)
4773 fun (name, _, _, _, _, _, _) ->
4774 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4775 failwithf "function name %s does not need 'guestfs' prefix" name;
4777 failwithf "function name is empty";
4778 if name.[0] < 'a' || name.[0] > 'z' then
4779 failwithf "function name %s must start with lowercase a-z" name;
4780 if String.contains name '-' then
4781 failwithf "function name %s should not contain '-', use '_' instead."
4785 (* Check function parameter/return names. *)
4787 fun (name, style, _, _, _, _, _) ->
4788 let check_arg_ret_name n =
4789 if contains_uppercase n then
4790 failwithf "%s param/ret %s should not contain uppercase chars"
4792 if String.contains n '-' || String.contains n '_' then
4793 failwithf "%s param/ret %s should not contain '-' or '_'"
4796 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;
4797 if n = "int" || n = "char" || n = "short" || n = "long" then
4798 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4799 if n = "i" || n = "n" then
4800 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4801 if n = "argv" || n = "args" then
4802 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4804 (* List Haskell, OCaml and C keywords here.
4805 * http://www.haskell.org/haskellwiki/Keywords
4806 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4807 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4808 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4809 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4810 * Omitting _-containing words, since they're handled above.
4811 * Omitting the OCaml reserved word, "val", is ok,
4812 * and saves us from renaming several parameters.
4815 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4816 "char"; "class"; "const"; "constraint"; "continue"; "data";
4817 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4818 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4819 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4820 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4821 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4823 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4824 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4825 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4826 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4827 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4828 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4829 "volatile"; "when"; "where"; "while";
4831 if List.mem n reserved then
4832 failwithf "%s has param/ret using reserved word %s" name n;
4835 (match fst style with
4837 | RInt n | RInt64 n | RBool n
4838 | RConstString n | RConstOptString n | RString n
4839 | RStringList n | RStruct (n, _) | RStructList (n, _)
4840 | RHashtable n | RBufferOut n ->
4841 check_arg_ret_name n
4843 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4846 (* Check short descriptions. *)
4848 fun (name, _, _, _, _, shortdesc, _) ->
4849 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4850 failwithf "short description of %s should begin with lowercase." name;
4851 let c = shortdesc.[String.length shortdesc-1] in
4852 if c = '\n' || c = '.' then
4853 failwithf "short description of %s should not end with . or \\n." name
4856 (* Check long dscriptions. *)
4858 fun (name, _, _, _, _, _, longdesc) ->
4859 if longdesc.[String.length longdesc-1] = '\n' then
4860 failwithf "long description of %s should not end with \\n." name
4863 (* Check proc_nrs. *)
4865 fun (name, _, proc_nr, _, _, _, _) ->
4866 if proc_nr <= 0 then
4867 failwithf "daemon function %s should have proc_nr > 0" name
4871 fun (name, _, proc_nr, _, _, _, _) ->
4872 if proc_nr <> -1 then
4873 failwithf "non-daemon function %s should have proc_nr -1" name
4874 ) non_daemon_functions;
4877 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4880 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4881 let rec loop = function
4884 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4886 | (name1,nr1) :: (name2,nr2) :: _ ->
4887 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4895 (* Ignore functions that have no tests. We generate a
4896 * warning when the user does 'make check' instead.
4898 | name, _, _, _, [], _, _ -> ()
4899 | name, _, _, _, tests, _, _ ->
4903 match seq_of_test test with
4905 failwithf "%s has a test containing an empty sequence" name
4906 | cmds -> List.map List.hd cmds
4908 let funcs = List.flatten funcs in
4910 let tested = List.mem name funcs in
4913 failwithf "function %s has tests but does not test itself" name
4916 (* 'pr' prints to the current output file. *)
4917 let chan = ref Pervasives.stdout
4922 let i = count_chars '\n' str in
4923 lines := !lines + i;
4924 output_string !chan str
4927 let copyright_years =
4928 let this_year = 1900 + (localtime (time ())).tm_year in
4929 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4931 (* Generate a header block in a number of standard styles. *)
4932 type comment_style =
4933 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4934 type license = GPLv2plus | LGPLv2plus
4936 let generate_header ?(extra_inputs = []) comment license =
4937 let inputs = "src/generator.ml" :: extra_inputs in
4938 let c = match comment with
4939 | CStyle -> pr "/* "; " *"
4940 | CPlusPlusStyle -> pr "// "; "//"
4941 | HashStyle -> pr "# "; "#"
4942 | OCamlStyle -> pr "(* "; " *"
4943 | HaskellStyle -> pr "{- "; " " in
4944 pr "libguestfs generated file\n";
4945 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4946 List.iter (pr "%s %s\n" c) inputs;
4947 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4949 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4953 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4954 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4955 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4956 pr "%s (at your option) any later version.\n" c;
4958 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4959 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4960 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4961 pr "%s GNU General Public License for more details.\n" c;
4963 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4964 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4965 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4968 pr "%s This library is free software; you can redistribute it and/or\n" c;
4969 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4970 pr "%s License as published by the Free Software Foundation; either\n" c;
4971 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4973 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4974 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4975 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4976 pr "%s Lesser General Public License for more details.\n" c;
4978 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4979 pr "%s License along with this library; if not, write to the Free Software\n" c;
4980 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4983 | CStyle -> pr " */\n"
4986 | OCamlStyle -> pr " *)\n"
4987 | HaskellStyle -> pr "-}\n"
4991 (* Start of main code generation functions below this line. *)
4993 (* Generate the pod documentation for the C API. *)
4994 let rec generate_actions_pod () =
4996 fun (shortname, style, _, flags, _, _, longdesc) ->
4997 if not (List.mem NotInDocs flags) then (
4998 let name = "guestfs_" ^ shortname in
4999 pr "=head2 %s\n\n" name;
5001 generate_prototype ~extern:false ~handle:"handle" name style;
5003 pr "%s\n\n" longdesc;
5004 (match fst style with
5006 pr "This function returns 0 on success or -1 on error.\n\n"
5008 pr "On error this function returns -1.\n\n"
5010 pr "On error this function returns -1.\n\n"
5012 pr "This function returns a C truth value on success or -1 on error.\n\n"
5014 pr "This function returns a string, or NULL on error.
5015 The string is owned by the guest handle and must I<not> be freed.\n\n"
5016 | RConstOptString _ ->
5017 pr "This function returns a string which may be NULL.
5018 There is way to return an error from this function.
5019 The string is owned by the guest handle and must I<not> be freed.\n\n"
5021 pr "This function returns a string, or NULL on error.
5022 I<The caller must free the returned string after use>.\n\n"
5024 pr "This function returns a NULL-terminated array of strings
5025 (like L<environ(3)>), or NULL if there was an error.
5026 I<The caller must free the strings and the array after use>.\n\n"
5027 | RStruct (_, typ) ->
5028 pr "This function returns a C<struct guestfs_%s *>,
5029 or NULL if there was an error.
5030 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5031 | RStructList (_, typ) ->
5032 pr "This function returns a C<struct guestfs_%s_list *>
5033 (see E<lt>guestfs-structs.hE<gt>),
5034 or NULL if there was an error.
5035 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5037 pr "This function returns a NULL-terminated array of
5038 strings, or NULL if there was an error.
5039 The array of strings will always have length C<2n+1>, where
5040 C<n> keys and values alternate, followed by the trailing NULL entry.
5041 I<The caller must free the strings and the array after use>.\n\n"
5043 pr "This function returns a buffer, or NULL on error.
5044 The size of the returned buffer is written to C<*size_r>.
5045 I<The caller must free the returned buffer after use>.\n\n"
5047 if List.mem ProtocolLimitWarning flags then
5048 pr "%s\n\n" protocol_limit_warning;
5049 if List.mem DangerWillRobinson flags then
5050 pr "%s\n\n" danger_will_robinson;
5051 match deprecation_notice flags with
5053 | Some txt -> pr "%s\n\n" txt
5055 ) all_functions_sorted
5057 and generate_structs_pod () =
5058 (* Structs documentation. *)
5061 pr "=head2 guestfs_%s\n" typ;
5063 pr " struct guestfs_%s {\n" typ;
5066 | name, FChar -> pr " char %s;\n" name
5067 | name, FUInt32 -> pr " uint32_t %s;\n" name
5068 | name, FInt32 -> pr " int32_t %s;\n" name
5069 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5070 | name, FInt64 -> pr " int64_t %s;\n" name
5071 | name, FString -> pr " char *%s;\n" name
5073 pr " /* The next two fields describe a byte array. */\n";
5074 pr " uint32_t %s_len;\n" name;
5075 pr " char *%s;\n" name
5077 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5078 pr " char %s[32];\n" name
5079 | name, FOptPercent ->
5080 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5081 pr " float %s;\n" name
5085 pr " struct guestfs_%s_list {\n" typ;
5086 pr " uint32_t len; /* Number of elements in list. */\n";
5087 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5090 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5091 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5096 and generate_availability_pod () =
5097 (* Availability documentation. *)
5101 fun (group, functions) ->
5102 pr "=item B<%s>\n" group;
5104 pr "The following functions:\n";
5105 List.iter (pr "L</guestfs_%s>\n") functions;
5111 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5112 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5114 * We have to use an underscore instead of a dash because otherwise
5115 * rpcgen generates incorrect code.
5117 * This header is NOT exported to clients, but see also generate_structs_h.
5119 and generate_xdr () =
5120 generate_header CStyle LGPLv2plus;
5122 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5123 pr "typedef string str<>;\n";
5126 (* Internal structures. *)
5130 pr "struct guestfs_int_%s {\n" typ;
5132 | name, FChar -> pr " char %s;\n" name
5133 | name, FString -> pr " string %s<>;\n" name
5134 | name, FBuffer -> pr " opaque %s<>;\n" name
5135 | name, FUUID -> pr " opaque %s[32];\n" name
5136 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5137 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5138 | name, FOptPercent -> pr " float %s;\n" name
5142 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5147 fun (shortname, style, _, _, _, _, _) ->
5148 let name = "guestfs_" ^ shortname in
5150 (match snd style with
5153 pr "struct %s_args {\n" name;
5156 | Pathname n | Device n | Dev_or_Path n | String n ->
5157 pr " string %s<>;\n" n
5158 | OptString n -> pr " str *%s;\n" n
5159 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5160 | Bool n -> pr " bool %s;\n" n
5161 | Int n -> pr " int %s;\n" n
5162 | Int64 n -> pr " hyper %s;\n" n
5163 | FileIn _ | FileOut _ -> ()
5167 (match fst style with
5170 pr "struct %s_ret {\n" name;
5174 pr "struct %s_ret {\n" name;
5175 pr " hyper %s;\n" n;
5178 pr "struct %s_ret {\n" name;
5181 | RConstString _ | RConstOptString _ ->
5182 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5184 pr "struct %s_ret {\n" name;
5185 pr " string %s<>;\n" n;
5188 pr "struct %s_ret {\n" name;
5189 pr " str %s<>;\n" n;
5191 | RStruct (n, typ) ->
5192 pr "struct %s_ret {\n" name;
5193 pr " guestfs_int_%s %s;\n" typ n;
5195 | RStructList (n, typ) ->
5196 pr "struct %s_ret {\n" name;
5197 pr " guestfs_int_%s_list %s;\n" typ n;
5200 pr "struct %s_ret {\n" name;
5201 pr " str %s<>;\n" n;
5204 pr "struct %s_ret {\n" name;
5205 pr " opaque %s<>;\n" n;
5210 (* Table of procedure numbers. *)
5211 pr "enum guestfs_procedure {\n";
5213 fun (shortname, _, proc_nr, _, _, _, _) ->
5214 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5216 pr " GUESTFS_PROC_NR_PROCS\n";
5220 (* Having to choose a maximum message size is annoying for several
5221 * reasons (it limits what we can do in the API), but it (a) makes
5222 * the protocol a lot simpler, and (b) provides a bound on the size
5223 * of the daemon which operates in limited memory space.
5225 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5228 (* Message header, etc. *)
5230 /* The communication protocol is now documented in the guestfs(3)
5234 const GUESTFS_PROGRAM = 0x2000F5F5;
5235 const GUESTFS_PROTOCOL_VERSION = 1;
5237 /* These constants must be larger than any possible message length. */
5238 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5239 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5241 enum guestfs_message_direction {
5242 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5243 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5246 enum guestfs_message_status {
5247 GUESTFS_STATUS_OK = 0,
5248 GUESTFS_STATUS_ERROR = 1
5251 const GUESTFS_ERROR_LEN = 256;
5253 struct guestfs_message_error {
5254 string error_message<GUESTFS_ERROR_LEN>;
5257 struct guestfs_message_header {
5258 unsigned prog; /* GUESTFS_PROGRAM */
5259 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5260 guestfs_procedure proc; /* GUESTFS_PROC_x */
5261 guestfs_message_direction direction;
5262 unsigned serial; /* message serial number */
5263 guestfs_message_status status;
5266 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5268 struct guestfs_chunk {
5269 int cancel; /* if non-zero, transfer is cancelled */
5270 /* data size is 0 bytes if the transfer has finished successfully */
5271 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5275 (* Generate the guestfs-structs.h file. *)
5276 and generate_structs_h () =
5277 generate_header CStyle LGPLv2plus;
5279 (* This is a public exported header file containing various
5280 * structures. The structures are carefully written to have
5281 * exactly the same in-memory format as the XDR structures that
5282 * we use on the wire to the daemon. The reason for creating
5283 * copies of these structures here is just so we don't have to
5284 * export the whole of guestfs_protocol.h (which includes much
5285 * unrelated and XDR-dependent stuff that we don't want to be
5286 * public, or required by clients).
5288 * To reiterate, we will pass these structures to and from the
5289 * client with a simple assignment or memcpy, so the format
5290 * must be identical to what rpcgen / the RFC defines.
5293 (* Public structures. *)
5296 pr "struct guestfs_%s {\n" typ;
5299 | name, FChar -> pr " char %s;\n" name
5300 | name, FString -> pr " char *%s;\n" name
5302 pr " uint32_t %s_len;\n" name;
5303 pr " char *%s;\n" name
5304 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5305 | name, FUInt32 -> pr " uint32_t %s;\n" name
5306 | name, FInt32 -> pr " int32_t %s;\n" name
5307 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5308 | name, FInt64 -> pr " int64_t %s;\n" name
5309 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5313 pr "struct guestfs_%s_list {\n" typ;
5314 pr " uint32_t len;\n";
5315 pr " struct guestfs_%s *val;\n" typ;
5318 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5319 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5323 (* Generate the guestfs-actions.h file. *)
5324 and generate_actions_h () =
5325 generate_header CStyle LGPLv2plus;
5327 fun (shortname, style, _, _, _, _, _) ->
5328 let name = "guestfs_" ^ shortname in
5329 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5333 (* Generate the guestfs-internal-actions.h file. *)
5334 and generate_internal_actions_h () =
5335 generate_header CStyle LGPLv2plus;
5337 fun (shortname, style, _, _, _, _, _) ->
5338 let name = "guestfs__" ^ shortname in
5339 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5341 ) non_daemon_functions
5343 (* Generate the client-side dispatch stubs. *)
5344 and generate_client_actions () =
5345 generate_header CStyle LGPLv2plus;
5351 #include <inttypes.h>
5353 #include \"guestfs.h\"
5354 #include \"guestfs-internal.h\"
5355 #include \"guestfs-internal-actions.h\"
5356 #include \"guestfs_protocol.h\"
5358 #define error guestfs_error
5359 //#define perrorf guestfs_perrorf
5360 #define safe_malloc guestfs_safe_malloc
5361 #define safe_realloc guestfs_safe_realloc
5362 //#define safe_strdup guestfs_safe_strdup
5363 #define safe_memdup guestfs_safe_memdup
5365 /* Check the return message from a call for validity. */
5367 check_reply_header (guestfs_h *g,
5368 const struct guestfs_message_header *hdr,
5369 unsigned int proc_nr, unsigned int serial)
5371 if (hdr->prog != GUESTFS_PROGRAM) {
5372 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5375 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5376 error (g, \"wrong protocol version (%%d/%%d)\",
5377 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5380 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5381 error (g, \"unexpected message direction (%%d/%%d)\",
5382 hdr->direction, GUESTFS_DIRECTION_REPLY);
5385 if (hdr->proc != proc_nr) {
5386 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5389 if (hdr->serial != serial) {
5390 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5397 /* Check we are in the right state to run a high-level action. */
5399 check_state (guestfs_h *g, const char *caller)
5401 if (!guestfs__is_ready (g)) {
5402 if (guestfs__is_config (g) || guestfs__is_launching (g))
5403 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5406 error (g, \"%%s called from the wrong state, %%d != READY\",
5407 caller, guestfs__get_state (g));
5415 (* Generate code to generate guestfish call traces. *)
5416 let trace_call shortname style =
5417 pr " if (guestfs__get_trace (g)) {\n";
5420 List.exists (function
5421 | StringList _ | DeviceList _ -> true
5422 | _ -> false) (snd style) in
5428 pr " printf (\"%s\");\n" shortname;
5431 | String n (* strings *)
5437 (* guestfish doesn't support string escaping, so neither do we *)
5438 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5439 | OptString n -> (* string option *)
5440 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5441 pr " else printf (\" null\");\n"
5443 | DeviceList n -> (* string list *)
5444 pr " putchar (' ');\n";
5445 pr " putchar ('\"');\n";
5446 pr " for (i = 0; %s[i]; ++i) {\n" n;
5447 pr " if (i > 0) putchar (' ');\n";
5448 pr " fputs (%s[i], stdout);\n" n;
5450 pr " putchar ('\"');\n";
5451 | Bool n -> (* boolean *)
5452 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5453 | Int n -> (* int *)
5454 pr " printf (\" %%d\", %s);\n" n
5456 pr " printf (\" %%\" PRIi64, %s);\n" n
5458 pr " putchar ('\\n');\n";
5463 (* For non-daemon functions, generate a wrapper around each function. *)
5465 fun (shortname, style, _, _, _, _, _) ->
5466 let name = "guestfs_" ^ shortname in
5468 generate_prototype ~extern:false ~semicolon:false ~newline:true
5469 ~handle:"g" name style;
5471 trace_call shortname style;
5472 pr " return guestfs__%s " shortname;
5473 generate_c_call_args ~handle:"g" style;
5477 ) non_daemon_functions;
5479 (* Client-side stubs for each function. *)
5481 fun (shortname, style, _, _, _, _, _) ->
5482 let name = "guestfs_" ^ shortname in
5484 (* Generate the action stub. *)
5485 generate_prototype ~extern:false ~semicolon:false ~newline:true
5486 ~handle:"g" name style;
5489 match fst style with
5490 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5491 | RConstString _ | RConstOptString _ ->
5492 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5493 | RString _ | RStringList _
5494 | RStruct _ | RStructList _
5495 | RHashtable _ | RBufferOut _ ->
5500 (match snd style with
5502 | _ -> pr " struct %s_args args;\n" name
5505 pr " guestfs_message_header hdr;\n";
5506 pr " guestfs_message_error err;\n";
5508 match fst style with
5510 | RConstString _ | RConstOptString _ ->
5511 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5513 | RBool _ | RString _ | RStringList _
5514 | RStruct _ | RStructList _
5515 | RHashtable _ | RBufferOut _ ->
5516 pr " struct %s_ret ret;\n" name;
5519 pr " int serial;\n";
5522 trace_call shortname style;
5523 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5524 pr " guestfs___set_busy (g);\n";
5527 (* Send the main header and arguments. *)
5528 (match snd style with
5530 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5531 (String.uppercase shortname)
5535 | Pathname n | Device n | Dev_or_Path n | String n ->
5536 pr " args.%s = (char *) %s;\n" n n
5538 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5539 | StringList n | DeviceList n ->
5540 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5541 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5543 pr " args.%s = %s;\n" n n
5545 pr " args.%s = %s;\n" n n
5547 pr " args.%s = %s;\n" n n
5548 | FileIn _ | FileOut _ -> ()
5550 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5551 (String.uppercase shortname);
5552 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5555 pr " if (serial == -1) {\n";
5556 pr " guestfs___end_busy (g);\n";
5557 pr " return %s;\n" error_code;
5561 (* Send any additional files (FileIn) requested. *)
5562 let need_read_reply_label = ref false in
5566 pr " r = guestfs___send_file (g, %s);\n" n;
5567 pr " if (r == -1) {\n";
5568 pr " guestfs___end_busy (g);\n";
5569 pr " return %s;\n" error_code;
5571 pr " if (r == -2) /* daemon cancelled */\n";
5572 pr " goto read_reply;\n";
5573 need_read_reply_label := true;
5578 (* Wait for the reply from the remote end. *)
5579 if !need_read_reply_label then pr " read_reply:\n";
5580 pr " memset (&hdr, 0, sizeof hdr);\n";
5581 pr " memset (&err, 0, sizeof err);\n";
5582 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5584 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5588 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5591 pr " if (r == -1) {\n";
5592 pr " guestfs___end_busy (g);\n";
5593 pr " return %s;\n" error_code;
5597 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5598 (String.uppercase shortname);
5599 pr " guestfs___end_busy (g);\n";
5600 pr " return %s;\n" error_code;
5604 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5605 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5606 pr " free (err.error_message);\n";
5607 pr " guestfs___end_busy (g);\n";
5608 pr " return %s;\n" error_code;
5612 (* Expecting to receive further files (FileOut)? *)
5616 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5617 pr " guestfs___end_busy (g);\n";
5618 pr " return %s;\n" error_code;
5624 pr " guestfs___end_busy (g);\n";
5626 (match fst style with
5627 | RErr -> pr " return 0;\n"
5628 | RInt n | RInt64 n | RBool n ->
5629 pr " return ret.%s;\n" n
5630 | RConstString _ | RConstOptString _ ->
5631 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5633 pr " return ret.%s; /* caller will free */\n" n
5634 | RStringList n | RHashtable n ->
5635 pr " /* caller will free this, but we need to add a NULL entry */\n";
5636 pr " ret.%s.%s_val =\n" n n;
5637 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5638 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5640 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5641 pr " return ret.%s.%s_val;\n" n n
5643 pr " /* caller will free this */\n";
5644 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5645 | RStructList (n, _) ->
5646 pr " /* caller will free this */\n";
5647 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5649 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5650 pr " * _val might be NULL here. To make the API saner for\n";
5651 pr " * callers, we turn this case into a unique pointer (using\n";
5652 pr " * malloc(1)).\n";
5654 pr " if (ret.%s.%s_len > 0) {\n" n n;
5655 pr " *size_r = ret.%s.%s_len;\n" n n;
5656 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5658 pr " free (ret.%s.%s_val);\n" n n;
5659 pr " char *p = safe_malloc (g, 1);\n";
5660 pr " *size_r = ret.%s.%s_len;\n" n n;
5668 (* Functions to free structures. *)
5669 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5670 pr " * structure format is identical to the XDR format. See note in\n";
5671 pr " * generator.ml.\n";
5678 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5680 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5686 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5688 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5695 (* Generate daemon/actions.h. *)
5696 and generate_daemon_actions_h () =
5697 generate_header CStyle GPLv2plus;
5699 pr "#include \"../src/guestfs_protocol.h\"\n";
5703 fun (name, style, _, _, _, _, _) ->
5705 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5709 (* Generate the linker script which controls the visibility of
5710 * symbols in the public ABI and ensures no other symbols get
5711 * exported accidentally.
5713 and generate_linker_script () =
5714 generate_header HashStyle GPLv2plus;
5719 "guestfs_get_error_handler";
5720 "guestfs_get_out_of_memory_handler";
5721 "guestfs_last_error";
5722 "guestfs_set_error_handler";
5723 "guestfs_set_launch_done_callback";
5724 "guestfs_set_log_message_callback";
5725 "guestfs_set_out_of_memory_handler";
5726 "guestfs_set_subprocess_quit_callback";
5728 (* Unofficial parts of the API: the bindings code use these
5729 * functions, so it is useful to export them.
5731 "guestfs_safe_calloc";
5732 "guestfs_safe_malloc";
5735 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5739 List.map (fun (typ, _) ->
5740 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5743 let globals = List.sort compare (globals @ functions @ structs) in
5747 List.iter (pr " %s;\n") globals;
5754 (* Generate the server-side stubs. *)
5755 and generate_daemon_actions () =
5756 generate_header CStyle GPLv2plus;
5758 pr "#include <config.h>\n";
5760 pr "#include <stdio.h>\n";
5761 pr "#include <stdlib.h>\n";
5762 pr "#include <string.h>\n";
5763 pr "#include <inttypes.h>\n";
5764 pr "#include <rpc/types.h>\n";
5765 pr "#include <rpc/xdr.h>\n";
5767 pr "#include \"daemon.h\"\n";
5768 pr "#include \"c-ctype.h\"\n";
5769 pr "#include \"../src/guestfs_protocol.h\"\n";
5770 pr "#include \"actions.h\"\n";
5774 fun (name, style, _, _, _, _, _) ->
5775 (* Generate server-side stubs. *)
5776 pr "static void %s_stub (XDR *xdr_in)\n" name;
5779 match fst style with
5780 | RErr | RInt _ -> pr " int r;\n"; "-1"
5781 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5782 | RBool _ -> pr " int r;\n"; "-1"
5783 | RConstString _ | RConstOptString _ ->
5784 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5785 | RString _ -> pr " char *r;\n"; "NULL"
5786 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5787 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5788 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5790 pr " size_t size = 1;\n";
5794 (match snd style with
5797 pr " struct guestfs_%s_args args;\n" name;
5800 | Device n | Dev_or_Path n
5803 | OptString n -> pr " char *%s;\n" n
5804 | StringList n | DeviceList n -> pr " char **%s;\n" n
5805 | Bool n -> pr " int %s;\n" n
5806 | Int n -> pr " int %s;\n" n
5807 | Int64 n -> pr " int64_t %s;\n" n
5808 | FileIn _ | FileOut _ -> ()
5813 (match snd style with
5816 pr " memset (&args, 0, sizeof args);\n";
5818 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5819 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5823 pr " char *%s = args.%s;\n" n n
5825 let pr_list_handling_code n =
5826 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5827 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5828 pr " if (%s == NULL) {\n" n;
5829 pr " reply_with_perror (\"realloc\");\n";
5832 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5833 pr " args.%s.%s_val = %s;\n" n n n;
5839 pr " ABS_PATH (%s, goto done);\n" n;
5842 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5845 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5846 | String n -> pr_args n
5847 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5849 pr_list_handling_code n;
5851 pr_list_handling_code n;
5852 pr " /* Ensure that each is a device,\n";
5853 pr " * and perform device name translation. */\n";
5854 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5855 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5857 | Bool n -> pr " %s = args.%s;\n" n n
5858 | Int n -> pr " %s = args.%s;\n" n n
5859 | Int64 n -> pr " %s = args.%s;\n" n n
5860 | FileIn _ | FileOut _ -> ()
5866 (* this is used at least for do_equal *)
5867 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5868 (* Emit NEED_ROOT just once, even when there are two or
5869 more Pathname args *)
5870 pr " NEED_ROOT (goto done);\n";
5873 (* Don't want to call the impl with any FileIn or FileOut
5874 * parameters, since these go "outside" the RPC protocol.
5877 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5879 pr " r = do_%s " name;
5880 generate_c_call_args (fst style, args');
5883 (match fst style with
5884 | RErr | RInt _ | RInt64 _ | RBool _
5885 | RConstString _ | RConstOptString _
5886 | RString _ | RStringList _ | RHashtable _
5887 | RStruct (_, _) | RStructList (_, _) ->
5888 pr " if (r == %s)\n" error_code;
5889 pr " /* do_%s has already called reply_with_error */\n" name;
5893 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
5894 pr " * an ordinary zero-length buffer), so be careful ...\n";
5896 pr " if (size == 1 && r == %s)\n" error_code;
5897 pr " /* do_%s has already called reply_with_error */\n" name;
5902 (* If there are any FileOut parameters, then the impl must
5903 * send its own reply.
5906 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5908 pr " /* do_%s has already sent a reply */\n" name
5910 match fst style with
5911 | RErr -> pr " reply (NULL, NULL);\n"
5912 | RInt n | RInt64 n | RBool n ->
5913 pr " struct guestfs_%s_ret ret;\n" name;
5914 pr " ret.%s = r;\n" n;
5915 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5917 | RConstString _ | RConstOptString _ ->
5918 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5920 pr " struct guestfs_%s_ret ret;\n" name;
5921 pr " ret.%s = r;\n" n;
5922 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5925 | RStringList n | RHashtable n ->
5926 pr " struct guestfs_%s_ret ret;\n" name;
5927 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5928 pr " ret.%s.%s_val = r;\n" n n;
5929 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5931 pr " free_strings (r);\n"
5933 pr " struct guestfs_%s_ret ret;\n" name;
5934 pr " ret.%s = *r;\n" n;
5935 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5937 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5939 | RStructList (n, _) ->
5940 pr " struct guestfs_%s_ret ret;\n" name;
5941 pr " ret.%s = *r;\n" n;
5942 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5944 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5947 pr " struct guestfs_%s_ret ret;\n" name;
5948 pr " ret.%s.%s_val = r;\n" n n;
5949 pr " ret.%s.%s_len = size;\n" n n;
5950 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5955 (* Free the args. *)
5956 (match snd style with
5961 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5968 (* Dispatch function. *)
5969 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5971 pr " switch (proc_nr) {\n";
5974 fun (name, style, _, _, _, _, _) ->
5975 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5976 pr " %s_stub (xdr_in);\n" name;
5981 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";
5986 (* LVM columns and tokenization functions. *)
5987 (* XXX This generates crap code. We should rethink how we
5993 pr "static const char *lvm_%s_cols = \"%s\";\n"
5994 typ (String.concat "," (List.map fst cols));
5997 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5999 pr " char *tok, *p, *next;\n";
6003 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6006 pr " if (!str) {\n";
6007 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6010 pr " if (!*str || c_isspace (*str)) {\n";
6011 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6016 fun (name, coltype) ->
6017 pr " if (!tok) {\n";
6018 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6021 pr " p = strchrnul (tok, ',');\n";
6022 pr " if (*p) next = p+1; else next = NULL;\n";
6023 pr " *p = '\\0';\n";
6026 pr " r->%s = strdup (tok);\n" name;
6027 pr " if (r->%s == NULL) {\n" name;
6028 pr " perror (\"strdup\");\n";
6032 pr " for (i = j = 0; i < 32; ++j) {\n";
6033 pr " if (tok[j] == '\\0') {\n";
6034 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6036 pr " } else if (tok[j] != '-')\n";
6037 pr " r->%s[i++] = tok[j];\n" name;
6040 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6041 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6045 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6046 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6050 pr " if (tok[0] == '\\0')\n";
6051 pr " r->%s = -1;\n" name;
6052 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6053 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6056 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6057 assert false (* can never be an LVM column *)
6059 pr " tok = next;\n";
6062 pr " if (tok != NULL) {\n";
6063 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6070 pr "guestfs_int_lvm_%s_list *\n" typ;
6071 pr "parse_command_line_%ss (void)\n" typ;
6073 pr " char *out, *err;\n";
6074 pr " char *p, *pend;\n";
6076 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6077 pr " void *newp;\n";
6079 pr " ret = malloc (sizeof *ret);\n";
6080 pr " if (!ret) {\n";
6081 pr " reply_with_perror (\"malloc\");\n";
6082 pr " return NULL;\n";
6085 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6086 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6088 pr " r = command (&out, &err,\n";
6089 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
6090 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6091 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6092 pr " if (r == -1) {\n";
6093 pr " reply_with_error (\"%%s\", err);\n";
6094 pr " free (out);\n";
6095 pr " free (err);\n";
6096 pr " free (ret);\n";
6097 pr " return NULL;\n";
6100 pr " free (err);\n";
6102 pr " /* Tokenize each line of the output. */\n";
6105 pr " while (p) {\n";
6106 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6107 pr " if (pend) {\n";
6108 pr " *pend = '\\0';\n";
6112 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6115 pr " if (!*p) { /* Empty line? Skip it. */\n";
6120 pr " /* Allocate some space to store this next entry. */\n";
6121 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6122 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6123 pr " if (newp == NULL) {\n";
6124 pr " reply_with_perror (\"realloc\");\n";
6125 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6126 pr " free (ret);\n";
6127 pr " free (out);\n";
6128 pr " return NULL;\n";
6130 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6132 pr " /* Tokenize the next entry. */\n";
6133 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6134 pr " if (r == -1) {\n";
6135 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6136 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6137 pr " free (ret);\n";
6138 pr " free (out);\n";
6139 pr " return NULL;\n";
6146 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6148 pr " free (out);\n";
6149 pr " return ret;\n";
6152 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6154 (* Generate a list of function names, for debugging in the daemon.. *)
6155 and generate_daemon_names () =
6156 generate_header CStyle GPLv2plus;
6158 pr "#include <config.h>\n";
6160 pr "#include \"daemon.h\"\n";
6163 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6164 pr "const char *function_names[] = {\n";
6166 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6170 (* Generate the optional groups for the daemon to implement
6171 * guestfs_available.
6173 and generate_daemon_optgroups_c () =
6174 generate_header CStyle GPLv2plus;
6176 pr "#include <config.h>\n";
6178 pr "#include \"daemon.h\"\n";
6179 pr "#include \"optgroups.h\"\n";
6182 pr "struct optgroup optgroups[] = {\n";
6185 pr " { \"%s\", optgroup_%s_available },\n" group group
6187 pr " { NULL, NULL }\n";
6190 and generate_daemon_optgroups_h () =
6191 generate_header CStyle GPLv2plus;
6195 pr "extern int optgroup_%s_available (void);\n" group
6198 (* Generate the tests. *)
6199 and generate_tests () =
6200 generate_header CStyle GPLv2plus;
6207 #include <sys/types.h>
6210 #include \"guestfs.h\"
6211 #include \"guestfs-internal.h\"
6213 static guestfs_h *g;
6214 static int suppress_error = 0;
6216 static void print_error (guestfs_h *g, void *data, const char *msg)
6218 if (!suppress_error)
6219 fprintf (stderr, \"%%s\\n\", msg);
6222 /* FIXME: nearly identical code appears in fish.c */
6223 static void print_strings (char *const *argv)
6227 for (argc = 0; argv[argc] != NULL; ++argc)
6228 printf (\"\\t%%s\\n\", argv[argc]);
6232 static void print_table (char const *const *argv)
6236 for (i = 0; argv[i] != NULL; i += 2)
6237 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6243 (* Generate a list of commands which are not tested anywhere. *)
6244 pr "static void no_test_warnings (void)\n";
6247 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6249 fun (_, _, _, _, tests, _, _) ->
6250 let tests = filter_map (
6252 | (_, (Always|If _|Unless _), test) -> Some test
6253 | (_, Disabled, _) -> None
6255 let seq = List.concat (List.map seq_of_test tests) in
6256 let cmds_tested = List.map List.hd seq in
6257 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6261 fun (name, _, _, _, _, _, _) ->
6262 if not (Hashtbl.mem hash name) then
6263 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6269 (* Generate the actual tests. Note that we generate the tests
6270 * in reverse order, deliberately, so that (in general) the
6271 * newest tests run first. This makes it quicker and easier to
6276 fun (name, _, _, flags, tests, _, _) ->
6277 mapi (generate_one_test name flags) tests
6278 ) (List.rev all_functions) in
6279 let test_names = List.concat test_names in
6280 let nr_tests = List.length test_names in
6283 int main (int argc, char *argv[])
6286 unsigned long int n_failed = 0;
6287 const char *filename;
6289 int nr_tests, test_num = 0;
6291 setbuf (stdout, NULL);
6293 no_test_warnings ();
6295 g = guestfs_create ();
6297 printf (\"guestfs_create FAILED\\n\");
6298 exit (EXIT_FAILURE);
6301 guestfs_set_error_handler (g, print_error, NULL);
6303 guestfs_set_path (g, \"../appliance\");
6305 filename = \"test1.img\";
6306 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6309 exit (EXIT_FAILURE);
6311 if (lseek (fd, %d, SEEK_SET) == -1) {
6315 exit (EXIT_FAILURE);
6317 if (write (fd, &c, 1) == -1) {
6321 exit (EXIT_FAILURE);
6323 if (close (fd) == -1) {
6326 exit (EXIT_FAILURE);
6328 if (guestfs_add_drive (g, filename) == -1) {
6329 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6330 exit (EXIT_FAILURE);
6333 filename = \"test2.img\";
6334 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6337 exit (EXIT_FAILURE);
6339 if (lseek (fd, %d, SEEK_SET) == -1) {
6343 exit (EXIT_FAILURE);
6345 if (write (fd, &c, 1) == -1) {
6349 exit (EXIT_FAILURE);
6351 if (close (fd) == -1) {
6354 exit (EXIT_FAILURE);
6356 if (guestfs_add_drive (g, filename) == -1) {
6357 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6358 exit (EXIT_FAILURE);
6361 filename = \"test3.img\";
6362 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6365 exit (EXIT_FAILURE);
6367 if (lseek (fd, %d, SEEK_SET) == -1) {
6371 exit (EXIT_FAILURE);
6373 if (write (fd, &c, 1) == -1) {
6377 exit (EXIT_FAILURE);
6379 if (close (fd) == -1) {
6382 exit (EXIT_FAILURE);
6384 if (guestfs_add_drive (g, filename) == -1) {
6385 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6386 exit (EXIT_FAILURE);
6389 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6390 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6391 exit (EXIT_FAILURE);
6394 if (guestfs_launch (g) == -1) {
6395 printf (\"guestfs_launch FAILED\\n\");
6396 exit (EXIT_FAILURE);
6399 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6402 /* Cancel previous alarm. */
6407 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6411 pr " test_num++;\n";
6412 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6413 pr " if (%s () == -1) {\n" test_name;
6414 pr " printf (\"%s FAILED\\n\");\n" test_name;
6415 pr " n_failed++;\n";
6420 pr " guestfs_close (g);\n";
6421 pr " unlink (\"test1.img\");\n";
6422 pr " unlink (\"test2.img\");\n";
6423 pr " unlink (\"test3.img\");\n";
6426 pr " if (n_failed > 0) {\n";
6427 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6428 pr " exit (EXIT_FAILURE);\n";
6432 pr " exit (EXIT_SUCCESS);\n";
6435 and generate_one_test name flags i (init, prereq, test) =
6436 let test_name = sprintf "test_%s_%d" name i in
6439 static int %s_skip (void)
6443 str = getenv (\"TEST_ONLY\");
6445 return strstr (str, \"%s\") == NULL;
6446 str = getenv (\"SKIP_%s\");
6447 if (str && STREQ (str, \"1\")) return 1;
6448 str = getenv (\"SKIP_TEST_%s\");
6449 if (str && STREQ (str, \"1\")) return 1;
6453 " test_name name (String.uppercase test_name) (String.uppercase name);
6456 | Disabled | Always -> ()
6457 | If code | Unless code ->
6458 pr "static int %s_prereq (void)\n" test_name;
6466 static int %s (void)
6469 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6473 " test_name test_name test_name;
6475 (* Optional functions should only be tested if the relevant
6476 * support is available in the daemon.
6482 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6484 pr " suppress_error = 1;\n";
6485 pr " r = guestfs_available (g, (char **) groups);\n";
6486 pr " suppress_error = 0;\n";
6487 pr " if (r == -1) {\n";
6488 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6497 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6499 pr " if (! %s_prereq ()) {\n" test_name;
6500 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6504 generate_one_test_body name i test_name init test;
6506 pr " if (%s_prereq ()) {\n" test_name;
6507 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6511 generate_one_test_body name i test_name init test;
6513 generate_one_test_body name i test_name init test
6521 and generate_one_test_body name i test_name init test =
6523 | InitNone (* XXX at some point, InitNone and InitEmpty became
6524 * folded together as the same thing. Really we should
6525 * make InitNone do nothing at all, but the tests may
6526 * need to be checked to make sure this is OK.
6529 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6530 List.iter (generate_test_command_call test_name)
6531 [["blockdev_setrw"; "/dev/sda"];
6535 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6536 List.iter (generate_test_command_call test_name)
6537 [["blockdev_setrw"; "/dev/sda"];
6540 ["part_disk"; "/dev/sda"; "mbr"]]
6542 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6543 List.iter (generate_test_command_call test_name)
6544 [["blockdev_setrw"; "/dev/sda"];
6547 ["part_disk"; "/dev/sda"; "mbr"];
6548 ["mkfs"; "ext2"; "/dev/sda1"];
6549 ["mount_options"; ""; "/dev/sda1"; "/"]]
6550 | InitBasicFSonLVM ->
6551 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6553 List.iter (generate_test_command_call test_name)
6554 [["blockdev_setrw"; "/dev/sda"];
6557 ["part_disk"; "/dev/sda"; "mbr"];
6558 ["pvcreate"; "/dev/sda1"];
6559 ["vgcreate"; "VG"; "/dev/sda1"];
6560 ["lvcreate"; "LV"; "VG"; "8"];
6561 ["mkfs"; "ext2"; "/dev/VG/LV"];
6562 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6564 pr " /* InitISOFS for %s */\n" test_name;
6565 List.iter (generate_test_command_call test_name)
6566 [["blockdev_setrw"; "/dev/sda"];
6569 ["mount_ro"; "/dev/sdd"; "/"]]
6572 let get_seq_last = function
6574 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6577 let seq = List.rev seq in
6578 List.rev (List.tl seq), List.hd seq
6583 pr " /* TestRun for %s (%d) */\n" name i;
6584 List.iter (generate_test_command_call test_name) seq
6585 | TestOutput (seq, expected) ->
6586 pr " /* TestOutput for %s (%d) */\n" name i;
6587 pr " const char *expected = \"%s\";\n" (c_quote expected);
6588 let seq, last = get_seq_last seq in
6590 pr " if (STRNEQ (r, expected)) {\n";
6591 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6595 List.iter (generate_test_command_call test_name) seq;
6596 generate_test_command_call ~test test_name last
6597 | TestOutputList (seq, expected) ->
6598 pr " /* TestOutputList for %s (%d) */\n" name i;
6599 let seq, last = get_seq_last seq in
6603 pr " if (!r[%d]) {\n" i;
6604 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6605 pr " print_strings (r);\n";
6609 pr " const char *expected = \"%s\";\n" (c_quote str);
6610 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6611 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6616 pr " if (r[%d] != NULL) {\n" (List.length expected);
6617 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6619 pr " print_strings (r);\n";
6623 List.iter (generate_test_command_call test_name) seq;
6624 generate_test_command_call ~test test_name last
6625 | TestOutputListOfDevices (seq, expected) ->
6626 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6627 let seq, last = get_seq_last seq in
6631 pr " if (!r[%d]) {\n" i;
6632 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6633 pr " print_strings (r);\n";
6637 pr " const char *expected = \"%s\";\n" (c_quote str);
6638 pr " r[%d][5] = 's';\n" i;
6639 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6640 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6645 pr " if (r[%d] != NULL) {\n" (List.length expected);
6646 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6648 pr " print_strings (r);\n";
6652 List.iter (generate_test_command_call test_name) seq;
6653 generate_test_command_call ~test test_name last
6654 | TestOutputInt (seq, expected) ->
6655 pr " /* TestOutputInt for %s (%d) */\n" name i;
6656 let seq, last = get_seq_last seq in
6658 pr " if (r != %d) {\n" expected;
6659 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6665 List.iter (generate_test_command_call test_name) seq;
6666 generate_test_command_call ~test test_name last
6667 | TestOutputIntOp (seq, op, expected) ->
6668 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6669 let seq, last = get_seq_last seq in
6671 pr " if (! (r %s %d)) {\n" op expected;
6672 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6673 test_name op expected;
6678 List.iter (generate_test_command_call test_name) seq;
6679 generate_test_command_call ~test test_name last
6680 | TestOutputTrue seq ->
6681 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6682 let seq, last = get_seq_last seq in
6685 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6690 List.iter (generate_test_command_call test_name) seq;
6691 generate_test_command_call ~test test_name last
6692 | TestOutputFalse seq ->
6693 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6694 let seq, last = get_seq_last seq in
6697 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6702 List.iter (generate_test_command_call test_name) seq;
6703 generate_test_command_call ~test test_name last
6704 | TestOutputLength (seq, expected) ->
6705 pr " /* TestOutputLength for %s (%d) */\n" name i;
6706 let seq, last = get_seq_last seq in
6709 pr " for (j = 0; j < %d; ++j)\n" expected;
6710 pr " if (r[j] == NULL) {\n";
6711 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6713 pr " print_strings (r);\n";
6716 pr " if (r[j] != NULL) {\n";
6717 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6719 pr " print_strings (r);\n";
6723 List.iter (generate_test_command_call test_name) seq;
6724 generate_test_command_call ~test test_name last
6725 | TestOutputBuffer (seq, expected) ->
6726 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6727 pr " const char *expected = \"%s\";\n" (c_quote expected);
6728 let seq, last = get_seq_last seq in
6729 let len = String.length expected in
6731 pr " if (size != %d) {\n" len;
6732 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6735 pr " if (STRNEQLEN (r, expected, size)) {\n";
6736 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6740 List.iter (generate_test_command_call test_name) seq;
6741 generate_test_command_call ~test test_name last
6742 | TestOutputStruct (seq, checks) ->
6743 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6744 let seq, last = get_seq_last seq in
6748 | CompareWithInt (field, expected) ->
6749 pr " if (r->%s != %d) {\n" field expected;
6750 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6751 test_name field expected;
6752 pr " (int) r->%s);\n" field;
6755 | CompareWithIntOp (field, op, expected) ->
6756 pr " if (!(r->%s %s %d)) {\n" field op expected;
6757 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6758 test_name field op expected;
6759 pr " (int) r->%s);\n" field;
6762 | CompareWithString (field, expected) ->
6763 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6764 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6765 test_name field expected;
6766 pr " r->%s);\n" field;
6769 | CompareFieldsIntEq (field1, field2) ->
6770 pr " if (r->%s != r->%s) {\n" field1 field2;
6771 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6772 test_name field1 field2;
6773 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6776 | CompareFieldsStrEq (field1, field2) ->
6777 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6778 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6779 test_name field1 field2;
6780 pr " r->%s, r->%s);\n" field1 field2;
6785 List.iter (generate_test_command_call test_name) seq;
6786 generate_test_command_call ~test test_name last
6787 | TestLastFail seq ->
6788 pr " /* TestLastFail for %s (%d) */\n" name i;
6789 let seq, last = get_seq_last seq in
6790 List.iter (generate_test_command_call test_name) seq;
6791 generate_test_command_call test_name ~expect_error:true last
6793 (* Generate the code to run a command, leaving the result in 'r'.
6794 * If you expect to get an error then you should set expect_error:true.
6796 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6798 | [] -> assert false
6800 (* Look up the command to find out what args/ret it has. *)
6803 let _, style, _, _, _, _, _ =
6804 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6807 failwithf "%s: in test, command %s was not found" test_name name in
6809 if List.length (snd style) <> List.length args then
6810 failwithf "%s: in test, wrong number of args given to %s"
6817 | OptString n, "NULL" -> ()
6820 | Dev_or_Path n, arg
6822 | OptString n, arg ->
6823 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6827 | FileIn _, _ | FileOut _, _ -> ()
6828 | StringList n, "" | DeviceList n, "" ->
6829 pr " const char *const %s[1] = { NULL };\n" n
6830 | StringList n, arg | DeviceList n, arg ->
6831 let strs = string_split " " arg in
6834 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
6836 pr " const char *const %s[] = {\n" n;
6838 fun i _ -> pr " %s_%d,\n" n i
6842 ) (List.combine (snd style) args);
6845 match fst style with
6846 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6847 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6848 | RConstString _ | RConstOptString _ ->
6849 pr " const char *r;\n"; "NULL"
6850 | RString _ -> pr " char *r;\n"; "NULL"
6851 | RStringList _ | RHashtable _ ->
6855 | RStruct (_, typ) ->
6856 pr " struct guestfs_%s *r;\n" typ; "NULL"
6857 | RStructList (_, typ) ->
6858 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6861 pr " size_t size;\n";
6864 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
6865 pr " r = guestfs_%s (g" name;
6867 (* Generate the parameters. *)
6870 | OptString _, "NULL" -> pr ", NULL"
6872 | Device n, _ | Dev_or_Path n, _
6876 | FileIn _, arg | FileOut _, arg ->
6877 pr ", \"%s\"" (c_quote arg)
6878 | StringList n, _ | DeviceList n, _ ->
6879 pr ", (char **) %s" n
6882 try int_of_string arg
6883 with Failure "int_of_string" ->
6884 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6888 try Int64.of_string arg
6889 with Failure "int_of_string" ->
6890 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6893 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6894 ) (List.combine (snd style) args);
6896 (match fst style with
6897 | RBufferOut _ -> pr ", &size"
6903 if not expect_error then
6904 pr " if (r == %s)\n" error_code
6906 pr " if (r != %s)\n" error_code;
6909 (* Insert the test code. *)
6915 (match fst style with
6916 | RErr | RInt _ | RInt64 _ | RBool _
6917 | RConstString _ | RConstOptString _ -> ()
6918 | RString _ | RBufferOut _ -> pr " free (r);\n"
6919 | RStringList _ | RHashtable _ ->
6920 pr " for (i = 0; r[i] != NULL; ++i)\n";
6921 pr " free (r[i]);\n";
6923 | RStruct (_, typ) ->
6924 pr " guestfs_free_%s (r);\n" typ
6925 | RStructList (_, typ) ->
6926 pr " guestfs_free_%s_list (r);\n" typ
6932 let str = replace_str str "\r" "\\r" in
6933 let str = replace_str str "\n" "\\n" in
6934 let str = replace_str str "\t" "\\t" in
6935 let str = replace_str str "\000" "\\0" in
6938 (* Generate a lot of different functions for guestfish. *)
6939 and generate_fish_cmds () =
6940 generate_header CStyle GPLv2plus;
6944 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6946 let all_functions_sorted =
6948 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6949 ) all_functions_sorted in
6951 pr "#include <config.h>\n";
6953 pr "#include <stdio.h>\n";
6954 pr "#include <stdlib.h>\n";
6955 pr "#include <string.h>\n";
6956 pr "#include <inttypes.h>\n";
6958 pr "#include <guestfs.h>\n";
6959 pr "#include \"c-ctype.h\"\n";
6960 pr "#include \"full-write.h\"\n";
6961 pr "#include \"xstrtol.h\"\n";
6962 pr "#include \"fish.h\"\n";
6965 (* list_commands function, which implements guestfish -h *)
6966 pr "void list_commands (void)\n";
6968 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6969 pr " list_builtin_commands ();\n";
6971 fun (name, _, _, flags, _, shortdesc, _) ->
6972 let name = replace_char name '_' '-' in
6973 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6975 ) all_functions_sorted;
6976 pr " printf (\" %%s\\n\",";
6977 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6981 (* display_command function, which implements guestfish -h cmd *)
6982 pr "void display_command (const char *cmd)\n";
6985 fun (name, style, _, flags, _, shortdesc, longdesc) ->
6986 let name2 = replace_char name '_' '-' in
6988 try find_map (function FishAlias n -> Some n | _ -> None) flags
6989 with Not_found -> name in
6990 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6992 match snd style with
6996 name2 (String.concat " " (List.map name_of_argt args)) in
6999 if List.mem ProtocolLimitWarning flags then
7000 ("\n\n" ^ protocol_limit_warning)
7003 (* For DangerWillRobinson commands, we should probably have
7004 * guestfish prompt before allowing you to use them (especially
7005 * in interactive mode). XXX
7009 if List.mem DangerWillRobinson flags then
7010 ("\n\n" ^ danger_will_robinson)
7015 match deprecation_notice flags with
7017 | Some txt -> "\n\n" ^ txt in
7019 let describe_alias =
7020 if name <> alias then
7021 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7025 pr "STRCASEEQ (cmd, \"%s\")" name;
7026 if name <> name2 then
7027 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7028 if name <> alias then
7029 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7031 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7033 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7034 "=head1 DESCRIPTION\n\n" ^
7035 longdesc ^ warnings ^ describe_alias);
7038 pr " display_builtin_command (cmd);\n";
7042 let emit_print_list_function typ =
7043 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7046 pr " unsigned int i;\n";
7048 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7049 pr " printf (\"[%%d] = {\\n\", i);\n";
7050 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7051 pr " printf (\"}\\n\");\n";
7057 (* print_* functions *)
7061 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7063 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7066 pr " unsigned int i;\n";
7072 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7074 pr " printf (\"%%s%s: \", indent);\n" name;
7075 pr " for (i = 0; i < 32; ++i)\n";
7076 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7077 pr " printf (\"\\n\");\n"
7079 pr " printf (\"%%s%s: \", indent);\n" name;
7080 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7081 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7082 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7084 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7085 pr " printf (\"\\n\");\n"
7086 | name, (FUInt64|FBytes) ->
7087 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7090 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7093 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7096 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7099 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7101 | name, FOptPercent ->
7102 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7103 typ name name typ name;
7104 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7110 (* Emit a print_TYPE_list function definition only if that function is used. *)
7113 | typ, (RStructListOnly | RStructAndList) ->
7114 (* generate the function for typ *)
7115 emit_print_list_function typ
7116 | typ, _ -> () (* empty *)
7117 ) (rstructs_used_by all_functions);
7119 (* Emit a print_TYPE function definition only if that function is used. *)
7122 | typ, (RStructOnly | RStructAndList) ->
7123 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7125 pr " print_%s_indent (%s, \"\");\n" typ typ;
7128 | typ, _ -> () (* empty *)
7129 ) (rstructs_used_by all_functions);
7131 (* run_<action> actions *)
7133 fun (name, style, _, flags, _, _, _) ->
7134 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7136 (match fst style with
7139 | RBool _ -> pr " int r;\n"
7140 | RInt64 _ -> pr " int64_t r;\n"
7141 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7142 | RString _ -> pr " char *r;\n"
7143 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7144 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7145 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7148 pr " size_t size;\n";
7156 | FileOut n -> pr " const char *%s;\n" n
7158 | Dev_or_Path n -> pr " char *%s;\n" n
7159 | StringList n | DeviceList n -> pr " char **%s;\n" n
7160 | Bool n -> pr " int %s;\n" n
7161 | Int n -> pr " int %s;\n" n
7162 | Int64 n -> pr " int64_t %s;\n" n
7165 (* Check and convert parameters. *)
7166 let argc_expected = List.length (snd style) in
7167 pr " if (argc != %d) {\n" argc_expected;
7168 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7170 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7174 let parse_integer fn fntyp rtyp range name i =
7176 pr " strtol_error xerr;\n";
7177 pr " %s r;\n" fntyp;
7179 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7180 pr " if (xerr != LONGINT_OK) {\n";
7181 pr " fprintf (stderr,\n";
7182 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7183 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7188 | Some (min, max, comment) ->
7189 pr " /* %s */\n" comment;
7190 pr " if (r < %s || r > %s) {\n" min max;
7191 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7195 pr " /* The check above should ensure this assignment does not overflow. */\n";
7197 pr " %s = r;\n" name;
7206 pr " %s = argv[%d];\n" name i
7208 | Dev_or_Path name ->
7209 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7210 pr " if (%s == NULL) return -1;\n" name
7212 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7215 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7218 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7220 | StringList name | DeviceList name ->
7221 pr " %s = parse_string_list (argv[%d]);\n" name i;
7222 pr " if (%s == NULL) return -1;\n" name;
7224 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7227 let min = "(-(2LL<<30))"
7228 and max = "((2LL<<30)-1)"
7230 "The Int type in the generator is a signed 31 bit int." in
7231 Some (min, max, comment) in
7232 parse_integer "xstrtoll" "long long" "int" range name i
7234 parse_integer "xstrtoll" "long long" "int64_t" None name i
7237 (* Call C API function. *)
7239 try find_map (function FishAction n -> Some n | _ -> None) flags
7240 with Not_found -> sprintf "guestfs_%s" name in
7242 generate_c_call_args ~handle:"g" style;
7247 | Device name | String name
7248 | OptString name | FileIn name | FileOut name | Bool name
7249 | Int name | Int64 name -> ()
7250 | Pathname name | Dev_or_Path name ->
7251 pr " free (%s);\n" name
7252 | StringList name | DeviceList name ->
7253 pr " free_strings (%s);\n" name
7256 (* Check return value for errors and display command results. *)
7257 (match fst style with
7258 | RErr -> pr " return r;\n"
7260 pr " if (r == -1) return -1;\n";
7261 pr " printf (\"%%d\\n\", r);\n";
7264 pr " if (r == -1) return -1;\n";
7265 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7268 pr " if (r == -1) return -1;\n";
7269 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7272 pr " if (r == NULL) return -1;\n";
7273 pr " printf (\"%%s\\n\", r);\n";
7275 | RConstOptString _ ->
7276 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7279 pr " if (r == NULL) return -1;\n";
7280 pr " printf (\"%%s\\n\", r);\n";
7284 pr " if (r == NULL) return -1;\n";
7285 pr " print_strings (r);\n";
7286 pr " free_strings (r);\n";
7288 | RStruct (_, typ) ->
7289 pr " if (r == NULL) return -1;\n";
7290 pr " print_%s (r);\n" typ;
7291 pr " guestfs_free_%s (r);\n" typ;
7293 | RStructList (_, typ) ->
7294 pr " if (r == NULL) return -1;\n";
7295 pr " print_%s_list (r);\n" typ;
7296 pr " guestfs_free_%s_list (r);\n" typ;
7299 pr " if (r == NULL) return -1;\n";
7300 pr " print_table (r);\n";
7301 pr " free_strings (r);\n";
7304 pr " if (r == NULL) return -1;\n";
7305 pr " if (full_write (1, r, size) != size) {\n";
7306 pr " perror (\"write\");\n";
7317 (* run_action function *)
7318 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7321 fun (name, _, _, flags, _, _, _) ->
7322 let name2 = replace_char name '_' '-' in
7324 try find_map (function FishAlias n -> Some n | _ -> None) flags
7325 with Not_found -> name in
7327 pr "STRCASEEQ (cmd, \"%s\")" name;
7328 if name <> name2 then
7329 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7330 if name <> alias then
7331 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7333 pr " return run_%s (cmd, argc, argv);\n" name;
7337 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7344 (* Readline completion for guestfish. *)
7345 and generate_fish_completion () =
7346 generate_header CStyle GPLv2plus;
7350 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7360 #ifdef HAVE_LIBREADLINE
7361 #include <readline/readline.h>
7366 #ifdef HAVE_LIBREADLINE
7368 static const char *const commands[] = {
7369 BUILTIN_COMMANDS_FOR_COMPLETION,
7372 (* Get the commands, including the aliases. They don't need to be
7373 * sorted - the generator() function just does a dumb linear search.
7377 fun (name, _, _, flags, _, _, _) ->
7378 let name2 = replace_char name '_' '-' in
7380 try find_map (function FishAlias n -> Some n | _ -> None) flags
7381 with Not_found -> name in
7383 if name <> alias then [name2; alias] else [name2]
7385 let commands = List.flatten commands in
7387 List.iter (pr " \"%s\",\n") commands;
7393 generator (const char *text, int state)
7395 static int index, len;
7400 len = strlen (text);
7403 rl_attempted_completion_over = 1;
7405 while ((name = commands[index]) != NULL) {
7407 if (STRCASEEQLEN (name, text, len))
7408 return strdup (name);
7414 #endif /* HAVE_LIBREADLINE */
7416 char **do_completion (const char *text, int start, int end)
7418 char **matches = NULL;
7420 #ifdef HAVE_LIBREADLINE
7421 rl_completion_append_character = ' ';
7424 matches = rl_completion_matches (text, generator);
7425 else if (complete_dest_paths)
7426 matches = rl_completion_matches (text, complete_dest_paths_generator);
7433 (* Generate the POD documentation for guestfish. *)
7434 and generate_fish_actions_pod () =
7435 let all_functions_sorted =
7437 fun (_, _, _, flags, _, _, _) ->
7438 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7439 ) all_functions_sorted in
7441 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7444 fun (name, style, _, flags, _, _, longdesc) ->
7446 Str.global_substitute rex (
7449 try Str.matched_group 1 s
7451 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7452 "C<" ^ replace_char sub '_' '-' ^ ">"
7454 let name = replace_char name '_' '-' in
7456 try find_map (function FishAlias n -> Some n | _ -> None) flags
7457 with Not_found -> name in
7459 pr "=head2 %s" name;
7460 if name <> alias then
7467 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7468 | OptString n -> pr " %s" n
7469 | StringList n | DeviceList n -> pr " '%s ...'" n
7470 | Bool _ -> pr " true|false"
7471 | Int n -> pr " %s" n
7472 | Int64 n -> pr " %s" n
7473 | FileIn n | FileOut n -> pr " (%s|-)" n
7477 pr "%s\n\n" longdesc;
7479 if List.exists (function FileIn _ | FileOut _ -> true
7480 | _ -> false) (snd style) then
7481 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7483 if List.mem ProtocolLimitWarning flags then
7484 pr "%s\n\n" protocol_limit_warning;
7486 if List.mem DangerWillRobinson flags then
7487 pr "%s\n\n" danger_will_robinson;
7489 match deprecation_notice flags with
7491 | Some txt -> pr "%s\n\n" txt
7492 ) all_functions_sorted
7494 (* Generate a C function prototype. *)
7495 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7496 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7498 ?handle name style =
7499 if extern then pr "extern ";
7500 if static then pr "static ";
7501 (match fst style with
7503 | RInt _ -> pr "int "
7504 | RInt64 _ -> pr "int64_t "
7505 | RBool _ -> pr "int "
7506 | RConstString _ | RConstOptString _ -> pr "const char *"
7507 | RString _ | RBufferOut _ -> pr "char *"
7508 | RStringList _ | RHashtable _ -> pr "char **"
7509 | RStruct (_, typ) ->
7510 if not in_daemon then pr "struct guestfs_%s *" typ
7511 else pr "guestfs_int_%s *" typ
7512 | RStructList (_, typ) ->
7513 if not in_daemon then pr "struct guestfs_%s_list *" typ
7514 else pr "guestfs_int_%s_list *" typ
7516 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7517 pr "%s%s (" prefix name;
7518 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7521 let comma = ref false in
7524 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7528 if single_line then pr ", " else pr ",\n\t\t"
7535 | Device n | Dev_or_Path n
7539 pr "const char *%s" n
7540 | StringList n | DeviceList n ->
7542 pr "char *const *%s" n
7543 | Bool n -> next (); pr "int %s" n
7544 | Int n -> next (); pr "int %s" n
7545 | Int64 n -> next (); pr "int64_t %s" n
7548 if not in_daemon then (next (); pr "const char *%s" n)
7550 if is_RBufferOut then (next (); pr "size_t *size_r");
7553 if semicolon then pr ";";
7554 if newline then pr "\n"
7556 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7557 and generate_c_call_args ?handle ?(decl = false) style =
7559 let comma = ref false in
7561 if !comma then pr ", ";
7566 | Some handle -> pr "%s" handle; comma := true
7571 pr "%s" (name_of_argt arg)
7573 (* For RBufferOut calls, add implicit &size parameter. *)
7575 match fst style with
7583 (* Generate the OCaml bindings interface. *)
7584 and generate_ocaml_mli () =
7585 generate_header OCamlStyle LGPLv2plus;
7588 (** For API documentation you should refer to the C API
7589 in the guestfs(3) manual page. The OCaml API uses almost
7590 exactly the same calls. *)
7593 (** A [guestfs_h] handle. *)
7595 exception Error of string
7596 (** This exception is raised when there is an error. *)
7598 exception Handle_closed of string
7599 (** This exception is raised if you use a {!Guestfs.t} handle
7600 after calling {!close} on it. The string is the name of
7603 val create : unit -> t
7604 (** Create a {!Guestfs.t} handle. *)
7606 val close : t -> unit
7607 (** Close the {!Guestfs.t} handle and free up all resources used
7610 Handles are closed by the garbage collector when they become
7611 unreferenced, but callers can call this in order to provide
7612 predictable cleanup. *)
7615 generate_ocaml_structure_decls ();
7619 fun (name, style, _, _, _, shortdesc, _) ->
7620 generate_ocaml_prototype name style;
7621 pr "(** %s *)\n" shortdesc;
7623 ) all_functions_sorted
7625 (* Generate the OCaml bindings implementation. *)
7626 and generate_ocaml_ml () =
7627 generate_header OCamlStyle LGPLv2plus;
7632 exception Error of string
7633 exception Handle_closed of string
7635 external create : unit -> t = \"ocaml_guestfs_create\"
7636 external close : t -> unit = \"ocaml_guestfs_close\"
7638 (* Give the exceptions names, so they can be raised from the C code. *)
7640 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7641 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7645 generate_ocaml_structure_decls ();
7649 fun (name, style, _, _, _, shortdesc, _) ->
7650 generate_ocaml_prototype ~is_external:true name style;
7651 ) all_functions_sorted
7653 (* Generate the OCaml bindings C implementation. *)
7654 and generate_ocaml_c () =
7655 generate_header CStyle LGPLv2plus;
7662 #include <caml/config.h>
7663 #include <caml/alloc.h>
7664 #include <caml/callback.h>
7665 #include <caml/fail.h>
7666 #include <caml/memory.h>
7667 #include <caml/mlvalues.h>
7668 #include <caml/signals.h>
7670 #include <guestfs.h>
7672 #include \"guestfs_c.h\"
7674 /* Copy a hashtable of string pairs into an assoc-list. We return
7675 * the list in reverse order, but hashtables aren't supposed to be
7678 static CAMLprim value
7679 copy_table (char * const * argv)
7682 CAMLlocal5 (rv, pairv, kv, vv, cons);
7686 for (i = 0; argv[i] != NULL; i += 2) {
7687 kv = caml_copy_string (argv[i]);
7688 vv = caml_copy_string (argv[i+1]);
7689 pairv = caml_alloc (2, 0);
7690 Store_field (pairv, 0, kv);
7691 Store_field (pairv, 1, vv);
7692 cons = caml_alloc (2, 0);
7693 Store_field (cons, 1, rv);
7695 Store_field (cons, 0, pairv);
7703 (* Struct copy functions. *)
7705 let emit_ocaml_copy_list_function typ =
7706 pr "static CAMLprim value\n";
7707 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7709 pr " CAMLparam0 ();\n";
7710 pr " CAMLlocal2 (rv, v);\n";
7711 pr " unsigned int i;\n";
7713 pr " if (%ss->len == 0)\n" typ;
7714 pr " CAMLreturn (Atom (0));\n";
7716 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7717 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7718 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7719 pr " caml_modify (&Field (rv, i), v);\n";
7721 pr " CAMLreturn (rv);\n";
7729 let has_optpercent_col =
7730 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7732 pr "static CAMLprim value\n";
7733 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7735 pr " CAMLparam0 ();\n";
7736 if has_optpercent_col then
7737 pr " CAMLlocal3 (rv, v, v2);\n"
7739 pr " CAMLlocal2 (rv, v);\n";
7741 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7746 pr " v = caml_copy_string (%s->%s);\n" typ name
7748 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7749 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7752 pr " v = caml_alloc_string (32);\n";
7753 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7754 | name, (FBytes|FInt64|FUInt64) ->
7755 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7756 | name, (FInt32|FUInt32) ->
7757 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7758 | name, FOptPercent ->
7759 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7760 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7761 pr " v = caml_alloc (1, 0);\n";
7762 pr " Store_field (v, 0, v2);\n";
7763 pr " } else /* None */\n";
7764 pr " v = Val_int (0);\n";
7766 pr " v = Val_int (%s->%s);\n" typ name
7768 pr " Store_field (rv, %d, v);\n" i
7770 pr " CAMLreturn (rv);\n";
7775 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7778 | typ, (RStructListOnly | RStructAndList) ->
7779 (* generate the function for typ *)
7780 emit_ocaml_copy_list_function typ
7781 | typ, _ -> () (* empty *)
7782 ) (rstructs_used_by all_functions);
7786 fun (name, style, _, _, _, _, _) ->
7787 pr "/* Automatically generated wrapper for function\n";
7789 generate_ocaml_prototype name style;
7794 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7796 let needs_extra_vs =
7797 match fst style with RConstOptString _ -> true | _ -> false in
7799 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7800 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7801 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7804 pr "CAMLprim value\n";
7805 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7806 List.iter (pr ", value %s") (List.tl params);
7811 | [p1; p2; p3; p4; p5] ->
7812 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7813 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7814 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7815 pr " CAMLxparam%d (%s);\n"
7816 (List.length rest) (String.concat ", " rest)
7818 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7820 if not needs_extra_vs then
7821 pr " CAMLlocal1 (rv);\n"
7823 pr " CAMLlocal3 (rv, v, v2);\n";
7826 pr " guestfs_h *g = Guestfs_val (gv);\n";
7827 pr " if (g == NULL)\n";
7828 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
7834 | Device n | Dev_or_Path n
7838 pr " const char *%s = String_val (%sv);\n" n n
7840 pr " const char *%s =\n" n;
7841 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7843 | StringList n | DeviceList n ->
7844 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7846 pr " int %s = Bool_val (%sv);\n" n n
7848 pr " int %s = Int_val (%sv);\n" n n
7850 pr " int64_t %s = Int64_val (%sv);\n" n n
7853 match fst style with
7854 | RErr -> pr " int r;\n"; "-1"
7855 | RInt _ -> pr " int r;\n"; "-1"
7856 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7857 | RBool _ -> pr " int r;\n"; "-1"
7858 | RConstString _ | RConstOptString _ ->
7859 pr " const char *r;\n"; "NULL"
7860 | RString _ -> pr " char *r;\n"; "NULL"
7865 | RStruct (_, typ) ->
7866 pr " struct guestfs_%s *r;\n" typ; "NULL"
7867 | RStructList (_, typ) ->
7868 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7875 pr " size_t size;\n";
7879 pr " caml_enter_blocking_section ();\n";
7880 pr " r = guestfs_%s " name;
7881 generate_c_call_args ~handle:"g" style;
7883 pr " caml_leave_blocking_section ();\n";
7887 | StringList n | DeviceList n ->
7888 pr " ocaml_guestfs_free_strings (%s);\n" n;
7889 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7890 | Bool _ | Int _ | Int64 _
7891 | FileIn _ | FileOut _ -> ()
7894 pr " if (r == %s)\n" error_code;
7895 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7898 (match fst style with
7899 | RErr -> pr " rv = Val_unit;\n"
7900 | RInt _ -> pr " rv = Val_int (r);\n"
7902 pr " rv = caml_copy_int64 (r);\n"
7903 | RBool _ -> pr " rv = Val_bool (r);\n"
7905 pr " rv = caml_copy_string (r);\n"
7906 | RConstOptString _ ->
7907 pr " if (r) { /* Some string */\n";
7908 pr " v = caml_alloc (1, 0);\n";
7909 pr " v2 = caml_copy_string (r);\n";
7910 pr " Store_field (v, 0, v2);\n";
7911 pr " } else /* None */\n";
7912 pr " v = Val_int (0);\n";
7914 pr " rv = caml_copy_string (r);\n";
7917 pr " rv = caml_copy_string_array ((const char **) r);\n";
7918 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7920 | RStruct (_, typ) ->
7921 pr " rv = copy_%s (r);\n" typ;
7922 pr " guestfs_free_%s (r);\n" typ;
7923 | RStructList (_, typ) ->
7924 pr " rv = copy_%s_list (r);\n" typ;
7925 pr " guestfs_free_%s_list (r);\n" typ;
7927 pr " rv = copy_table (r);\n";
7928 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7931 pr " rv = caml_alloc_string (size);\n";
7932 pr " memcpy (String_val (rv), r, size);\n";
7935 pr " CAMLreturn (rv);\n";
7939 if List.length params > 5 then (
7940 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7941 pr "CAMLprim value ";
7942 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7943 pr "CAMLprim value\n";
7944 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7946 pr " return ocaml_guestfs_%s (argv[0]" name;
7947 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7952 ) all_functions_sorted
7954 and generate_ocaml_structure_decls () =
7957 pr "type %s = {\n" typ;
7960 | name, FString -> pr " %s : string;\n" name
7961 | name, FBuffer -> pr " %s : string;\n" name
7962 | name, FUUID -> pr " %s : string;\n" name
7963 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
7964 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
7965 | name, FChar -> pr " %s : char;\n" name
7966 | name, FOptPercent -> pr " %s : float option;\n" name
7972 and generate_ocaml_prototype ?(is_external = false) name style =
7973 if is_external then pr "external " else pr "val ";
7974 pr "%s : t -> " name;
7977 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7978 | OptString _ -> pr "string option -> "
7979 | StringList _ | DeviceList _ -> pr "string array -> "
7980 | Bool _ -> pr "bool -> "
7981 | Int _ -> pr "int -> "
7982 | Int64 _ -> pr "int64 -> "
7984 (match fst style with
7985 | RErr -> pr "unit" (* all errors are turned into exceptions *)
7986 | RInt _ -> pr "int"
7987 | RInt64 _ -> pr "int64"
7988 | RBool _ -> pr "bool"
7989 | RConstString _ -> pr "string"
7990 | RConstOptString _ -> pr "string option"
7991 | RString _ | RBufferOut _ -> pr "string"
7992 | RStringList _ -> pr "string array"
7993 | RStruct (_, typ) -> pr "%s" typ
7994 | RStructList (_, typ) -> pr "%s array" typ
7995 | RHashtable _ -> pr "(string * string) list"
7997 if is_external then (
7999 if List.length (snd style) + 1 > 5 then
8000 pr "\"ocaml_guestfs_%s_byte\" " name;
8001 pr "\"ocaml_guestfs_%s\"" name
8005 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8006 and generate_perl_xs () =
8007 generate_header CStyle LGPLv2plus;
8010 #include \"EXTERN.h\"
8014 #include <guestfs.h>
8017 #define PRId64 \"lld\"
8021 my_newSVll(long long val) {
8022 #ifdef USE_64_BIT_ALL
8023 return newSViv(val);
8027 len = snprintf(buf, 100, \"%%\" PRId64, val);
8028 return newSVpv(buf, len);
8033 #define PRIu64 \"llu\"
8037 my_newSVull(unsigned long long val) {
8038 #ifdef USE_64_BIT_ALL
8039 return newSVuv(val);
8043 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8044 return newSVpv(buf, len);
8048 /* http://www.perlmonks.org/?node_id=680842 */
8050 XS_unpack_charPtrPtr (SV *arg) {
8055 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8056 croak (\"array reference expected\");
8058 av = (AV *)SvRV (arg);
8059 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8061 croak (\"malloc failed\");
8063 for (i = 0; i <= av_len (av); i++) {
8064 SV **elem = av_fetch (av, i, 0);
8066 if (!elem || !*elem)
8067 croak (\"missing element in list\");
8069 ret[i] = SvPV_nolen (*elem);
8077 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8084 RETVAL = guestfs_create ();
8086 croak (\"could not create guestfs handle\");
8087 guestfs_set_error_handler (RETVAL, NULL, NULL);
8100 fun (name, style, _, _, _, _, _) ->
8101 (match fst style with
8102 | RErr -> pr "void\n"
8103 | RInt _ -> pr "SV *\n"
8104 | RInt64 _ -> pr "SV *\n"
8105 | RBool _ -> pr "SV *\n"
8106 | RConstString _ -> pr "SV *\n"
8107 | RConstOptString _ -> pr "SV *\n"
8108 | RString _ -> pr "SV *\n"
8109 | RBufferOut _ -> pr "SV *\n"
8111 | RStruct _ | RStructList _
8113 pr "void\n" (* all lists returned implictly on the stack *)
8115 (* Call and arguments. *)
8117 generate_c_call_args ~handle:"g" ~decl:true style;
8119 pr " guestfs_h *g;\n";
8123 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8126 (* http://www.perlmonks.org/?node_id=554277
8127 * Note that the implicit handle argument means we have
8128 * to add 1 to the ST(x) operator.
8130 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8131 | StringList n | DeviceList n -> pr " char **%s;\n" n
8132 | Bool n -> pr " int %s;\n" n
8133 | Int n -> pr " int %s;\n" n
8134 | Int64 n -> pr " int64_t %s;\n" n
8137 let do_cleanups () =
8140 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8141 | Bool _ | Int _ | Int64 _
8142 | FileIn _ | FileOut _ -> ()
8143 | StringList n | DeviceList n -> pr " free (%s);\n" n
8148 (match fst style with
8153 pr " r = guestfs_%s " name;
8154 generate_c_call_args ~handle:"g" style;
8157 pr " if (r == -1)\n";
8158 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8164 pr " %s = guestfs_%s " n name;
8165 generate_c_call_args ~handle:"g" style;
8168 pr " if (%s == -1)\n" n;
8169 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8170 pr " RETVAL = newSViv (%s);\n" n;
8175 pr " int64_t %s;\n" n;
8177 pr " %s = guestfs_%s " n name;
8178 generate_c_call_args ~handle:"g" style;
8181 pr " if (%s == -1)\n" n;
8182 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8183 pr " RETVAL = my_newSVll (%s);\n" n;
8188 pr " const char *%s;\n" n;
8190 pr " %s = guestfs_%s " n name;
8191 generate_c_call_args ~handle:"g" style;
8194 pr " if (%s == NULL)\n" n;
8195 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8196 pr " RETVAL = newSVpv (%s, 0);\n" n;
8199 | RConstOptString n ->
8201 pr " const char *%s;\n" n;
8203 pr " %s = guestfs_%s " n name;
8204 generate_c_call_args ~handle:"g" style;
8207 pr " if (%s == NULL)\n" n;
8208 pr " RETVAL = &PL_sv_undef;\n";
8210 pr " RETVAL = newSVpv (%s, 0);\n" n;
8215 pr " char *%s;\n" n;
8217 pr " %s = guestfs_%s " n name;
8218 generate_c_call_args ~handle:"g" style;
8221 pr " if (%s == NULL)\n" n;
8222 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8223 pr " RETVAL = newSVpv (%s, 0);\n" n;
8224 pr " free (%s);\n" n;
8227 | RStringList n | RHashtable n ->
8229 pr " char **%s;\n" n;
8232 pr " %s = guestfs_%s " n name;
8233 generate_c_call_args ~handle:"g" style;
8236 pr " if (%s == NULL)\n" n;
8237 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8238 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8239 pr " EXTEND (SP, n);\n";
8240 pr " for (i = 0; i < n; ++i) {\n";
8241 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8242 pr " free (%s[i]);\n" n;
8244 pr " free (%s);\n" n;
8245 | RStruct (n, typ) ->
8246 let cols = cols_of_struct typ in
8247 generate_perl_struct_code typ cols name style n do_cleanups
8248 | RStructList (n, typ) ->
8249 let cols = cols_of_struct typ in
8250 generate_perl_struct_list_code typ cols name style n do_cleanups
8253 pr " char *%s;\n" n;
8254 pr " size_t size;\n";
8256 pr " %s = guestfs_%s " n name;
8257 generate_c_call_args ~handle:"g" style;
8260 pr " if (%s == NULL)\n" n;
8261 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8262 pr " RETVAL = newSVpv (%s, size);\n" n;
8263 pr " free (%s);\n" n;
8271 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8273 pr " struct guestfs_%s_list *%s;\n" typ n;
8277 pr " %s = guestfs_%s " n name;
8278 generate_c_call_args ~handle:"g" style;
8281 pr " if (%s == NULL)\n" n;
8282 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8283 pr " EXTEND (SP, %s->len);\n" n;
8284 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8285 pr " hv = newHV ();\n";
8289 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8290 name (String.length name) n name
8292 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8293 name (String.length name) n name
8295 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8296 name (String.length name) n name n name
8297 | name, (FBytes|FUInt64) ->
8298 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8299 name (String.length name) n name
8301 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8302 name (String.length name) n name
8303 | name, (FInt32|FUInt32) ->
8304 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8305 name (String.length name) n name
8307 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8308 name (String.length name) n name
8309 | name, FOptPercent ->
8310 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8311 name (String.length name) n name
8313 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8315 pr " guestfs_free_%s_list (%s);\n" typ n
8317 and generate_perl_struct_code typ cols name style n do_cleanups =
8319 pr " struct guestfs_%s *%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, 2 * %d);\n" (List.length cols);
8329 fun ((name, _) as col) ->
8330 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8334 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8337 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8340 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8342 | name, (FBytes|FUInt64) ->
8343 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8346 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8348 | name, (FInt32|FUInt32) ->
8349 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8352 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8354 | name, FOptPercent ->
8355 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8358 pr " free (%s);\n" n
8360 (* Generate Sys/Guestfs.pm. *)
8361 and generate_perl_pm () =
8362 generate_header HashStyle LGPLv2plus;
8369 Sys::Guestfs - Perl bindings for libguestfs
8375 my $h = Sys::Guestfs->new ();
8376 $h->add_drive ('guest.img');
8378 $h->mount ('/dev/sda1', '/');
8379 $h->touch ('/hello');
8384 The C<Sys::Guestfs> module provides a Perl XS binding to the
8385 libguestfs API for examining and modifying virtual machine
8388 Amongst the things this is good for: making batch configuration
8389 changes to guests, getting disk used/free statistics (see also:
8390 virt-df), migrating between virtualization systems (see also:
8391 virt-p2v), performing partial backups, performing partial guest
8392 clones, cloning guests and changing registry/UUID/hostname info, and
8395 Libguestfs uses Linux kernel and qemu code, and can access any type of
8396 guest filesystem that Linux and qemu can, including but not limited
8397 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8398 schemes, qcow, qcow2, vmdk.
8400 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8401 LVs, what filesystem is in each LV, etc.). It can also run commands
8402 in the context of the guest. Also you can access filesystems over
8405 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8406 functions for using libguestfs from Perl, including integration
8411 All errors turn into calls to C<croak> (see L<Carp(3)>).
8419 package Sys::Guestfs;
8425 XSLoader::load ('Sys::Guestfs');
8427 =item $h = Sys::Guestfs->new ();
8429 Create a new guestfs handle.
8435 my $class = ref ($proto) || $proto;
8437 my $self = Sys::Guestfs::_create ();
8438 bless $self, $class;
8444 (* Actions. We only need to print documentation for these as
8445 * they are pulled in from the XS code automatically.
8448 fun (name, style, _, flags, _, _, longdesc) ->
8449 if not (List.mem NotInDocs flags) then (
8450 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8452 generate_perl_prototype name style;
8454 pr "%s\n\n" longdesc;
8455 if List.mem ProtocolLimitWarning flags then
8456 pr "%s\n\n" protocol_limit_warning;
8457 if List.mem DangerWillRobinson flags then
8458 pr "%s\n\n" danger_will_robinson;
8459 match deprecation_notice flags with
8461 | Some txt -> pr "%s\n\n" txt
8463 ) all_functions_sorted;
8475 Copyright (C) %s Red Hat Inc.
8479 Please see the file COPYING.LIB for the full license.
8485 L<http://libguestfs.org>,
8486 L<Sys::Guestfs::Lib(3)>.
8491 and generate_perl_prototype name style =
8492 (match fst style with
8500 | RBufferOut n -> pr "$%s = " n
8502 | RHashtable n -> pr "%%%s = " n
8504 | RStructList (n,_) -> pr "@%s = " n
8507 let comma = ref false in
8510 if !comma then pr ", ";
8513 | Pathname n | Device n | Dev_or_Path n | String n
8514 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8516 | StringList n | DeviceList n ->
8521 (* Generate Python C module. *)
8522 and generate_python_c () =
8523 generate_header CStyle LGPLv2plus;
8532 #include \"guestfs.h\"
8540 get_handle (PyObject *obj)
8543 assert (obj != Py_None);
8544 return ((Pyguestfs_Object *) obj)->g;
8548 put_handle (guestfs_h *g)
8552 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8555 /* This list should be freed (but not the strings) after use. */
8557 get_string_list (PyObject *obj)
8564 if (!PyList_Check (obj)) {
8565 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8569 len = PyList_Size (obj);
8570 r = malloc (sizeof (char *) * (len+1));
8572 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8576 for (i = 0; i < len; ++i)
8577 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8584 put_string_list (char * const * const argv)
8589 for (argc = 0; argv[argc] != NULL; ++argc)
8592 list = PyList_New (argc);
8593 for (i = 0; i < argc; ++i)
8594 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8600 put_table (char * const * const argv)
8602 PyObject *list, *item;
8605 for (argc = 0; argv[argc] != NULL; ++argc)
8608 list = PyList_New (argc >> 1);
8609 for (i = 0; i < argc; i += 2) {
8610 item = PyTuple_New (2);
8611 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8612 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8613 PyList_SetItem (list, i >> 1, item);
8620 free_strings (char **argv)
8624 for (argc = 0; argv[argc] != NULL; ++argc)
8630 py_guestfs_create (PyObject *self, PyObject *args)
8634 g = guestfs_create ();
8636 PyErr_SetString (PyExc_RuntimeError,
8637 \"guestfs.create: failed to allocate handle\");
8640 guestfs_set_error_handler (g, NULL, NULL);
8641 return put_handle (g);
8645 py_guestfs_close (PyObject *self, PyObject *args)
8650 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8652 g = get_handle (py_g);
8656 Py_INCREF (Py_None);
8662 let emit_put_list_function typ =
8663 pr "static PyObject *\n";
8664 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8666 pr " PyObject *list;\n";
8669 pr " list = PyList_New (%ss->len);\n" typ;
8670 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8671 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8672 pr " return list;\n";
8677 (* Structures, turned into Python dictionaries. *)
8680 pr "static PyObject *\n";
8681 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8683 pr " PyObject *dict;\n";
8685 pr " dict = PyDict_New ();\n";
8689 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8690 pr " PyString_FromString (%s->%s));\n"
8693 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8694 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8697 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8698 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8700 | name, (FBytes|FUInt64) ->
8701 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8702 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8705 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8706 pr " PyLong_FromLongLong (%s->%s));\n"
8709 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8710 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8713 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8714 pr " PyLong_FromLong (%s->%s));\n"
8716 | name, FOptPercent ->
8717 pr " if (%s->%s >= 0)\n" typ name;
8718 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8719 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8722 pr " Py_INCREF (Py_None);\n";
8723 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8726 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8727 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8729 pr " return dict;\n";
8735 (* Emit a put_TYPE_list function definition only if that function is used. *)
8738 | typ, (RStructListOnly | RStructAndList) ->
8739 (* generate the function for typ *)
8740 emit_put_list_function typ
8741 | typ, _ -> () (* empty *)
8742 ) (rstructs_used_by all_functions);
8744 (* Python wrapper functions. *)
8746 fun (name, style, _, _, _, _, _) ->
8747 pr "static PyObject *\n";
8748 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8751 pr " PyObject *py_g;\n";
8752 pr " guestfs_h *g;\n";
8753 pr " PyObject *py_r;\n";
8756 match fst style with
8757 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8758 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8759 | RConstString _ | RConstOptString _ ->
8760 pr " const char *r;\n"; "NULL"
8761 | RString _ -> pr " char *r;\n"; "NULL"
8762 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8763 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8764 | RStructList (_, typ) ->
8765 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8768 pr " size_t size;\n";
8773 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8774 pr " const char *%s;\n" n
8775 | OptString n -> pr " const char *%s;\n" n
8776 | StringList n | DeviceList n ->
8777 pr " PyObject *py_%s;\n" n;
8778 pr " char **%s;\n" n
8779 | Bool n -> pr " int %s;\n" n
8780 | Int n -> pr " int %s;\n" n
8781 | Int64 n -> pr " long long %s;\n" n
8786 (* Convert the parameters. *)
8787 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8790 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8791 | OptString _ -> pr "z"
8792 | StringList _ | DeviceList _ -> pr "O"
8793 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8795 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8796 * emulate C's int/long/long long in Python?
8799 pr ":guestfs_%s\",\n" name;
8803 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8804 | OptString n -> pr ", &%s" n
8805 | StringList n | DeviceList n -> pr ", &py_%s" n
8806 | Bool n -> pr ", &%s" n
8807 | Int n -> pr ", &%s" n
8808 | Int64 n -> pr ", &%s" n
8812 pr " return NULL;\n";
8814 pr " g = get_handle (py_g);\n";
8817 | Pathname _ | Device _ | Dev_or_Path _ | String _
8818 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8819 | StringList n | DeviceList n ->
8820 pr " %s = get_string_list (py_%s);\n" n n;
8821 pr " if (!%s) return NULL;\n" n
8826 pr " r = guestfs_%s " name;
8827 generate_c_call_args ~handle:"g" style;
8832 | Pathname _ | Device _ | Dev_or_Path _ | String _
8833 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8834 | StringList n | DeviceList n ->
8835 pr " free (%s);\n" n
8838 pr " if (r == %s) {\n" error_code;
8839 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8840 pr " return NULL;\n";
8844 (match fst style with
8846 pr " Py_INCREF (Py_None);\n";
8847 pr " py_r = Py_None;\n"
8849 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
8850 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
8851 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
8852 | RConstOptString _ ->
8854 pr " py_r = PyString_FromString (r);\n";
8856 pr " Py_INCREF (Py_None);\n";
8857 pr " py_r = Py_None;\n";
8860 pr " py_r = PyString_FromString (r);\n";
8863 pr " py_r = put_string_list (r);\n";
8864 pr " free_strings (r);\n"
8865 | RStruct (_, typ) ->
8866 pr " py_r = put_%s (r);\n" typ;
8867 pr " guestfs_free_%s (r);\n" typ
8868 | RStructList (_, typ) ->
8869 pr " py_r = put_%s_list (r);\n" typ;
8870 pr " guestfs_free_%s_list (r);\n" typ
8872 pr " py_r = put_table (r);\n";
8873 pr " free_strings (r);\n"
8875 pr " py_r = PyString_FromStringAndSize (r, size);\n";
8879 pr " return py_r;\n";
8884 (* Table of functions. *)
8885 pr "static PyMethodDef methods[] = {\n";
8886 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8887 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8889 fun (name, _, _, _, _, _, _) ->
8890 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8893 pr " { NULL, NULL, 0, NULL }\n";
8897 (* Init function. *)
8900 initlibguestfsmod (void)
8902 static int initialized = 0;
8904 if (initialized) return;
8905 Py_InitModule ((char *) \"libguestfsmod\", methods);
8910 (* Generate Python module. *)
8911 and generate_python_py () =
8912 generate_header HashStyle LGPLv2plus;
8915 u\"\"\"Python bindings for libguestfs
8918 g = guestfs.GuestFS ()
8919 g.add_drive (\"guest.img\")
8921 parts = g.list_partitions ()
8923 The guestfs module provides a Python binding to the libguestfs API
8924 for examining and modifying virtual machine disk images.
8926 Amongst the things this is good for: making batch configuration
8927 changes to guests, getting disk used/free statistics (see also:
8928 virt-df), migrating between virtualization systems (see also:
8929 virt-p2v), performing partial backups, performing partial guest
8930 clones, cloning guests and changing registry/UUID/hostname info, and
8933 Libguestfs uses Linux kernel and qemu code, and can access any type of
8934 guest filesystem that Linux and qemu can, including but not limited
8935 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8936 schemes, qcow, qcow2, vmdk.
8938 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8939 LVs, what filesystem is in each LV, etc.). It can also run commands
8940 in the context of the guest. Also you can access filesystems over
8943 Errors which happen while using the API are turned into Python
8944 RuntimeError exceptions.
8946 To create a guestfs handle you usually have to perform the following
8949 # Create the handle, call add_drive at least once, and possibly
8950 # several times if the guest has multiple block devices:
8951 g = guestfs.GuestFS ()
8952 g.add_drive (\"guest.img\")
8954 # Launch the qemu subprocess and wait for it to become ready:
8957 # Now you can issue commands, for example:
8962 import libguestfsmod
8965 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8967 def __init__ (self):
8968 \"\"\"Create a new libguestfs handle.\"\"\"
8969 self._o = libguestfsmod.create ()
8972 libguestfsmod.close (self._o)
8977 fun (name, style, _, flags, _, _, longdesc) ->
8979 generate_py_call_args ~handle:"self" (snd style);
8982 if not (List.mem NotInDocs flags) then (
8983 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8985 match fst style with
8986 | RErr | RInt _ | RInt64 _ | RBool _
8987 | RConstOptString _ | RConstString _
8988 | RString _ | RBufferOut _ -> doc
8990 doc ^ "\n\nThis function returns a list of strings."
8991 | RStruct (_, typ) ->
8992 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8993 | RStructList (_, typ) ->
8994 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
8996 doc ^ "\n\nThis function returns a dictionary." in
8998 if List.mem ProtocolLimitWarning flags then
8999 doc ^ "\n\n" ^ protocol_limit_warning
9002 if List.mem DangerWillRobinson flags then
9003 doc ^ "\n\n" ^ danger_will_robinson
9006 match deprecation_notice flags with
9008 | Some txt -> doc ^ "\n\n" ^ txt in
9009 let doc = pod2text ~width:60 name doc in
9010 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9011 let doc = String.concat "\n " doc in
9012 pr " u\"\"\"%s\"\"\"\n" doc;
9014 pr " return libguestfsmod.%s " name;
9015 generate_py_call_args ~handle:"self._o" (snd style);
9020 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9021 and generate_py_call_args ~handle args =
9023 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9026 (* Useful if you need the longdesc POD text as plain text. Returns a
9029 * Because this is very slow (the slowest part of autogeneration),
9030 * we memoize the results.
9032 and pod2text ~width name longdesc =
9033 let key = width, name, longdesc in
9034 try Hashtbl.find pod2text_memo key
9036 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9037 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9039 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9040 let chan = open_process_in cmd in
9041 let lines = ref [] in
9043 let line = input_line chan in
9044 if i = 1 then (* discard the first line of output *)
9047 let line = triml line in
9048 lines := line :: !lines;
9051 let lines = try loop 1 with End_of_file -> List.rev !lines in
9053 (match close_process_in chan with
9056 failwithf "pod2text: process exited with non-zero status (%d)" i
9057 | WSIGNALED i | WSTOPPED i ->
9058 failwithf "pod2text: process signalled or stopped by signal %d" i
9060 Hashtbl.add pod2text_memo key lines;
9061 pod2text_memo_updated ();
9064 (* Generate ruby bindings. *)
9065 and generate_ruby_c () =
9066 generate_header CStyle LGPLv2plus;
9074 #include \"guestfs.h\"
9076 #include \"extconf.h\"
9078 /* For Ruby < 1.9 */
9080 #define RARRAY_LEN(r) (RARRAY((r))->len)
9083 static VALUE m_guestfs; /* guestfs module */
9084 static VALUE c_guestfs; /* guestfs_h handle */
9085 static VALUE e_Error; /* used for all errors */
9087 static void ruby_guestfs_free (void *p)
9090 guestfs_close ((guestfs_h *) p);
9093 static VALUE ruby_guestfs_create (VALUE m)
9097 g = guestfs_create ();
9099 rb_raise (e_Error, \"failed to create guestfs handle\");
9101 /* Don't print error messages to stderr by default. */
9102 guestfs_set_error_handler (g, NULL, NULL);
9104 /* Wrap it, and make sure the close function is called when the
9107 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9110 static VALUE ruby_guestfs_close (VALUE gv)
9113 Data_Get_Struct (gv, guestfs_h, g);
9115 ruby_guestfs_free (g);
9116 DATA_PTR (gv) = NULL;
9124 fun (name, style, _, _, _, _, _) ->
9125 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9126 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9129 pr " guestfs_h *g;\n";
9130 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9132 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9138 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9139 pr " Check_Type (%sv, T_STRING);\n" n;
9140 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9142 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9143 pr " \"%s\", \"%s\");\n" n name
9145 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9146 | StringList n | DeviceList n ->
9147 pr " char **%s;\n" n;
9148 pr " Check_Type (%sv, T_ARRAY);\n" n;
9150 pr " int i, len;\n";
9151 pr " len = RARRAY_LEN (%sv);\n" n;
9152 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9154 pr " for (i = 0; i < len; ++i) {\n";
9155 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9156 pr " %s[i] = StringValueCStr (v);\n" n;
9158 pr " %s[len] = NULL;\n" n;
9161 pr " int %s = RTEST (%sv);\n" n n
9163 pr " int %s = NUM2INT (%sv);\n" n n
9165 pr " long long %s = NUM2LL (%sv);\n" n n
9170 match fst style with
9171 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9172 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9173 | RConstString _ | RConstOptString _ ->
9174 pr " const char *r;\n"; "NULL"
9175 | RString _ -> pr " char *r;\n"; "NULL"
9176 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9177 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9178 | RStructList (_, typ) ->
9179 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9182 pr " size_t size;\n";
9186 pr " r = guestfs_%s " name;
9187 generate_c_call_args ~handle:"g" style;
9192 | Pathname _ | Device _ | Dev_or_Path _ | String _
9193 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9194 | StringList n | DeviceList n ->
9195 pr " free (%s);\n" n
9198 pr " if (r == %s)\n" error_code;
9199 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9202 (match fst style with
9204 pr " return Qnil;\n"
9205 | RInt _ | RBool _ ->
9206 pr " return INT2NUM (r);\n"
9208 pr " return ULL2NUM (r);\n"
9210 pr " return rb_str_new2 (r);\n";
9211 | RConstOptString _ ->
9213 pr " return rb_str_new2 (r);\n";
9215 pr " return Qnil;\n";
9217 pr " VALUE rv = rb_str_new2 (r);\n";
9221 pr " int i, len = 0;\n";
9222 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9223 pr " VALUE rv = rb_ary_new2 (len);\n";
9224 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9225 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9226 pr " free (r[i]);\n";
9230 | RStruct (_, typ) ->
9231 let cols = cols_of_struct typ in
9232 generate_ruby_struct_code typ cols
9233 | RStructList (_, typ) ->
9234 let cols = cols_of_struct typ in
9235 generate_ruby_struct_list_code typ cols
9237 pr " VALUE rv = rb_hash_new ();\n";
9239 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9240 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9241 pr " free (r[i]);\n";
9242 pr " free (r[i+1]);\n";
9247 pr " VALUE rv = rb_str_new (r, size);\n";
9257 /* Initialize the module. */
9258 void Init__guestfs ()
9260 m_guestfs = rb_define_module (\"Guestfs\");
9261 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9262 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9264 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9265 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9268 (* Define the rest of the methods. *)
9270 fun (name, style, _, _, _, _, _) ->
9271 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9272 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9277 (* Ruby code to return a struct. *)
9278 and generate_ruby_struct_code typ cols =
9279 pr " VALUE rv = rb_hash_new ();\n";
9283 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9285 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9287 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9288 | name, (FBytes|FUInt64) ->
9289 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9291 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9293 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9295 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9296 | name, FOptPercent ->
9297 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9298 | name, FChar -> (* XXX wrong? *)
9299 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9301 pr " guestfs_free_%s (r);\n" typ;
9304 (* Ruby code to return a struct list. *)
9305 and generate_ruby_struct_list_code typ cols =
9306 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9308 pr " for (i = 0; i < r->len; ++i) {\n";
9309 pr " VALUE hv = rb_hash_new ();\n";
9313 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9315 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
9317 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9318 | name, (FBytes|FUInt64) ->
9319 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9321 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9323 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9325 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9326 | name, FOptPercent ->
9327 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9328 | name, FChar -> (* XXX wrong? *)
9329 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9331 pr " rb_ary_push (rv, hv);\n";
9333 pr " guestfs_free_%s_list (r);\n" typ;
9336 (* Generate Java bindings GuestFS.java file. *)
9337 and generate_java_java () =
9338 generate_header CStyle LGPLv2plus;
9341 package com.redhat.et.libguestfs;
9343 import java.util.HashMap;
9344 import com.redhat.et.libguestfs.LibGuestFSException;
9345 import com.redhat.et.libguestfs.PV;
9346 import com.redhat.et.libguestfs.VG;
9347 import com.redhat.et.libguestfs.LV;
9348 import com.redhat.et.libguestfs.Stat;
9349 import com.redhat.et.libguestfs.StatVFS;
9350 import com.redhat.et.libguestfs.IntBool;
9351 import com.redhat.et.libguestfs.Dirent;
9354 * The GuestFS object is a libguestfs handle.
9358 public class GuestFS {
9359 // Load the native code.
9361 System.loadLibrary (\"guestfs_jni\");
9365 * The native guestfs_h pointer.
9370 * Create a libguestfs handle.
9372 * @throws LibGuestFSException
9374 public GuestFS () throws LibGuestFSException
9378 private native long _create () throws LibGuestFSException;
9381 * Close a libguestfs handle.
9383 * You can also leave handles to be collected by the garbage
9384 * collector, but this method ensures that the resources used
9385 * by the handle are freed up immediately. If you call any
9386 * other methods after closing the handle, you will get an
9389 * @throws LibGuestFSException
9391 public void close () throws LibGuestFSException
9397 private native void _close (long g) throws LibGuestFSException;
9399 public void finalize () throws LibGuestFSException
9407 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9408 if not (List.mem NotInDocs flags); then (
9409 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9411 if List.mem ProtocolLimitWarning flags then
9412 doc ^ "\n\n" ^ protocol_limit_warning
9415 if List.mem DangerWillRobinson flags then
9416 doc ^ "\n\n" ^ danger_will_robinson
9419 match deprecation_notice flags with
9421 | Some txt -> doc ^ "\n\n" ^ txt in
9422 let doc = pod2text ~width:60 name doc in
9423 let doc = List.map ( (* RHBZ#501883 *)
9426 | nonempty -> nonempty
9428 let doc = String.concat "\n * " doc in
9431 pr " * %s\n" shortdesc;
9434 pr " * @throws LibGuestFSException\n";
9438 generate_java_prototype ~public:true ~semicolon:false name style;
9441 pr " if (g == 0)\n";
9442 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9445 if fst style <> RErr then pr "return ";
9447 generate_java_call_args ~handle:"g" (snd style);
9451 generate_java_prototype ~privat:true ~native:true name style;
9458 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9459 and generate_java_call_args ~handle args =
9461 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9464 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9465 ?(semicolon=true) name style =
9466 if privat then pr "private ";
9467 if public then pr "public ";
9468 if native then pr "native ";
9471 (match fst style with
9472 | RErr -> pr "void ";
9473 | RInt _ -> pr "int ";
9474 | RInt64 _ -> pr "long ";
9475 | RBool _ -> pr "boolean ";
9476 | RConstString _ | RConstOptString _ | RString _
9477 | RBufferOut _ -> pr "String ";
9478 | RStringList _ -> pr "String[] ";
9479 | RStruct (_, typ) ->
9480 let name = java_name_of_struct typ in
9482 | RStructList (_, typ) ->
9483 let name = java_name_of_struct typ in
9485 | RHashtable _ -> pr "HashMap<String,String> ";
9488 if native then pr "_%s " name else pr "%s " name;
9490 let needs_comma = ref false in
9499 if !needs_comma then pr ", ";
9500 needs_comma := true;
9504 | Device n | Dev_or_Path n
9510 | StringList n | DeviceList n ->
9521 pr " throws LibGuestFSException";
9522 if semicolon then pr ";"
9524 and generate_java_struct jtyp cols () =
9525 generate_header CStyle LGPLv2plus;
9528 package com.redhat.et.libguestfs;
9531 * Libguestfs %s structure.
9543 | name, FBuffer -> pr " public String %s;\n" name
9544 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9545 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9546 | name, FChar -> pr " public char %s;\n" name
9547 | name, FOptPercent ->
9548 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9549 pr " public float %s;\n" name
9554 and generate_java_c () =
9555 generate_header CStyle LGPLv2plus;
9562 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9563 #include \"guestfs.h\"
9565 /* Note that this function returns. The exception is not thrown
9566 * until after the wrapper function returns.
9569 throw_exception (JNIEnv *env, const char *msg)
9572 cl = (*env)->FindClass (env,
9573 \"com/redhat/et/libguestfs/LibGuestFSException\");
9574 (*env)->ThrowNew (env, cl, msg);
9577 JNIEXPORT jlong JNICALL
9578 Java_com_redhat_et_libguestfs_GuestFS__1create
9579 (JNIEnv *env, jobject obj)
9583 g = guestfs_create ();
9585 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9588 guestfs_set_error_handler (g, NULL, NULL);
9589 return (jlong) (long) g;
9592 JNIEXPORT void JNICALL
9593 Java_com_redhat_et_libguestfs_GuestFS__1close
9594 (JNIEnv *env, jobject obj, jlong jg)
9596 guestfs_h *g = (guestfs_h *) (long) jg;
9603 fun (name, style, _, _, _, _, _) ->
9605 (match fst style with
9606 | RErr -> pr "void ";
9607 | RInt _ -> pr "jint ";
9608 | RInt64 _ -> pr "jlong ";
9609 | RBool _ -> pr "jboolean ";
9610 | RConstString _ | RConstOptString _ | RString _
9611 | RBufferOut _ -> pr "jstring ";
9612 | RStruct _ | RHashtable _ ->
9614 | RStringList _ | RStructList _ ->
9618 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9619 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9621 pr " (JNIEnv *env, jobject obj, jlong jg";
9625 | Device n | Dev_or_Path n
9630 pr ", jstring j%s" n
9631 | StringList n | DeviceList n ->
9632 pr ", jobjectArray j%s" n
9634 pr ", jboolean j%s" n
9642 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9643 let error_code, no_ret =
9644 match fst style with
9645 | RErr -> pr " int r;\n"; "-1", ""
9647 | RInt _ -> pr " int r;\n"; "-1", "0"
9648 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9649 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9650 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9652 pr " jstring jr;\n";
9653 pr " char *r;\n"; "NULL", "NULL"
9655 pr " jobjectArray jr;\n";
9658 pr " jstring jstr;\n";
9659 pr " char **r;\n"; "NULL", "NULL"
9660 | RStruct (_, typ) ->
9661 pr " jobject jr;\n";
9663 pr " jfieldID fl;\n";
9664 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9665 | RStructList (_, typ) ->
9666 pr " jobjectArray jr;\n";
9668 pr " jfieldID fl;\n";
9669 pr " jobject jfl;\n";
9670 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9671 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9673 pr " jstring jr;\n";
9675 pr " size_t size;\n";
9680 | Device n | Dev_or_Path n
9685 pr " const char *%s;\n" n
9686 | StringList n | DeviceList n ->
9687 pr " int %s_len;\n" n;
9688 pr " const char **%s;\n" n
9693 pr " int64_t %s;\n" n
9697 (match fst style with
9698 | RStringList _ | RStructList _ -> true
9699 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9701 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9702 List.exists (function
9703 | StringList _ -> true
9704 | DeviceList _ -> true
9705 | _ -> false) (snd style) in
9711 (* Get the parameters. *)
9715 | Device n | Dev_or_Path n
9719 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9721 (* This is completely undocumented, but Java null becomes
9724 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9725 | StringList n | DeviceList n ->
9726 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9727 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9728 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9729 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9731 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9733 pr " %s[%s_len] = NULL;\n" n n;
9737 pr " %s = j%s;\n" n n
9740 (* Make the call. *)
9741 pr " r = guestfs_%s " name;
9742 generate_c_call_args ~handle:"g" style;
9745 (* Release the parameters. *)
9749 | Device n | Dev_or_Path n
9753 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9756 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9757 | StringList n | DeviceList n ->
9758 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9759 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9761 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9763 pr " free (%s);\n" n
9769 (* Check for errors. *)
9770 pr " if (r == %s) {\n" error_code;
9771 pr " throw_exception (env, guestfs_last_error (g));\n";
9772 pr " return %s;\n" no_ret;
9776 (match fst style with
9778 | RInt _ -> pr " return (jint) r;\n"
9779 | RBool _ -> pr " return (jboolean) r;\n"
9780 | RInt64 _ -> pr " return (jlong) r;\n"
9781 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9782 | RConstOptString _ ->
9783 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9785 pr " jr = (*env)->NewStringUTF (env, r);\n";
9789 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9790 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9791 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9792 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9793 pr " for (i = 0; i < r_len; ++i) {\n";
9794 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9795 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9796 pr " free (r[i]);\n";
9800 | RStruct (_, typ) ->
9801 let jtyp = java_name_of_struct typ in
9802 let cols = cols_of_struct typ in
9803 generate_java_struct_return typ jtyp cols
9804 | RStructList (_, typ) ->
9805 let jtyp = java_name_of_struct typ in
9806 let cols = cols_of_struct typ in
9807 generate_java_struct_list_return typ jtyp cols
9810 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9811 pr " return NULL;\n"
9813 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9822 and generate_java_struct_return typ jtyp cols =
9823 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9824 pr " jr = (*env)->AllocObject (env, cl);\n";
9828 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9829 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9832 pr " char s[33];\n";
9833 pr " memcpy (s, r->%s, 32);\n" name;
9835 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9836 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9840 pr " int len = r->%s_len;\n" name;
9841 pr " char s[len+1];\n";
9842 pr " memcpy (s, r->%s, len);\n" name;
9843 pr " s[len] = 0;\n";
9844 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9845 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9847 | name, (FBytes|FUInt64|FInt64) ->
9848 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9849 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9850 | name, (FUInt32|FInt32) ->
9851 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9852 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9853 | name, FOptPercent ->
9854 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9855 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9857 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9858 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9863 and generate_java_struct_list_return typ jtyp cols =
9864 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9865 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9866 pr " for (i = 0; i < r->len; ++i) {\n";
9867 pr " jfl = (*env)->AllocObject (env, cl);\n";
9871 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9872 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9875 pr " char s[33];\n";
9876 pr " memcpy (s, r->val[i].%s, 32);\n" name;
9878 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9879 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9883 pr " int len = r->val[i].%s_len;\n" name;
9884 pr " char s[len+1];\n";
9885 pr " memcpy (s, r->val[i].%s, len);\n" name;
9886 pr " s[len] = 0;\n";
9887 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9888 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9890 | name, (FBytes|FUInt64|FInt64) ->
9891 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9892 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9893 | name, (FUInt32|FInt32) ->
9894 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9895 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9896 | name, FOptPercent ->
9897 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9898 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9900 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9901 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9903 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9905 pr " guestfs_free_%s_list (r);\n" typ;
9908 and generate_java_makefile_inc () =
9909 generate_header HashStyle GPLv2plus;
9911 pr "java_built_sources = \\\n";
9914 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9916 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9918 and generate_haskell_hs () =
9919 generate_header HaskellStyle LGPLv2plus;
9921 (* XXX We only know how to generate partial FFI for Haskell
9922 * at the moment. Please help out!
9924 let can_generate style =
9928 | RInt64 _, _ -> true
9931 | RConstOptString _, _
9937 | RBufferOut _, _ -> false in
9940 {-# INCLUDE <guestfs.h> #-}
9941 {-# LANGUAGE ForeignFunctionInterface #-}
9946 (* List out the names of the actions we want to export. *)
9948 fun (name, style, _, _, _, _, _) ->
9949 if can_generate style then pr ",\n %s" name
9955 -- Unfortunately some symbols duplicate ones already present
9956 -- in Prelude. We don't know which, so we hard-code a list
9958 import Prelude hiding (truncate)
9962 import Foreign.C.Types
9964 import Control.Exception
9965 import Data.Typeable
9967 data GuestfsS = GuestfsS -- represents the opaque C struct
9968 type GuestfsP = Ptr GuestfsS -- guestfs_h *
9969 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9971 -- XXX define properly later XXX
9975 data IntBool = IntBool
9977 data StatVFS = StatVFS
9978 data Hashtable = Hashtable
9980 foreign import ccall unsafe \"guestfs_create\" c_create
9982 foreign import ccall unsafe \"&guestfs_close\" c_close
9983 :: FunPtr (GuestfsP -> IO ())
9984 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9985 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9987 create :: IO GuestfsH
9990 c_set_error_handler p nullPtr nullPtr
9991 h <- newForeignPtr c_close p
9994 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9995 :: GuestfsP -> IO CString
9997 -- last_error :: GuestfsH -> IO (Maybe String)
9998 -- last_error h = do
9999 -- str <- withForeignPtr h (\\p -> c_last_error p)
10000 -- maybePeek peekCString str
10002 last_error :: GuestfsH -> IO (String)
10004 str <- withForeignPtr h (\\p -> c_last_error p)
10005 if (str == nullPtr)
10006 then return \"no error\"
10007 else peekCString str
10011 (* Generate wrappers for each foreign function. *)
10013 fun (name, style, _, _, _, _, _) ->
10014 if can_generate style then (
10015 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10017 generate_haskell_prototype ~handle:"GuestfsP" style;
10021 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10023 pr "%s %s = do\n" name
10024 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10026 (* Convert pointer arguments using with* functions. *)
10031 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10032 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10033 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10034 | Bool _ | Int _ | Int64 _ -> ()
10036 (* Convert integer arguments. *)
10040 | Bool n -> sprintf "(fromBool %s)" n
10041 | Int n -> sprintf "(fromIntegral %s)" n
10042 | Int64 n -> sprintf "(fromIntegral %s)" n
10043 | FileIn n | FileOut n
10044 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10046 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10047 (String.concat " " ("p" :: args));
10048 (match fst style with
10049 | RErr | RInt _ | RInt64 _ | RBool _ ->
10050 pr " if (r == -1)\n";
10052 pr " err <- last_error h\n";
10054 | RConstString _ | RConstOptString _ | RString _
10055 | RStringList _ | RStruct _
10056 | RStructList _ | RHashtable _ | RBufferOut _ ->
10057 pr " if (r == nullPtr)\n";
10059 pr " err <- last_error h\n";
10062 (match fst style with
10064 pr " else return ()\n"
10066 pr " else return (fromIntegral r)\n"
10068 pr " else return (fromIntegral r)\n"
10070 pr " else return (toBool r)\n"
10072 | RConstOptString _
10079 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10085 and generate_haskell_prototype ~handle ?(hs = false) style =
10086 pr "%s -> " handle;
10087 let string = if hs then "String" else "CString" in
10088 let int = if hs then "Int" else "CInt" in
10089 let bool = if hs then "Bool" else "CInt" in
10090 let int64 = if hs then "Integer" else "Int64" in
10094 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10095 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10096 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10097 | Bool _ -> pr "%s" bool
10098 | Int _ -> pr "%s" int
10099 | Int64 _ -> pr "%s" int
10100 | FileIn _ -> pr "%s" string
10101 | FileOut _ -> pr "%s" string
10106 (match fst style with
10107 | RErr -> if not hs then pr "CInt"
10108 | RInt _ -> pr "%s" int
10109 | RInt64 _ -> pr "%s" int64
10110 | RBool _ -> pr "%s" bool
10111 | RConstString _ -> pr "%s" string
10112 | RConstOptString _ -> pr "Maybe %s" string
10113 | RString _ -> pr "%s" string
10114 | RStringList _ -> pr "[%s]" string
10115 | RStruct (_, typ) ->
10116 let name = java_name_of_struct typ in
10118 | RStructList (_, typ) ->
10119 let name = java_name_of_struct typ in
10121 | RHashtable _ -> pr "Hashtable"
10122 | RBufferOut _ -> pr "%s" string
10126 and generate_csharp () =
10127 generate_header CPlusPlusStyle LGPLv2plus;
10129 (* XXX Make this configurable by the C# assembly users. *)
10130 let library = "libguestfs.so.0" in
10133 // These C# bindings are highly experimental at present.
10135 // Firstly they only work on Linux (ie. Mono). In order to get them
10136 // to work on Windows (ie. .Net) you would need to port the library
10137 // itself to Windows first.
10139 // The second issue is that some calls are known to be incorrect and
10140 // can cause Mono to segfault. Particularly: calls which pass or
10141 // return string[], or return any structure value. This is because
10142 // we haven't worked out the correct way to do this from C#.
10144 // The third issue is that when compiling you get a lot of warnings.
10145 // We are not sure whether the warnings are important or not.
10147 // Fourthly we do not routinely build or test these bindings as part
10148 // of the make && make check cycle, which means that regressions might
10151 // Suggestions and patches are welcome.
10155 // gmcs Libguestfs.cs
10156 // mono Libguestfs.exe
10158 // (You'll probably want to add a Test class / static main function
10159 // otherwise this won't do anything useful).
10163 using System.Runtime.InteropServices;
10164 using System.Runtime.Serialization;
10165 using System.Collections;
10169 class Error : System.ApplicationException
10171 public Error (string message) : base (message) {}
10172 protected Error (SerializationInfo info, StreamingContext context) {}
10179 [DllImport (\"%s\")]
10180 static extern IntPtr guestfs_create ();
10184 _handle = guestfs_create ();
10185 if (_handle == IntPtr.Zero)
10186 throw new Error (\"could not create guestfs handle\");
10189 [DllImport (\"%s\")]
10190 static extern void guestfs_close (IntPtr h);
10194 guestfs_close (_handle);
10197 [DllImport (\"%s\")]
10198 static extern string guestfs_last_error (IntPtr h);
10200 " library library library;
10202 (* Generate C# structure bindings. We prefix struct names with
10203 * underscore because C# cannot have conflicting struct names and
10204 * method names (eg. "class stat" and "stat").
10208 pr " [StructLayout (LayoutKind.Sequential)]\n";
10209 pr " public class _%s {\n" typ;
10212 | name, FChar -> pr " char %s;\n" name
10213 | name, FString -> pr " string %s;\n" name
10215 pr " uint %s_len;\n" name;
10216 pr " string %s;\n" name
10218 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10219 pr " string %s;\n" name
10220 | name, FUInt32 -> pr " uint %s;\n" name
10221 | name, FInt32 -> pr " int %s;\n" name
10222 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10223 | name, FInt64 -> pr " long %s;\n" name
10224 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10230 (* Generate C# function bindings. *)
10232 fun (name, style, _, _, _, shortdesc, _) ->
10233 let rec csharp_return_type () =
10234 match fst style with
10236 | RBool n -> "bool"
10238 | RInt64 n -> "long"
10240 | RConstOptString n
10242 | RBufferOut n -> "string"
10243 | RStruct (_,n) -> "_" ^ n
10244 | RHashtable n -> "Hashtable"
10245 | RStringList n -> "string[]"
10246 | RStructList (_,n) -> sprintf "_%s[]" n
10248 and c_return_type () =
10249 match fst style with
10253 | RInt64 _ -> "long"
10255 | RConstOptString _
10257 | RBufferOut _ -> "string"
10258 | RStruct (_,n) -> "_" ^ n
10260 | RStringList _ -> "string[]"
10261 | RStructList (_,n) -> sprintf "_%s[]" n
10263 and c_error_comparison () =
10264 match fst style with
10268 | RInt64 _ -> "== -1"
10270 | RConstOptString _
10276 | RStructList (_,_) -> "== null"
10278 and generate_extern_prototype () =
10279 pr " static extern %s guestfs_%s (IntPtr h"
10280 (c_return_type ()) name;
10283 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10284 | FileIn n | FileOut n ->
10285 pr ", [In] string %s" n
10286 | StringList n | DeviceList n ->
10287 pr ", [In] string[] %s" n
10297 and generate_public_prototype () =
10298 pr " public %s %s (" (csharp_return_type ()) name;
10299 let comma = ref false in
10301 if !comma then pr ", ";
10306 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10307 | FileIn n | FileOut n ->
10308 next (); pr "string %s" n
10309 | StringList n | DeviceList n ->
10310 next (); pr "string[] %s" n
10312 next (); pr "bool %s" n
10314 next (); pr "int %s" n
10316 next (); pr "long %s" n
10320 and generate_call () =
10321 pr "guestfs_%s (_handle" name;
10322 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10326 pr " [DllImport (\"%s\")]\n" library;
10327 generate_extern_prototype ();
10329 pr " /// <summary>\n";
10330 pr " /// %s\n" shortdesc;
10331 pr " /// </summary>\n";
10332 generate_public_prototype ();
10334 pr " %s r;\n" (c_return_type ());
10337 pr " if (r %s)\n" (c_error_comparison ());
10338 pr " throw new Error (guestfs_last_error (_handle));\n";
10339 (match fst style with
10342 pr " return r != 0 ? true : false;\n"
10344 pr " Hashtable rr = new Hashtable ();\n";
10345 pr " for (int i = 0; i < r.Length; i += 2)\n";
10346 pr " rr.Add (r[i], r[i+1]);\n";
10348 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10349 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10355 ) all_functions_sorted;
10361 and generate_bindtests () =
10362 generate_header CStyle LGPLv2plus;
10366 #include <stdlib.h>
10367 #include <inttypes.h>
10368 #include <string.h>
10370 #include \"guestfs.h\"
10371 #include \"guestfs-internal.h\"
10372 #include \"guestfs-internal-actions.h\"
10373 #include \"guestfs_protocol.h\"
10375 #define error guestfs_error
10376 #define safe_calloc guestfs_safe_calloc
10377 #define safe_malloc guestfs_safe_malloc
10380 print_strings (char *const *argv)
10385 for (argc = 0; argv[argc] != NULL; ++argc) {
10386 if (argc > 0) printf (\", \");
10387 printf (\"\\\"%%s\\\"\", argv[argc]);
10392 /* The test0 function prints its parameters to stdout. */
10396 match test_functions with
10397 | [] -> assert false
10398 | test0 :: tests -> test0, tests in
10401 let (name, style, _, _, _, _, _) = test0 in
10402 generate_prototype ~extern:false ~semicolon:false ~newline:true
10403 ~handle:"g" ~prefix:"guestfs__" name style;
10408 | Device n | Dev_or_Path n
10411 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10412 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10413 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10414 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10415 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10416 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10418 pr " /* Java changes stdout line buffering so we need this: */\n";
10419 pr " fflush (stdout);\n";
10425 fun (name, style, _, _, _, _, _) ->
10426 if String.sub name (String.length name - 3) 3 <> "err" then (
10427 pr "/* Test normal return. */\n";
10428 generate_prototype ~extern:false ~semicolon:false ~newline:true
10429 ~handle:"g" ~prefix:"guestfs__" name style;
10431 (match fst style with
10436 pr " sscanf (val, \"%%d\", &r);\n";
10439 pr " int64_t r;\n";
10440 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10443 pr " return STREQ (val, \"true\");\n"
10445 | RConstOptString _ ->
10446 (* Can't return the input string here. Return a static
10447 * string so we ensure we get a segfault if the caller
10448 * tries to free it.
10450 pr " return \"static string\";\n"
10452 pr " return strdup (val);\n"
10454 pr " char **strs;\n";
10456 pr " sscanf (val, \"%%d\", &n);\n";
10457 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10458 pr " for (i = 0; i < n; ++i) {\n";
10459 pr " strs[i] = safe_malloc (g, 16);\n";
10460 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10462 pr " strs[n] = NULL;\n";
10463 pr " return strs;\n"
10464 | RStruct (_, typ) ->
10465 pr " struct guestfs_%s *r;\n" typ;
10466 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10468 | RStructList (_, typ) ->
10469 pr " struct guestfs_%s_list *r;\n" typ;
10470 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10471 pr " sscanf (val, \"%%d\", &r->len);\n";
10472 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10475 pr " char **strs;\n";
10477 pr " sscanf (val, \"%%d\", &n);\n";
10478 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10479 pr " for (i = 0; i < n; ++i) {\n";
10480 pr " strs[i*2] = safe_malloc (g, 16);\n";
10481 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10482 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10483 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10485 pr " strs[n*2] = NULL;\n";
10486 pr " return strs;\n"
10488 pr " return strdup (val);\n"
10493 pr "/* Test error return. */\n";
10494 generate_prototype ~extern:false ~semicolon:false ~newline:true
10495 ~handle:"g" ~prefix:"guestfs__" name style;
10497 pr " error (g, \"error\");\n";
10498 (match fst style with
10499 | RErr | RInt _ | RInt64 _ | RBool _ ->
10501 | RConstString _ | RConstOptString _
10502 | RString _ | RStringList _ | RStruct _
10506 pr " return NULL;\n"
10513 and generate_ocaml_bindtests () =
10514 generate_header OCamlStyle GPLv2plus;
10518 let g = Guestfs.create () in
10522 String.concat " " (
10525 | CallString s -> "\"" ^ s ^ "\""
10526 | CallOptString None -> "None"
10527 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10528 | CallStringList xs ->
10529 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10530 | CallInt i when i >= 0 -> string_of_int i
10531 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10532 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10533 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10534 | CallBool b -> string_of_bool b
10539 generate_lang_bindtests (
10540 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10543 pr "print_endline \"EOF\"\n"
10545 and generate_perl_bindtests () =
10546 pr "#!/usr/bin/perl -w\n";
10547 generate_header HashStyle GPLv2plus;
10554 my $g = Sys::Guestfs->new ();
10558 String.concat ", " (
10561 | CallString s -> "\"" ^ s ^ "\""
10562 | CallOptString None -> "undef"
10563 | CallOptString (Some s) -> sprintf "\"%s\"" s
10564 | CallStringList xs ->
10565 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10566 | CallInt i -> string_of_int i
10567 | CallInt64 i -> Int64.to_string i
10568 | CallBool b -> if b then "1" else "0"
10573 generate_lang_bindtests (
10574 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10577 pr "print \"EOF\\n\"\n"
10579 and generate_python_bindtests () =
10580 generate_header HashStyle GPLv2plus;
10585 g = guestfs.GuestFS ()
10589 String.concat ", " (
10592 | CallString s -> "\"" ^ s ^ "\""
10593 | CallOptString None -> "None"
10594 | CallOptString (Some s) -> sprintf "\"%s\"" s
10595 | CallStringList xs ->
10596 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10597 | CallInt i -> string_of_int i
10598 | CallInt64 i -> Int64.to_string i
10599 | CallBool b -> if b then "1" else "0"
10604 generate_lang_bindtests (
10605 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10608 pr "print \"EOF\"\n"
10610 and generate_ruby_bindtests () =
10611 generate_header HashStyle GPLv2plus;
10616 g = Guestfs::create()
10620 String.concat ", " (
10623 | CallString s -> "\"" ^ s ^ "\""
10624 | CallOptString None -> "nil"
10625 | CallOptString (Some s) -> sprintf "\"%s\"" s
10626 | CallStringList xs ->
10627 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10628 | CallInt i -> string_of_int i
10629 | CallInt64 i -> Int64.to_string i
10630 | CallBool b -> string_of_bool b
10635 generate_lang_bindtests (
10636 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10639 pr "print \"EOF\\n\"\n"
10641 and generate_java_bindtests () =
10642 generate_header CStyle GPLv2plus;
10645 import com.redhat.et.libguestfs.*;
10647 public class Bindtests {
10648 public static void main (String[] argv)
10651 GuestFS g = new GuestFS ();
10655 String.concat ", " (
10658 | CallString s -> "\"" ^ s ^ "\""
10659 | CallOptString None -> "null"
10660 | CallOptString (Some s) -> sprintf "\"%s\"" s
10661 | CallStringList xs ->
10663 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10664 | CallInt i -> string_of_int i
10665 | CallInt64 i -> Int64.to_string i
10666 | CallBool b -> string_of_bool b
10671 generate_lang_bindtests (
10672 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10676 System.out.println (\"EOF\");
10678 catch (Exception exn) {
10679 System.err.println (exn);
10686 and generate_haskell_bindtests () =
10687 generate_header HaskellStyle GPLv2plus;
10690 module Bindtests where
10691 import qualified Guestfs
10694 g <- Guestfs.create
10698 String.concat " " (
10701 | CallString s -> "\"" ^ s ^ "\""
10702 | CallOptString None -> "Nothing"
10703 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10704 | CallStringList xs ->
10705 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10706 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10707 | CallInt i -> string_of_int i
10708 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10709 | CallInt64 i -> Int64.to_string i
10710 | CallBool true -> "True"
10711 | CallBool false -> "False"
10716 generate_lang_bindtests (
10717 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10720 pr " putStrLn \"EOF\"\n"
10722 (* Language-independent bindings tests - we do it this way to
10723 * ensure there is parity in testing bindings across all languages.
10725 and generate_lang_bindtests call =
10726 call "test0" [CallString "abc"; CallOptString (Some "def");
10727 CallStringList []; CallBool false;
10728 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10729 call "test0" [CallString "abc"; CallOptString None;
10730 CallStringList []; CallBool false;
10731 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10732 call "test0" [CallString ""; CallOptString (Some "def");
10733 CallStringList []; CallBool false;
10734 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10735 call "test0" [CallString ""; CallOptString (Some "");
10736 CallStringList []; CallBool false;
10737 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10738 call "test0" [CallString "abc"; CallOptString (Some "def");
10739 CallStringList ["1"]; CallBool false;
10740 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10741 call "test0" [CallString "abc"; CallOptString (Some "def");
10742 CallStringList ["1"; "2"]; CallBool false;
10743 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10744 call "test0" [CallString "abc"; CallOptString (Some "def");
10745 CallStringList ["1"]; CallBool true;
10746 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10747 call "test0" [CallString "abc"; CallOptString (Some "def");
10748 CallStringList ["1"]; CallBool false;
10749 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10750 call "test0" [CallString "abc"; CallOptString (Some "def");
10751 CallStringList ["1"]; CallBool false;
10752 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10753 call "test0" [CallString "abc"; CallOptString (Some "def");
10754 CallStringList ["1"]; CallBool false;
10755 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10756 call "test0" [CallString "abc"; CallOptString (Some "def");
10757 CallStringList ["1"]; CallBool false;
10758 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10759 call "test0" [CallString "abc"; CallOptString (Some "def");
10760 CallStringList ["1"]; CallBool false;
10761 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10762 call "test0" [CallString "abc"; CallOptString (Some "def");
10763 CallStringList ["1"]; CallBool false;
10764 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10766 (* XXX Add here tests of the return and error functions. *)
10768 (* Code to generator bindings for virt-inspector. Currently only
10769 * implemented for OCaml code (for virt-p2v 2.0).
10771 let rng_input = "inspector/virt-inspector.rng"
10773 (* Read the input file and parse it into internal structures. This is
10774 * by no means a complete RELAX NG parser, but is just enough to be
10775 * able to parse the specific input file.
10778 | Element of string * rng list (* <element name=name/> *)
10779 | Attribute of string * rng list (* <attribute name=name/> *)
10780 | Interleave of rng list (* <interleave/> *)
10781 | ZeroOrMore of rng (* <zeroOrMore/> *)
10782 | OneOrMore of rng (* <oneOrMore/> *)
10783 | Optional of rng (* <optional/> *)
10784 | Choice of string list (* <choice><value/>*</choice> *)
10785 | Value of string (* <value>str</value> *)
10786 | Text (* <text/> *)
10788 let rec string_of_rng = function
10789 | Element (name, xs) ->
10790 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10791 | Attribute (name, xs) ->
10792 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10793 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10794 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10795 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10796 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10797 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10798 | Value value -> "Value \"" ^ value ^ "\""
10801 and string_of_rng_list xs =
10802 String.concat ", " (List.map string_of_rng xs)
10804 let rec parse_rng ?defines context = function
10806 | Xml.Element ("element", ["name", name], children) :: rest ->
10807 Element (name, parse_rng ?defines context children)
10808 :: parse_rng ?defines context rest
10809 | Xml.Element ("attribute", ["name", name], children) :: rest ->
10810 Attribute (name, parse_rng ?defines context children)
10811 :: parse_rng ?defines context rest
10812 | Xml.Element ("interleave", [], children) :: rest ->
10813 Interleave (parse_rng ?defines context children)
10814 :: parse_rng ?defines context rest
10815 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10816 let rng = parse_rng ?defines context [child] in
10818 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10820 failwithf "%s: <zeroOrMore> contains more than one child element"
10823 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10824 let rng = parse_rng ?defines context [child] in
10826 | [child] -> OneOrMore child :: parse_rng ?defines context rest
10828 failwithf "%s: <oneOrMore> contains more than one child element"
10831 | Xml.Element ("optional", [], [child]) :: rest ->
10832 let rng = parse_rng ?defines context [child] in
10834 | [child] -> Optional child :: parse_rng ?defines context rest
10836 failwithf "%s: <optional> contains more than one child element"
10839 | Xml.Element ("choice", [], children) :: rest ->
10840 let values = List.map (
10841 function Xml.Element ("value", [], [Xml.PCData value]) -> value
10843 failwithf "%s: can't handle anything except <value> in <choice>"
10847 :: parse_rng ?defines context rest
10848 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10849 Value value :: parse_rng ?defines context rest
10850 | Xml.Element ("text", [], []) :: rest ->
10851 Text :: parse_rng ?defines context rest
10852 | Xml.Element ("ref", ["name", name], []) :: rest ->
10853 (* Look up the reference. Because of limitations in this parser,
10854 * we can't handle arbitrarily nested <ref> yet. You can only
10855 * use <ref> from inside <start>.
10857 (match defines with
10859 failwithf "%s: contains <ref>, but no refs are defined yet" context
10861 let rng = StringMap.find name map in
10862 rng @ parse_rng ?defines context rest
10865 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10868 let xml = Xml.parse_file rng_input in
10870 | Xml.Element ("grammar", _,
10871 Xml.Element ("start", _, gram) :: defines) ->
10872 (* The <define/> elements are referenced in the <start> section,
10873 * so build a map of those first.
10875 let defines = List.fold_left (
10877 function Xml.Element ("define", ["name", name], defn) ->
10878 StringMap.add name defn map
10880 failwithf "%s: expected <define name=name/>" rng_input
10881 ) StringMap.empty defines in
10882 let defines = StringMap.mapi parse_rng defines in
10884 (* Parse the <start> clause, passing the defines. *)
10885 parse_rng ~defines "<start>" gram
10887 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10890 let name_of_field = function
10891 | Element (name, _) | Attribute (name, _)
10892 | ZeroOrMore (Element (name, _))
10893 | OneOrMore (Element (name, _))
10894 | Optional (Element (name, _)) -> name
10895 | Optional (Attribute (name, _)) -> name
10896 | Text -> (* an unnamed field in an element *)
10899 failwithf "name_of_field failed at: %s" (string_of_rng rng)
10901 (* At the moment this function only generates OCaml types. However we
10902 * should parameterize it later so it can generate types/structs in a
10903 * variety of languages.
10905 let generate_types xs =
10906 (* A simple type is one that can be printed out directly, eg.
10907 * "string option". A complex type is one which has a name and has
10908 * to be defined via another toplevel definition, eg. a struct.
10910 * generate_type generates code for either simple or complex types.
10911 * In the simple case, it returns the string ("string option"). In
10912 * the complex case, it returns the name ("mountpoint"). In the
10913 * complex case it has to print out the definition before returning,
10914 * so it should only be called when we are at the beginning of a
10915 * new line (BOL context).
10917 let rec generate_type = function
10918 | Text -> (* string *)
10920 | Choice values -> (* [`val1|`val2|...] *)
10921 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10922 | ZeroOrMore rng -> (* <rng> list *)
10923 let t, is_simple = generate_type rng in
10924 t ^ " list (* 0 or more *)", is_simple
10925 | OneOrMore rng -> (* <rng> list *)
10926 let t, is_simple = generate_type rng in
10927 t ^ " list (* 1 or more *)", is_simple
10928 (* virt-inspector hack: bool *)
10929 | Optional (Attribute (name, [Value "1"])) ->
10931 | Optional rng -> (* <rng> list *)
10932 let t, is_simple = generate_type rng in
10933 t ^ " option", is_simple
10934 (* type name = { fields ... } *)
10935 | Element (name, fields) when is_attrs_interleave fields ->
10936 generate_type_struct name (get_attrs_interleave fields)
10937 | Element (name, [field]) (* type name = field *)
10938 | Attribute (name, [field]) ->
10939 let t, is_simple = generate_type field in
10940 if is_simple then (t, true)
10942 pr "type %s = %s\n" name t;
10945 | Element (name, fields) -> (* type name = { fields ... } *)
10946 generate_type_struct name fields
10948 failwithf "generate_type failed at: %s" (string_of_rng rng)
10950 and is_attrs_interleave = function
10951 | [Interleave _] -> true
10952 | Attribute _ :: fields -> is_attrs_interleave fields
10953 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10956 and get_attrs_interleave = function
10957 | [Interleave fields] -> fields
10958 | ((Attribute _) as field) :: fields
10959 | ((Optional (Attribute _)) as field) :: fields ->
10960 field :: get_attrs_interleave fields
10961 | _ -> assert false
10963 and generate_types xs =
10964 List.iter (fun x -> ignore (generate_type x)) xs
10966 and generate_type_struct name fields =
10967 (* Calculate the types of the fields first. We have to do this
10968 * before printing anything so we are still in BOL context.
10970 let types = List.map fst (List.map generate_type fields) in
10972 (* Special case of a struct containing just a string and another
10973 * field. Turn it into an assoc list.
10976 | ["string"; other] ->
10977 let fname1, fname2 =
10979 | [f1; f2] -> name_of_field f1, name_of_field f2
10980 | _ -> assert false in
10981 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10985 pr "type %s = {\n" name;
10987 fun (field, ftype) ->
10988 let fname = name_of_field field in
10989 pr " %s_%s : %s;\n" name fname ftype
10990 ) (List.combine fields types);
10992 (* Return the name of this type, and
10993 * false because it's not a simple type.
11000 let generate_parsers xs =
11001 (* As for generate_type above, generate_parser makes a parser for
11002 * some type, and returns the name of the parser it has generated.
11003 * Because it (may) need to print something, it should always be
11004 * called in BOL context.
11006 let rec generate_parser = function
11007 | Text -> (* string *)
11008 "string_child_or_empty"
11009 | Choice values -> (* [`val1|`val2|...] *)
11010 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11012 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11013 | ZeroOrMore rng -> (* <rng> list *)
11014 let pa = generate_parser rng in
11015 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11016 | OneOrMore rng -> (* <rng> list *)
11017 let pa = generate_parser rng in
11018 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11019 (* virt-inspector hack: bool *)
11020 | Optional (Attribute (name, [Value "1"])) ->
11021 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11022 | Optional rng -> (* <rng> list *)
11023 let pa = generate_parser rng in
11024 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11025 (* type name = { fields ... } *)
11026 | Element (name, fields) when is_attrs_interleave fields ->
11027 generate_parser_struct name (get_attrs_interleave fields)
11028 | Element (name, [field]) -> (* type name = field *)
11029 let pa = generate_parser field in
11030 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11031 pr "let %s =\n" parser_name;
11033 pr "let parse_%s = %s\n" name parser_name;
11035 | Attribute (name, [field]) ->
11036 let pa = generate_parser field in
11037 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11038 pr "let %s =\n" parser_name;
11040 pr "let parse_%s = %s\n" name parser_name;
11042 | Element (name, fields) -> (* type name = { fields ... } *)
11043 generate_parser_struct name ([], fields)
11045 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11047 and is_attrs_interleave = function
11048 | [Interleave _] -> true
11049 | Attribute _ :: fields -> is_attrs_interleave fields
11050 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11053 and get_attrs_interleave = function
11054 | [Interleave fields] -> [], fields
11055 | ((Attribute _) as field) :: fields
11056 | ((Optional (Attribute _)) as field) :: fields ->
11057 let attrs, interleaves = get_attrs_interleave fields in
11058 (field :: attrs), interleaves
11059 | _ -> assert false
11061 and generate_parsers xs =
11062 List.iter (fun x -> ignore (generate_parser x)) xs
11064 and generate_parser_struct name (attrs, interleaves) =
11065 (* Generate parsers for the fields first. We have to do this
11066 * before printing anything so we are still in BOL context.
11068 let fields = attrs @ interleaves in
11069 let pas = List.map generate_parser fields in
11071 (* Generate an intermediate tuple from all the fields first.
11072 * If the type is just a string + another field, then we will
11073 * return this directly, otherwise it is turned into a record.
11075 * RELAX NG note: This code treats <interleave> and plain lists of
11076 * fields the same. In other words, it doesn't bother enforcing
11077 * any ordering of fields in the XML.
11079 pr "let parse_%s x =\n" name;
11080 pr " let t = (\n ";
11081 let comma = ref false in
11084 if !comma then pr ",\n ";
11087 | Optional (Attribute (fname, [field])), pa ->
11089 | Optional (Element (fname, [field])), pa ->
11090 pr "%s (optional_child %S x)" pa fname
11091 | Attribute (fname, [Text]), _ ->
11092 pr "attribute %S x" fname
11093 | (ZeroOrMore _ | OneOrMore _), pa ->
11098 let fname = name_of_field field in
11099 pr "%s (child %S x)" pa fname
11100 ) (List.combine fields pas);
11104 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11108 pr " (Obj.magic t : %s)\n" name
11112 | (Optional (Attribute (fname, [field])), pa) ->
11113 pr " %s_%s =\n" name fname;
11115 | (Optional (Element (fname, [field])), pa) ->
11116 pr " %s_%s =\n" name fname;
11117 pr " (let x = optional_child %S x in\n" fname;
11120 let fname = name_of_field field in
11121 pr " %s_%s =\n" name fname;
11122 pr " (let x = child %S x in\n" fname;
11124 ) (List.combine fields pas);
11128 sprintf "parse_%s" name
11131 generate_parsers xs
11133 (* Generate ocaml/guestfs_inspector.mli. *)
11134 let generate_ocaml_inspector_mli () =
11135 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11138 (** This is an OCaml language binding to the external [virt-inspector]
11141 For more information, please read the man page [virt-inspector(1)].
11146 generate_types grammar;
11147 pr "(** The nested information returned from the {!inspect} function. *)\n";
11151 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11152 (** To inspect a libvirt domain called [name], pass a singleton
11153 list: [inspect [name]]. When using libvirt only, you may
11154 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11156 To inspect a disk image or images, pass a list of the filenames
11157 of the disk images: [inspect filenames]
11159 This function inspects the given guest or disk images and
11160 returns a list of operating system(s) found and a large amount
11161 of information about them. In the vast majority of cases,
11162 a virtual machine only contains a single operating system.
11164 If the optional [~xml] parameter is given, then this function
11165 skips running the external virt-inspector program and just
11166 parses the given XML directly (which is expected to be XML
11167 produced from a previous run of virt-inspector). The list of
11168 names and connect URI are ignored in this case.
11170 This function can throw a wide variety of exceptions, for example
11171 if the external virt-inspector program cannot be found, or if
11172 it doesn't generate valid XML.
11176 (* Generate ocaml/guestfs_inspector.ml. *)
11177 let generate_ocaml_inspector_ml () =
11178 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11183 generate_types grammar;
11187 (* Misc functions which are used by the parser code below. *)
11188 let first_child = function
11189 | Xml.Element (_, _, c::_) -> c
11190 | Xml.Element (name, _, []) ->
11191 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11192 | Xml.PCData str ->
11193 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11195 let string_child_or_empty = function
11196 | Xml.Element (_, _, [Xml.PCData s]) -> s
11197 | Xml.Element (_, _, []) -> \"\"
11198 | Xml.Element (x, _, _) ->
11199 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11201 | Xml.PCData str ->
11202 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11204 let optional_child name xml =
11205 let children = Xml.children xml in
11207 Some (List.find (function
11208 | Xml.Element (n, _, _) when n = name -> true
11209 | _ -> false) children)
11213 let child name xml =
11214 match optional_child name xml with
11217 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11219 let attribute name xml =
11220 try Xml.attrib xml name
11221 with Xml.No_attribute _ ->
11222 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11226 generate_parsers grammar;
11230 (* Run external virt-inspector, then use parser to parse the XML. *)
11231 let inspect ?connect ?xml names =
11235 if names = [] then invalid_arg \"inspect: no names given\";
11236 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11237 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11239 let cmd = List.map Filename.quote cmd in
11240 let cmd = String.concat \" \" cmd in
11241 let chan = open_process_in cmd in
11242 let xml = Xml.parse_in chan in
11243 (match close_process_in chan with
11245 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11246 | WSIGNALED i | WSTOPPED i ->
11247 failwith (\"external virt-inspector command died or stopped on sig \" ^
11252 Xml.parse_string doc in
11253 parse_operatingsystems xml
11256 (* This is used to generate the src/MAX_PROC_NR file which
11257 * contains the maximum procedure number, a surrogate for the
11258 * ABI version number. See src/Makefile.am for the details.
11260 and generate_max_proc_nr () =
11261 let proc_nrs = List.map (
11262 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11263 ) daemon_functions in
11265 let max_proc_nr = List.fold_left max 0 proc_nrs in
11267 pr "%d\n" max_proc_nr
11269 let output_to filename k =
11270 let filename_new = filename ^ ".new" in
11271 chan := open_out filename_new;
11274 chan := Pervasives.stdout;
11276 (* Is the new file different from the current file? *)
11277 if Sys.file_exists filename && files_equal filename filename_new then
11278 unlink filename_new (* same, so skip it *)
11280 (* different, overwrite old one *)
11281 (try chmod filename 0o644 with Unix_error _ -> ());
11282 rename filename_new filename;
11283 chmod filename 0o444;
11284 printf "written %s\n%!" filename;
11287 let perror msg = function
11288 | Unix_error (err, _, _) ->
11289 eprintf "%s: %s\n" msg (error_message err)
11291 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11293 (* Main program. *)
11296 try openfile "HACKING" [O_RDWR] 0
11298 | Unix_error (ENOENT, _, _) ->
11300 You are probably running this from the wrong directory.
11301 Run it from the top source directory using the command
11306 perror "open: HACKING" exn;
11309 (* Acquire a lock so parallel builds won't try to run the generator
11310 * twice at the same time. Subsequent builds will wait for the first
11311 * one to finish. Note the lock is released implicitly when the
11314 (try lockf lock_fd F_LOCK 1
11316 perror "lock: HACKING" exn;
11319 check_functions ();
11321 output_to "src/guestfs_protocol.x" generate_xdr;
11322 output_to "src/guestfs-structs.h" generate_structs_h;
11323 output_to "src/guestfs-actions.h" generate_actions_h;
11324 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11325 output_to "src/guestfs-actions.c" generate_client_actions;
11326 output_to "src/guestfs-bindtests.c" generate_bindtests;
11327 output_to "src/guestfs-structs.pod" generate_structs_pod;
11328 output_to "src/guestfs-actions.pod" generate_actions_pod;
11329 output_to "src/guestfs-availability.pod" generate_availability_pod;
11330 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11331 output_to "src/libguestfs.syms" generate_linker_script;
11332 output_to "daemon/actions.h" generate_daemon_actions_h;
11333 output_to "daemon/stubs.c" generate_daemon_actions;
11334 output_to "daemon/names.c" generate_daemon_names;
11335 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11336 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11337 output_to "capitests/tests.c" generate_tests;
11338 output_to "fish/cmds.c" generate_fish_cmds;
11339 output_to "fish/completion.c" generate_fish_completion;
11340 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11341 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11342 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11343 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11344 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11345 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11346 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11347 output_to "perl/Guestfs.xs" generate_perl_xs;
11348 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11349 output_to "perl/bindtests.pl" generate_perl_bindtests;
11350 output_to "python/guestfs-py.c" generate_python_c;
11351 output_to "python/guestfs.py" generate_python_py;
11352 output_to "python/bindtests.py" generate_python_bindtests;
11353 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11354 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11355 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11359 let cols = cols_of_struct typ in
11360 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11361 output_to filename (generate_java_struct jtyp cols);
11364 output_to "java/Makefile.inc" generate_java_makefile_inc;
11365 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11366 output_to "java/Bindtests.java" generate_java_bindtests;
11367 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11368 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11369 output_to "csharp/Libguestfs.cs" generate_csharp;
11371 (* Always generate this file last, and unconditionally. It's used
11372 * by the Makefile to know when we must re-run the generator.
11374 let chan = open_out "src/stamp-generator" in
11375 fprintf chan "1\n";
11378 printf "generated %d lines of code\n" !lines