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 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <const char *, size_t> 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.
179 | ProtocolLimitWarning (* display warning about protocol size limits *)
180 | DangerWillRobinson (* flags particularly dangerous commands *)
181 | FishAlias of string (* provide an alias for this cmd in guestfish *)
182 | FishOutput of fish_output_t (* how to display output in guestfish *)
183 | NotInFish (* do not export via guestfish *)
184 | NotInDocs (* do not add this function to documentation *)
185 | DeprecatedBy of string (* function is deprecated, use .. instead *)
186 | Optional of string (* function is part of an optional group *)
189 | FishOutputOctal (* for int return, print in octal *)
190 | FishOutputHexadecimal (* for int return, print in hex *)
192 (* You can supply zero or as many tests as you want per API call.
194 * Note that the test environment has 3 block devices, of size 500MB,
195 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196 * a fourth ISO block device with some known files on it (/dev/sdd).
198 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199 * Number of cylinders was 63 for IDE emulated disks with precisely
200 * the same size. How exactly this is calculated is a mystery.
202 * The ISO block device (/dev/sdd) comes from images/test.iso.
204 * To be able to run the tests in a reasonable amount of time,
205 * the virtual machine and block devices are reused between tests.
206 * So don't try testing kill_subprocess :-x
208 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
210 * Don't assume anything about the previous contents of the block
211 * devices. Use 'Init*' to create some initial scenarios.
213 * You can add a prerequisite clause to any individual test. This
214 * is a run-time check, which, if it fails, causes the test to be
215 * skipped. Useful if testing a command which might not work on
216 * all variations of libguestfs builds. A test that has prerequisite
217 * of 'Always' is run unconditionally.
219 * In addition, packagers can skip individual tests by setting the
220 * environment variables: eg:
221 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
222 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
224 type tests = (test_init * test_prereq * test) list
226 (* Run the command sequence and just expect nothing to fail. *)
229 (* Run the command sequence and expect the output of the final
230 * command to be the string.
232 | TestOutput of seq * string
234 (* Run the command sequence and expect the output of the final
235 * command to be the list of strings.
237 | TestOutputList of seq * string list
239 (* Run the command sequence and expect the output of the final
240 * command to be the list of block devices (could be either
241 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242 * character of each string).
244 | TestOutputListOfDevices of seq * string list
246 (* Run the command sequence and expect the output of the final
247 * command to be the integer.
249 | TestOutputInt of seq * int
251 (* Run the command sequence and expect the output of the final
252 * command to be <op> <int>, eg. ">=", "1".
254 | TestOutputIntOp of seq * string * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a true value (!= 0 or != NULL).
259 | TestOutputTrue of seq
261 (* Run the command sequence and expect the output of the final
262 * command to be a false value (== 0 or == NULL, but not an error).
264 | TestOutputFalse of seq
266 (* Run the command sequence and expect the output of the final
267 * command to be a list of the given length (but don't care about
270 | TestOutputLength of seq * int
272 (* Run the command sequence and expect the output of the final
273 * command to be a buffer (RBufferOut), ie. string + size.
275 | TestOutputBuffer of seq * string
277 (* Run the command sequence and expect the output of the final
278 * command to be a structure.
280 | TestOutputStruct of seq * test_field_compare list
282 (* Run the command sequence and expect the final command (only)
285 | TestLastFail of seq
287 and test_field_compare =
288 | CompareWithInt of string * int
289 | CompareWithIntOp of string * string * int
290 | CompareWithString of string * string
291 | CompareFieldsIntEq of string * string
292 | CompareFieldsStrEq of string * string
294 (* Test prerequisites. *)
296 (* Test always runs. *)
299 (* Test is currently disabled - eg. it fails, or it tests some
300 * unimplemented feature.
304 (* 'string' is some C code (a function body) that should return
305 * true or false. The test will run if the code returns true.
309 (* As for 'If' but the test runs _unless_ the code returns true. *)
312 (* Some initial scenarios for testing. *)
314 (* Do nothing, block devices could contain random stuff including
315 * LVM PVs, and some filesystems might be mounted. This is usually
320 (* Block devices are empty and no filesystems are mounted. *)
323 (* /dev/sda contains a single partition /dev/sda1, with random
324 * content. /dev/sdb and /dev/sdc may have random content.
329 (* /dev/sda contains a single partition /dev/sda1, which is formatted
330 * as ext2, empty [except for lost+found] and mounted on /.
331 * /dev/sdb and /dev/sdc may have random content.
337 * /dev/sda1 (is a PV):
338 * /dev/VG/LV (size 8MB):
339 * formatted as ext2, empty [except for lost+found], mounted on /
340 * /dev/sdb and /dev/sdc may have random content.
344 (* /dev/sdd (the ISO, see images/ directory in source)
349 (* Sequence of commands for testing. *)
351 and cmd = string list
353 (* Note about long descriptions: When referring to another
354 * action, use the format C<guestfs_other> (ie. the full name of
355 * the C function). This will be replaced as appropriate in other
358 * Apart from that, long descriptions are just perldoc paragraphs.
361 (* Generate a random UUID (used in tests). *)
363 let chan = open_process_in "uuidgen" in
364 let uuid = input_line chan in
365 (match close_process_in chan with
368 failwith "uuidgen: process exited with non-zero status"
369 | WSIGNALED _ | WSTOPPED _ ->
370 failwith "uuidgen: process signalled or stopped by signal"
374 (* These test functions are used in the language binding tests. *)
376 let test_all_args = [
379 StringList "strlist";
388 let test_all_rets = [
389 (* except for RErr, which is tested thoroughly elsewhere *)
390 "test0rint", RInt "valout";
391 "test0rint64", RInt64 "valout";
392 "test0rbool", RBool "valout";
393 "test0rconststring", RConstString "valout";
394 "test0rconstoptstring", RConstOptString "valout";
395 "test0rstring", RString "valout";
396 "test0rstringlist", RStringList "valout";
397 "test0rstruct", RStruct ("valout", "lvm_pv");
398 "test0rstructlist", RStructList ("valout", "lvm_pv");
399 "test0rhashtable", RHashtable "valout";
402 let test_functions = [
403 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
405 "internal test function - do not use",
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
411 It echos the contents of each parameter to stdout.
413 You probably don't want to call this function.");
417 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
419 "internal test function - do not use",
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
425 It converts string C<val> to the return type.
427 You probably don't want to call this function.");
428 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
430 "internal test function - do not use",
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
436 This function always returns an error.
438 You probably don't want to call this function.")]
442 (* non_daemon_functions are any functions which don't get processed
443 * in the daemon, eg. functions for setting and getting local
444 * configuration values.
447 let non_daemon_functions = test_functions @ [
448 ("launch", (RErr, []), -1, [FishAlias "run"],
450 "launch the qemu subprocess",
452 Internally libguestfs is implemented by running a virtual machine
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
458 ("wait_ready", (RErr, []), -1, [NotInFish],
460 "wait until the qemu subprocess launches (no op)",
462 This function is a no op.
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete. However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
473 ("kill_subprocess", (RErr, []), -1, [],
475 "kill the qemu subprocess",
477 This kills the qemu subprocess. You should never need to call this.");
479 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
481 "add an image to examine or modify",
483 This function adds a virtual machine disk image C<filename> to the
484 guest. The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 You don't necessarily need to be root when using libguestfs. However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>. In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
505 Note that this call checks for the existence of C<filename>. This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
508 the general C<guestfs_config> call instead.");
510 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
512 "add a CD-ROM disk image to examine",
514 This function adds a virtual CD-ROM disk image to the guest.
516 This is equivalent to the qemu parameter C<-cdrom filename>.
524 This call checks for the existence of C<filename>. This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
527 the general C<guestfs_config> call instead.
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
537 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
539 "add a drive in snapshot mode (read-only)",
541 This adds a drive in snapshot mode, making it effectively
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed. We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>. In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
558 C<readonly=on> is only added where qemu supports this option.
560 Note that this call checks for the existence of C<filename>. This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
563 the general C<guestfs_config> call instead.");
565 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567 "add qemu parameters",
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>. Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
574 The first character of C<param> string must be a C<-> (dash).
576 C<value> can be NULL.");
578 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
580 "set the qemu binary",
582 Set the qemu binary that we will use.
584 The default is chosen when the library was compiled by the
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
592 Note that you should call this function as early as possible
593 after creating the handle. This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results. Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
600 ("get_qemu", (RConstString "qemu", []), -1, [],
601 [InitNone, Always, TestRun (
603 "get the qemu binary",
605 Return the current qemu binary.
607 This is always non-NULL. If it wasn't set already, then this will
608 return the default qemu binary name.");
610 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
612 "set the search path",
614 Set the path that libguestfs searches for kernel and initrd.img.
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
619 Setting C<path> to C<NULL> restores the default path.");
621 ("get_path", (RConstString "path", []), -1, [],
622 [InitNone, Always, TestRun (
624 "get the search path",
626 Return the current search path.
628 This is always non-NULL. If it wasn't set already, then this will
629 return the default path.");
631 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633 "add options to kernel command line",
635 This function is used to add additional options to the
636 guest kernel command line.
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
644 ("get_append", (RConstOptString "append", []), -1, [],
645 (* This cannot be tested with the current framework. The
646 * function can return NULL in normal operations, which the
647 * test framework interprets as an error.
650 "get the additional kernel options",
652 Return the additional kernel options which are added to the
653 guest kernel command line.
655 If C<NULL> then no options are added.");
657 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
661 If C<autosync> is true, this enables autosync. Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
669 ("get_autosync", (RBool "autosync", []), -1, [],
670 [InitNone, Always, TestRun (
671 [["get_autosync"]])],
674 Get the autosync flag.");
676 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685 ("get_verbose", (RBool "verbose", []), -1, [],
689 This returns the verbose messages flag.");
691 ("is_ready", (RBool "ready", []), -1, [],
692 [InitNone, Always, TestOutputTrue (
694 "is ready to accept commands",
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
699 For more information on states, see L<guestfs(3)>.");
701 ("is_config", (RBool "config", []), -1, [],
702 [InitNone, Always, TestOutputFalse (
704 "is in configuration state",
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
709 For more information on states, see L<guestfs(3)>.");
711 ("is_launching", (RBool "launching", []), -1, [],
712 [InitNone, Always, TestOutputFalse (
713 [["is_launching"]])],
714 "is launching subprocess",
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
719 For more information on states, see L<guestfs(3)>.");
721 ("is_busy", (RBool "busy", []), -1, [],
722 [InitNone, Always, TestOutputFalse (
724 "is busy processing a command",
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
729 For more information on states, see L<guestfs(3)>.");
731 ("get_state", (RInt "state", []), -1, [],
733 "get the current state",
735 This returns the current state as an opaque integer. This is
736 only useful for printing debug and internal error messages.
738 For more information on states, see L<guestfs(3)>.");
740 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741 [InitNone, Always, TestOutputInt (
742 [["set_memsize"; "500"];
743 ["get_memsize"]], 500)],
744 "set memory allocated to the qemu subprocess",
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess. This only has any effect if called before
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
757 ("get_memsize", (RInt "memsize", []), -1, [],
758 [InitNone, Always, TestOutputIntOp (
759 [["get_memsize"]], ">=", 256)],
760 "get memory allocated to the qemu subprocess",
762 This gets the memory size in megabytes allocated to the
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
772 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773 [InitNone, Always, TestOutputIntOp (
774 [["get_pid"]], ">=", 1)],
775 "get PID of qemu subprocess",
777 Return the process ID of the qemu subprocess. If there is no
778 qemu subprocess, then this will return an error.
780 This is an internal call used for debugging and testing.");
782 ("version", (RStruct ("version", "version"), []), -1, [],
783 [InitNone, Always, TestOutputStruct (
784 [["version"]], [CompareWithInt ("major", 1)])],
785 "get the library version number",
787 Return the libguestfs version number that the program is linked
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against. You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
795 This call was added in version C<1.0.58>. In previous
796 versions of libguestfs there was no way to get the version
797 number. From C code you can use ELF weak linking tricks to find out if
798 this symbol exists (if it doesn't, then it's an earlier version).
800 The call returns a structure with four elements. The first
801 three (C<major>, C<minor> and C<release>) are numbers and
802 correspond to the usual version triplet. The fourth element
803 (C<extra>) is a string and is normally empty, but may be
804 used for distro-specific information.
806 To construct the original version string:
807 C<$major.$minor.$release$extra>
809 I<Note:> Don't use this call to test for availability
810 of features. Distro backports makes this unreliable. Use
811 C<guestfs_available> instead.");
813 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814 [InitNone, Always, TestOutputTrue (
815 [["set_selinux"; "true"];
817 "set SELinux enabled or disabled at appliance boot",
819 This sets the selinux flag that is passed to the appliance
820 at boot time. The default is C<selinux=0> (disabled).
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
828 ("get_selinux", (RBool "selinux", []), -1, [],
830 "get SELinux enabled flag",
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
838 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839 [InitNone, Always, TestOutputFalse (
840 [["set_trace"; "false"];
842 "enable or disable command traces",
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish. In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858 ("get_trace", (RBool "trace", []), -1, [],
860 "get command trace enabled flag",
862 Return the command trace flag.");
864 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865 [InitNone, Always, TestOutputFalse (
866 [["set_direct"; "false"];
868 "enable or disable direct appliance mode",
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
878 You probably don't want to use this unless you know what you
881 The default is disabled.");
883 ("get_direct", (RBool "direct", []), -1, [],
885 "get direct appliance mode flag",
887 Return the direct appliance mode flag.");
889 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890 [InitNone, Always, TestOutputTrue (
891 [["set_recovery_proc"; "true"];
892 ["get_recovery_proc"]])],
893 "enable or disable the recovery process",
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process. The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself). In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
909 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911 "get recovery process enabled flag",
913 Return the recovery process enabled flag.");
915 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917 "add a drive specifying the QEMU block emulation to use",
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
922 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924 "add a drive read-only specifying the QEMU block emulation to use",
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
931 (* daemon_functions are any functions which cause some action
932 * to take place in the daemon.
935 let daemon_functions = [
936 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937 [InitEmpty, Always, TestOutput (
938 [["part_disk"; "/dev/sda"; "mbr"];
939 ["mkfs"; "ext2"; "/dev/sda1"];
940 ["mount"; "/dev/sda1"; "/"];
941 ["write_file"; "/new"; "new file contents"; "0"];
942 ["cat"; "/new"]], "new file contents")],
943 "mount a guest disk at a position in the filesystem",
945 Mount a guest disk at a position in the filesystem. Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest. If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
951 The rules are the same as for L<mount(2)>: A filesystem must
952 first be mounted on C</> before others can be mounted. Other
953 filesystems can only be mounted on directories which already
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly. This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability. Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
969 ("sync", (RErr, []), 2, [],
970 [ InitEmpty, Always, TestRun [["sync"]]],
971 "sync disks, writes are flushed through to the disk image",
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
979 ("touch", (RErr, [Pathname "path"]), 3, [],
980 [InitBasicFS, Always, TestOutputTrue (
982 ["exists"; "/new"]])],
983 "update file timestamps or create a new file",
985 Touch acts like the L<touch(1)> command. It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
989 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990 [InitISOFS, Always, TestOutput (
991 [["cat"; "/known-2"]], "abcdef\n")],
992 "list the contents of a file",
994 Return the contents of the file named C<path>.
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string). For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1001 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002 [], (* XXX Tricky to test because it depends on the exact format
1003 * of the 'ls -l' command, which changes between F10 and F11.
1005 "list the files in a directory (long format)",
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1010 This command is mostly useful for interactive sessions. It
1011 is I<not> intended that you try to parse the output string.");
1013 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014 [InitBasicFS, Always, TestOutputList (
1016 ["touch"; "/newer"];
1017 ["touch"; "/newest"];
1018 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019 "list the files in a directory",
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd). The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1025 This command is mostly useful for interactive sessions. Programs
1026 should probably use C<guestfs_readdir> instead.");
1028 ("list_devices", (RStringList "devices", []), 7, [],
1029 [InitEmpty, Always, TestOutputListOfDevices (
1030 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031 "list the block devices",
1033 List all the block devices.
1035 The full block device names are returned, eg. C</dev/sda>");
1037 ("list_partitions", (RStringList "partitions", []), 8, [],
1038 [InitBasicFS, Always, TestOutputListOfDevices (
1039 [["list_partitions"]], ["/dev/sda1"]);
1040 InitEmpty, Always, TestOutputListOfDevices (
1041 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043 "list the partitions",
1045 List all the partitions detected on all block devices.
1047 The full partition device names are returned, eg. C</dev/sda1>
1049 This does not return logical volumes. For that you will need to
1050 call C<guestfs_lvs>.");
1052 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054 [["pvs"]], ["/dev/sda1"]);
1055 InitEmpty, Always, TestOutputListOfDevices (
1056 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057 ["pvcreate"; "/dev/sda1"];
1058 ["pvcreate"; "/dev/sda2"];
1059 ["pvcreate"; "/dev/sda3"];
1060 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061 "list the LVM physical volumes (PVs)",
1063 List all the physical volumes detected. This is the equivalent
1064 of the L<pvs(8)> command.
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1069 See also C<guestfs_pvs_full>.");
1071 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072 [InitBasicFSonLVM, Always, TestOutputList (
1074 InitEmpty, Always, TestOutputList (
1075 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076 ["pvcreate"; "/dev/sda1"];
1077 ["pvcreate"; "/dev/sda2"];
1078 ["pvcreate"; "/dev/sda3"];
1079 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080 ["vgcreate"; "VG2"; "/dev/sda3"];
1081 ["vgs"]], ["VG1"; "VG2"])],
1082 "list the LVM volume groups (VGs)",
1084 List all the volumes groups detected. This is the equivalent
1085 of the L<vgs(8)> command.
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1090 See also C<guestfs_vgs_full>.");
1092 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093 [InitBasicFSonLVM, Always, TestOutputList (
1094 [["lvs"]], ["/dev/VG/LV"]);
1095 InitEmpty, Always, TestOutputList (
1096 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097 ["pvcreate"; "/dev/sda1"];
1098 ["pvcreate"; "/dev/sda2"];
1099 ["pvcreate"; "/dev/sda3"];
1100 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101 ["vgcreate"; "VG2"; "/dev/sda3"];
1102 ["lvcreate"; "LV1"; "VG1"; "50"];
1103 ["lvcreate"; "LV2"; "VG1"; "50"];
1104 ["lvcreate"; "LV3"; "VG2"; "50"];
1105 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106 "list the LVM logical volumes (LVs)",
1108 List all the logical volumes detected. This is the equivalent
1109 of the L<lvs(8)> command.
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1114 See also C<guestfs_lvs_full>.");
1116 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117 [], (* XXX how to test? *)
1118 "list the LVM physical volumes (PVs)",
1120 List all the physical volumes detected. This is the equivalent
1121 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1123 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124 [], (* XXX how to test? *)
1125 "list the LVM volume groups (VGs)",
1127 List all the volumes groups detected. This is the equivalent
1128 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1130 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131 [], (* XXX how to test? *)
1132 "list the LVM logical volumes (LVs)",
1134 List all the logical volumes detected. This is the equivalent
1135 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1137 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138 [InitISOFS, Always, TestOutputList (
1139 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140 InitISOFS, Always, TestOutputList (
1141 [["read_lines"; "/empty"]], [])],
1142 "read file as lines",
1144 Return the contents of the file named C<path>.
1146 The file contents are returned as a list of lines. Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line). For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1154 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155 [], (* XXX Augeas code needs tests. *)
1156 "create a new Augeas handle",
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1162 You must call this before using any other C<guestfs_aug_*>
1165 C<root> is the filesystem root. C<root> must not be NULL,
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1174 =item C<AUG_SAVE_BACKUP> = 1
1176 Keep the original file with a C<.augsave> extension.
1178 =item C<AUG_SAVE_NEWFILE> = 2
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1183 =item C<AUG_TYPE_CHECK> = 4
1185 Typecheck lenses (can be expensive).
1187 =item C<AUG_NO_STDINC> = 8
1189 Do not use standard load path for modules.
1191 =item C<AUG_SAVE_NOOP> = 16
1193 Make save a no-op, just record what would have been changed.
1195 =item C<AUG_NO_LOAD> = 32
1197 Do not load the tree in C<guestfs_aug_init>.
1201 To close the handle, you can call C<guestfs_aug_close>.
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1205 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206 [], (* XXX Augeas code needs tests. *)
1207 "close the current Augeas handle",
1209 Close the current Augeas handle and free up any resources
1210 used by it. After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1214 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "define an Augeas variable",
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226 [], (* XXX Augeas code needs tests. *)
1227 "define an Augeas node",
1229 Defines a variable C<name> whose value is the result of
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1240 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241 [], (* XXX Augeas code needs tests. *)
1242 "look up the value of an Augeas path",
1244 Look up the value associated with C<path>. If C<path>
1245 matches exactly one node, the C<value> is returned.");
1247 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248 [], (* XXX Augeas code needs tests. *)
1249 "set Augeas path to value",
1251 Set the value associated with C<path> to C<val>.
1253 In the Augeas API, it is possible to clear a node by setting
1254 the value to NULL. Due to an oversight in the libguestfs API
1255 you cannot do that with this call. Instead you must use the
1256 C<guestfs_aug_clear> call.");
1258 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1259 [], (* XXX Augeas code needs tests. *)
1260 "insert a sibling Augeas node",
1262 Create a new sibling C<label> for C<path>, inserting it into
1263 the tree before or after C<path> (depending on the boolean
1266 C<path> must match exactly one existing node in the tree, and
1267 C<label> must be a label, ie. not contain C</>, C<*> or end
1268 with a bracketed index C<[N]>.");
1270 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1271 [], (* XXX Augeas code needs tests. *)
1272 "remove an Augeas path",
1274 Remove C<path> and all of its children.
1276 On success this returns the number of entries which were removed.");
1278 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1279 [], (* XXX Augeas code needs tests. *)
1282 Move the node C<src> to C<dest>. C<src> must match exactly
1283 one node. C<dest> is overwritten if it exists.");
1285 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1286 [], (* XXX Augeas code needs tests. *)
1287 "return Augeas nodes which match augpath",
1289 Returns a list of paths which match the path expression C<path>.
1290 The returned paths are sufficiently qualified so that they match
1291 exactly one node in the current tree.");
1293 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1294 [], (* XXX Augeas code needs tests. *)
1295 "write all pending Augeas changes to disk",
1297 This writes all pending changes to disk.
1299 The flags which were passed to C<guestfs_aug_init> affect exactly
1300 how files are saved.");
1302 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1303 [], (* XXX Augeas code needs tests. *)
1304 "load files into the tree",
1306 Load files into the tree.
1308 See C<aug_load> in the Augeas documentation for the full gory
1311 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1312 [], (* XXX Augeas code needs tests. *)
1313 "list Augeas nodes under augpath",
1315 This is just a shortcut for listing C<guestfs_aug_match>
1316 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318 ("rm", (RErr, [Pathname "path"]), 29, [],
1319 [InitBasicFS, Always, TestRun
1322 InitBasicFS, Always, TestLastFail
1324 InitBasicFS, Always, TestLastFail
1329 Remove the single file C<path>.");
1331 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1332 [InitBasicFS, Always, TestRun
1335 InitBasicFS, Always, TestLastFail
1336 [["rmdir"; "/new"]];
1337 InitBasicFS, Always, TestLastFail
1339 ["rmdir"; "/new"]]],
1340 "remove a directory",
1342 Remove the single directory C<path>.");
1344 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1345 [InitBasicFS, Always, TestOutputFalse
1347 ["mkdir"; "/new/foo"];
1348 ["touch"; "/new/foo/bar"];
1350 ["exists"; "/new"]]],
1351 "remove a file or directory recursively",
1353 Remove the file or directory C<path>, recursively removing the
1354 contents if its a directory. This is like the C<rm -rf> shell
1357 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1358 [InitBasicFS, Always, TestOutputTrue
1360 ["is_dir"; "/new"]];
1361 InitBasicFS, Always, TestLastFail
1362 [["mkdir"; "/new/foo/bar"]]],
1363 "create a directory",
1365 Create a directory named C<path>.");
1367 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1368 [InitBasicFS, Always, TestOutputTrue
1369 [["mkdir_p"; "/new/foo/bar"];
1370 ["is_dir"; "/new/foo/bar"]];
1371 InitBasicFS, Always, TestOutputTrue
1372 [["mkdir_p"; "/new/foo/bar"];
1373 ["is_dir"; "/new/foo"]];
1374 InitBasicFS, Always, TestOutputTrue
1375 [["mkdir_p"; "/new/foo/bar"];
1376 ["is_dir"; "/new"]];
1377 (* Regression tests for RHBZ#503133: *)
1378 InitBasicFS, Always, TestRun
1380 ["mkdir_p"; "/new"]];
1381 InitBasicFS, Always, TestLastFail
1383 ["mkdir_p"; "/new"]]],
1384 "create a directory and parents",
1386 Create a directory named C<path>, creating any parent directories
1387 as necessary. This is like the C<mkdir -p> shell command.");
1389 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1390 [], (* XXX Need stat command to test *)
1393 Change the mode (permissions) of C<path> to C<mode>. Only
1394 numeric modes are supported.
1396 I<Note>: When using this command from guestfish, C<mode>
1397 by default would be decimal, unless you prefix it with
1398 C<0> to get octal, ie. use C<0700> not C<700>.
1400 The mode actually set is affected by the umask.");
1402 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1403 [], (* XXX Need stat command to test *)
1404 "change file owner and group",
1406 Change the file owner to C<owner> and group to C<group>.
1408 Only numeric uid and gid are supported. If you want to use
1409 names, you will need to locate and parse the password file
1410 yourself (Augeas support makes this relatively easy).");
1412 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1413 [InitISOFS, Always, TestOutputTrue (
1414 [["exists"; "/empty"]]);
1415 InitISOFS, Always, TestOutputTrue (
1416 [["exists"; "/directory"]])],
1417 "test if file or directory exists",
1419 This returns C<true> if and only if there is a file, directory
1420 (or anything) with the given C<path> name.
1422 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1425 [InitISOFS, Always, TestOutputTrue (
1426 [["is_file"; "/known-1"]]);
1427 InitISOFS, Always, TestOutputFalse (
1428 [["is_file"; "/directory"]])],
1429 "test if file exists",
1431 This returns C<true> if and only if there is a file
1432 with the given C<path> name. Note that it returns false for
1433 other objects like directories.
1435 See also C<guestfs_stat>.");
1437 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1438 [InitISOFS, Always, TestOutputFalse (
1439 [["is_dir"; "/known-3"]]);
1440 InitISOFS, Always, TestOutputTrue (
1441 [["is_dir"; "/directory"]])],
1442 "test if file exists",
1444 This returns C<true> if and only if there is a directory
1445 with the given C<path> name. Note that it returns false for
1446 other objects like files.
1448 See also C<guestfs_stat>.");
1450 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1451 [InitEmpty, Always, TestOutputListOfDevices (
1452 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1453 ["pvcreate"; "/dev/sda1"];
1454 ["pvcreate"; "/dev/sda2"];
1455 ["pvcreate"; "/dev/sda3"];
1456 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1457 "create an LVM physical volume",
1459 This creates an LVM physical volume on the named C<device>,
1460 where C<device> should usually be a partition name such
1463 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1464 [InitEmpty, Always, TestOutputList (
1465 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1466 ["pvcreate"; "/dev/sda1"];
1467 ["pvcreate"; "/dev/sda2"];
1468 ["pvcreate"; "/dev/sda3"];
1469 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1470 ["vgcreate"; "VG2"; "/dev/sda3"];
1471 ["vgs"]], ["VG1"; "VG2"])],
1472 "create an LVM volume group",
1474 This creates an LVM volume group called C<volgroup>
1475 from the non-empty list of physical volumes C<physvols>.");
1477 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1478 [InitEmpty, Always, TestOutputList (
1479 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1480 ["pvcreate"; "/dev/sda1"];
1481 ["pvcreate"; "/dev/sda2"];
1482 ["pvcreate"; "/dev/sda3"];
1483 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1484 ["vgcreate"; "VG2"; "/dev/sda3"];
1485 ["lvcreate"; "LV1"; "VG1"; "50"];
1486 ["lvcreate"; "LV2"; "VG1"; "50"];
1487 ["lvcreate"; "LV3"; "VG2"; "50"];
1488 ["lvcreate"; "LV4"; "VG2"; "50"];
1489 ["lvcreate"; "LV5"; "VG2"; "50"];
1491 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1492 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1493 "create an LVM logical volume",
1495 This creates an LVM logical volume called C<logvol>
1496 on the volume group C<volgroup>, with C<size> megabytes.");
1498 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1499 [InitEmpty, Always, TestOutput (
1500 [["part_disk"; "/dev/sda"; "mbr"];
1501 ["mkfs"; "ext2"; "/dev/sda1"];
1502 ["mount_options"; ""; "/dev/sda1"; "/"];
1503 ["write_file"; "/new"; "new file contents"; "0"];
1504 ["cat"; "/new"]], "new file contents")],
1505 "make a filesystem",
1507 This creates a filesystem on C<device> (usually a partition
1508 or LVM logical volume). The filesystem type is C<fstype>, for
1511 ("sfdisk", (RErr, [Device "device";
1512 Int "cyls"; Int "heads"; Int "sectors";
1513 StringList "lines"]), 43, [DangerWillRobinson],
1515 "create partitions on a block device",
1517 This is a direct interface to the L<sfdisk(8)> program for creating
1518 partitions on block devices.
1520 C<device> should be a block device, for example C</dev/sda>.
1522 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1523 and sectors on the device, which are passed directly to sfdisk as
1524 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1525 of these, then the corresponding parameter is omitted. Usually for
1526 'large' disks, you can just pass C<0> for these, but for small
1527 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1528 out the right geometry and you will need to tell it.
1530 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1531 information refer to the L<sfdisk(8)> manpage.
1533 To create a single partition occupying the whole disk, you would
1534 pass C<lines> as a single element list, when the single element being
1535 the string C<,> (comma).
1537 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1538 C<guestfs_part_init>");
1540 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1541 [InitBasicFS, Always, TestOutput (
1542 [["write_file"; "/new"; "new file contents"; "0"];
1543 ["cat"; "/new"]], "new file contents");
1544 InitBasicFS, Always, TestOutput (
1545 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1546 ["cat"; "/new"]], "\nnew file contents\n");
1547 InitBasicFS, Always, TestOutput (
1548 [["write_file"; "/new"; "\n\n"; "0"];
1549 ["cat"; "/new"]], "\n\n");
1550 InitBasicFS, Always, TestOutput (
1551 [["write_file"; "/new"; ""; "0"];
1552 ["cat"; "/new"]], "");
1553 InitBasicFS, Always, TestOutput (
1554 [["write_file"; "/new"; "\n\n\n"; "0"];
1555 ["cat"; "/new"]], "\n\n\n");
1556 InitBasicFS, Always, TestOutput (
1557 [["write_file"; "/new"; "\n"; "0"];
1558 ["cat"; "/new"]], "\n")],
1561 This call creates a file called C<path>. The contents of the
1562 file is the string C<content> (which can contain any 8 bit data),
1563 with length C<size>.
1565 As a special case, if C<size> is C<0>
1566 then the length is calculated using C<strlen> (so in this case
1567 the content cannot contain embedded ASCII NULs).
1569 I<NB.> Owing to a bug, writing content containing ASCII NUL
1570 characters does I<not> work, even if the length is specified.
1571 We hope to resolve this bug in a future version. In the meantime
1572 use C<guestfs_upload>.");
1574 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1575 [InitEmpty, Always, TestOutputListOfDevices (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1579 ["mounts"]], ["/dev/sda1"]);
1580 InitEmpty, Always, TestOutputList (
1581 [["part_disk"; "/dev/sda"; "mbr"];
1582 ["mkfs"; "ext2"; "/dev/sda1"];
1583 ["mount_options"; ""; "/dev/sda1"; "/"];
1586 "unmount a filesystem",
1588 This unmounts the given filesystem. The filesystem may be
1589 specified either by its mountpoint (path) or the device which
1590 contains the filesystem.");
1592 ("mounts", (RStringList "devices", []), 46, [],
1593 [InitBasicFS, Always, TestOutputListOfDevices (
1594 [["mounts"]], ["/dev/sda1"])],
1595 "show mounted filesystems",
1597 This returns the list of currently mounted filesystems. It returns
1598 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1600 Some internal mounts are not shown.
1602 See also: C<guestfs_mountpoints>");
1604 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1605 [InitBasicFS, Always, TestOutputList (
1608 (* check that umount_all can unmount nested mounts correctly: *)
1609 InitEmpty, Always, TestOutputList (
1610 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1611 ["mkfs"; "ext2"; "/dev/sda1"];
1612 ["mkfs"; "ext2"; "/dev/sda2"];
1613 ["mkfs"; "ext2"; "/dev/sda3"];
1614 ["mount_options"; ""; "/dev/sda1"; "/"];
1616 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1617 ["mkdir"; "/mp1/mp2"];
1618 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1619 ["mkdir"; "/mp1/mp2/mp3"];
1622 "unmount all filesystems",
1624 This unmounts all mounted filesystems.
1626 Some internal mounts are not unmounted by this call.");
1628 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1630 "remove all LVM LVs, VGs and PVs",
1632 This command removes all LVM logical volumes, volume groups
1633 and physical volumes.");
1635 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1636 [InitISOFS, Always, TestOutput (
1637 [["file"; "/empty"]], "empty");
1638 InitISOFS, Always, TestOutput (
1639 [["file"; "/known-1"]], "ASCII text");
1640 InitISOFS, Always, TestLastFail (
1641 [["file"; "/notexists"]])],
1642 "determine file type",
1644 This call uses the standard L<file(1)> command to determine
1645 the type or contents of the file. This also works on devices,
1646 for example to find out whether a partition contains a filesystem.
1648 This call will also transparently look inside various types
1651 The exact command which runs is C<file -zbsL path>. Note in
1652 particular that the filename is not prepended to the output
1653 (the C<-b> option).");
1655 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1656 [InitBasicFS, Always, TestOutput (
1657 [["upload"; "test-command"; "/test-command"];
1658 ["chmod"; "0o755"; "/test-command"];
1659 ["command"; "/test-command 1"]], "Result1");
1660 InitBasicFS, Always, TestOutput (
1661 [["upload"; "test-command"; "/test-command"];
1662 ["chmod"; "0o755"; "/test-command"];
1663 ["command"; "/test-command 2"]], "Result2\n");
1664 InitBasicFS, Always, TestOutput (
1665 [["upload"; "test-command"; "/test-command"];
1666 ["chmod"; "0o755"; "/test-command"];
1667 ["command"; "/test-command 3"]], "\nResult3");
1668 InitBasicFS, Always, TestOutput (
1669 [["upload"; "test-command"; "/test-command"];
1670 ["chmod"; "0o755"; "/test-command"];
1671 ["command"; "/test-command 4"]], "\nResult4\n");
1672 InitBasicFS, Always, TestOutput (
1673 [["upload"; "test-command"; "/test-command"];
1674 ["chmod"; "0o755"; "/test-command"];
1675 ["command"; "/test-command 5"]], "\nResult5\n\n");
1676 InitBasicFS, Always, TestOutput (
1677 [["upload"; "test-command"; "/test-command"];
1678 ["chmod"; "0o755"; "/test-command"];
1679 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1680 InitBasicFS, Always, TestOutput (
1681 [["upload"; "test-command"; "/test-command"];
1682 ["chmod"; "0o755"; "/test-command"];
1683 ["command"; "/test-command 7"]], "");
1684 InitBasicFS, Always, TestOutput (
1685 [["upload"; "test-command"; "/test-command"];
1686 ["chmod"; "0o755"; "/test-command"];
1687 ["command"; "/test-command 8"]], "\n");
1688 InitBasicFS, Always, TestOutput (
1689 [["upload"; "test-command"; "/test-command"];
1690 ["chmod"; "0o755"; "/test-command"];
1691 ["command"; "/test-command 9"]], "\n\n");
1692 InitBasicFS, Always, TestOutput (
1693 [["upload"; "test-command"; "/test-command"];
1694 ["chmod"; "0o755"; "/test-command"];
1695 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1696 InitBasicFS, Always, TestOutput (
1697 [["upload"; "test-command"; "/test-command"];
1698 ["chmod"; "0o755"; "/test-command"];
1699 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1700 InitBasicFS, Always, TestLastFail (
1701 [["upload"; "test-command"; "/test-command"];
1702 ["chmod"; "0o755"; "/test-command"];
1703 ["command"; "/test-command"]])],
1704 "run a command from the guest filesystem",
1706 This call runs a command from the guest filesystem. The
1707 filesystem must be mounted, and must contain a compatible
1708 operating system (ie. something Linux, with the same
1709 or compatible processor architecture).
1711 The single parameter is an argv-style list of arguments.
1712 The first element is the name of the program to run.
1713 Subsequent elements are parameters. The list must be
1714 non-empty (ie. must contain a program name). Note that
1715 the command runs directly, and is I<not> invoked via
1716 the shell (see C<guestfs_sh>).
1718 The return value is anything printed to I<stdout> by
1721 If the command returns a non-zero exit status, then
1722 this function returns an error message. The error message
1723 string is the content of I<stderr> from the command.
1725 The C<$PATH> environment variable will contain at least
1726 C</usr/bin> and C</bin>. If you require a program from
1727 another location, you should provide the full path in the
1730 Shared libraries and data files required by the program
1731 must be available on filesystems which are mounted in the
1732 correct places. It is the caller's responsibility to ensure
1733 all filesystems that are needed are mounted at the right
1736 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1737 [InitBasicFS, Always, TestOutputList (
1738 [["upload"; "test-command"; "/test-command"];
1739 ["chmod"; "0o755"; "/test-command"];
1740 ["command_lines"; "/test-command 1"]], ["Result1"]);
1741 InitBasicFS, Always, TestOutputList (
1742 [["upload"; "test-command"; "/test-command"];
1743 ["chmod"; "0o755"; "/test-command"];
1744 ["command_lines"; "/test-command 2"]], ["Result2"]);
1745 InitBasicFS, Always, TestOutputList (
1746 [["upload"; "test-command"; "/test-command"];
1747 ["chmod"; "0o755"; "/test-command"];
1748 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1749 InitBasicFS, Always, TestOutputList (
1750 [["upload"; "test-command"; "/test-command"];
1751 ["chmod"; "0o755"; "/test-command"];
1752 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1753 InitBasicFS, Always, TestOutputList (
1754 [["upload"; "test-command"; "/test-command"];
1755 ["chmod"; "0o755"; "/test-command"];
1756 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1757 InitBasicFS, Always, TestOutputList (
1758 [["upload"; "test-command"; "/test-command"];
1759 ["chmod"; "0o755"; "/test-command"];
1760 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1761 InitBasicFS, Always, TestOutputList (
1762 [["upload"; "test-command"; "/test-command"];
1763 ["chmod"; "0o755"; "/test-command"];
1764 ["command_lines"; "/test-command 7"]], []);
1765 InitBasicFS, Always, TestOutputList (
1766 [["upload"; "test-command"; "/test-command"];
1767 ["chmod"; "0o755"; "/test-command"];
1768 ["command_lines"; "/test-command 8"]], [""]);
1769 InitBasicFS, Always, TestOutputList (
1770 [["upload"; "test-command"; "/test-command"];
1771 ["chmod"; "0o755"; "/test-command"];
1772 ["command_lines"; "/test-command 9"]], ["";""]);
1773 InitBasicFS, Always, TestOutputList (
1774 [["upload"; "test-command"; "/test-command"];
1775 ["chmod"; "0o755"; "/test-command"];
1776 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1777 InitBasicFS, Always, TestOutputList (
1778 [["upload"; "test-command"; "/test-command"];
1779 ["chmod"; "0o755"; "/test-command"];
1780 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1781 "run a command, returning lines",
1783 This is the same as C<guestfs_command>, but splits the
1784 result into a list of lines.
1786 See also: C<guestfs_sh_lines>");
1788 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1789 [InitISOFS, Always, TestOutputStruct (
1790 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1791 "get file information",
1793 Returns file information for the given C<path>.
1795 This is the same as the C<stat(2)> system call.");
1797 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1798 [InitISOFS, Always, TestOutputStruct (
1799 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1800 "get file information for a symbolic link",
1802 Returns file information for the given C<path>.
1804 This is the same as C<guestfs_stat> except that if C<path>
1805 is a symbolic link, then the link is stat-ed, not the file it
1808 This is the same as the C<lstat(2)> system call.");
1810 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1811 [InitISOFS, Always, TestOutputStruct (
1812 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1813 "get file system statistics",
1815 Returns file system statistics for any mounted file system.
1816 C<path> should be a file or directory in the mounted file system
1817 (typically it is the mount point itself, but it doesn't need to be).
1819 This is the same as the C<statvfs(2)> system call.");
1821 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1823 "get ext2/ext3/ext4 superblock details",
1825 This returns the contents of the ext2, ext3 or ext4 filesystem
1826 superblock on C<device>.
1828 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1829 manpage for more details. The list of fields returned isn't
1830 clearly defined, and depends on both the version of C<tune2fs>
1831 that libguestfs was built against, and the filesystem itself.");
1833 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1834 [InitEmpty, Always, TestOutputTrue (
1835 [["blockdev_setro"; "/dev/sda"];
1836 ["blockdev_getro"; "/dev/sda"]])],
1837 "set block device to read-only",
1839 Sets the block device named C<device> to read-only.
1841 This uses the L<blockdev(8)> command.");
1843 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1844 [InitEmpty, Always, TestOutputFalse (
1845 [["blockdev_setrw"; "/dev/sda"];
1846 ["blockdev_getro"; "/dev/sda"]])],
1847 "set block device to read-write",
1849 Sets the block device named C<device> to read-write.
1851 This uses the L<blockdev(8)> command.");
1853 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1854 [InitEmpty, Always, TestOutputTrue (
1855 [["blockdev_setro"; "/dev/sda"];
1856 ["blockdev_getro"; "/dev/sda"]])],
1857 "is block device set to read-only",
1859 Returns a boolean indicating if the block device is read-only
1860 (true if read-only, false if not).
1862 This uses the L<blockdev(8)> command.");
1864 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1865 [InitEmpty, Always, TestOutputInt (
1866 [["blockdev_getss"; "/dev/sda"]], 512)],
1867 "get sectorsize of block device",
1869 This returns the size of sectors on a block device.
1870 Usually 512, but can be larger for modern devices.
1872 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 This uses the L<blockdev(8)> command.");
1877 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1878 [InitEmpty, Always, TestOutputInt (
1879 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1880 "get blocksize of block device",
1882 This returns the block size of a device.
1884 (Note this is different from both I<size in blocks> and
1885 I<filesystem block size>).
1887 This uses the L<blockdev(8)> command.");
1889 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1891 "set blocksize of block device",
1893 This sets the block size of a device.
1895 (Note this is different from both I<size in blocks> and
1896 I<filesystem block size>).
1898 This uses the L<blockdev(8)> command.");
1900 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1901 [InitEmpty, Always, TestOutputInt (
1902 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1903 "get total size of device in 512-byte sectors",
1905 This returns the size of the device in units of 512-byte sectors
1906 (even if the sectorsize isn't 512 bytes ... weird).
1908 See also C<guestfs_blockdev_getss> for the real sector size of
1909 the device, and C<guestfs_blockdev_getsize64> for the more
1910 useful I<size in bytes>.
1912 This uses the L<blockdev(8)> command.");
1914 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1915 [InitEmpty, Always, TestOutputInt (
1916 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1917 "get total size of device in bytes",
1919 This returns the size of the device in bytes.
1921 See also C<guestfs_blockdev_getsz>.
1923 This uses the L<blockdev(8)> command.");
1925 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1926 [InitEmpty, Always, TestRun
1927 [["blockdev_flushbufs"; "/dev/sda"]]],
1928 "flush device buffers",
1930 This tells the kernel to flush internal buffers associated
1933 This uses the L<blockdev(8)> command.");
1935 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1936 [InitEmpty, Always, TestRun
1937 [["blockdev_rereadpt"; "/dev/sda"]]],
1938 "reread partition table",
1940 Reread the partition table on C<device>.
1942 This uses the L<blockdev(8)> command.");
1944 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1945 [InitBasicFS, Always, TestOutput (
1946 (* Pick a file from cwd which isn't likely to change. *)
1947 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948 ["checksum"; "md5"; "/COPYING.LIB"]],
1949 Digest.to_hex (Digest.file "COPYING.LIB"))],
1950 "upload a file from the local machine",
1952 Upload local file C<filename> to C<remotefilename> on the
1955 C<filename> can also be a named pipe.
1957 See also C<guestfs_download>.");
1959 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1960 [InitBasicFS, Always, TestOutput (
1961 (* Pick a file from cwd which isn't likely to change. *)
1962 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1963 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1964 ["upload"; "testdownload.tmp"; "/upload"];
1965 ["checksum"; "md5"; "/upload"]],
1966 Digest.to_hex (Digest.file "COPYING.LIB"))],
1967 "download a file to the local machine",
1969 Download file C<remotefilename> and save it as C<filename>
1970 on the local machine.
1972 C<filename> can also be a named pipe.
1974 See also C<guestfs_upload>, C<guestfs_cat>.");
1976 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1977 [InitISOFS, Always, TestOutput (
1978 [["checksum"; "crc"; "/known-3"]], "2891671662");
1979 InitISOFS, Always, TestLastFail (
1980 [["checksum"; "crc"; "/notexists"]]);
1981 InitISOFS, Always, TestOutput (
1982 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1983 InitISOFS, Always, TestOutput (
1984 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1985 InitISOFS, Always, TestOutput (
1986 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1987 InitISOFS, Always, TestOutput (
1988 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1989 InitISOFS, Always, TestOutput (
1990 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1991 InitISOFS, Always, TestOutput (
1992 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1993 (* Test for RHBZ#579608, absolute symbolic links. *)
1994 InitISOFS, Always, TestOutput (
1995 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1996 "compute MD5, SHAx or CRC checksum of file",
1998 This call computes the MD5, SHAx or CRC checksum of the
2001 The type of checksum to compute is given by the C<csumtype>
2002 parameter which must have one of the following values:
2008 Compute the cyclic redundancy check (CRC) specified by POSIX
2009 for the C<cksum> command.
2013 Compute the MD5 hash (using the C<md5sum> program).
2017 Compute the SHA1 hash (using the C<sha1sum> program).
2021 Compute the SHA224 hash (using the C<sha224sum> program).
2025 Compute the SHA256 hash (using the C<sha256sum> program).
2029 Compute the SHA384 hash (using the C<sha384sum> program).
2033 Compute the SHA512 hash (using the C<sha512sum> program).
2037 The checksum is returned as a printable string.
2039 To get the checksum for a device, use C<guestfs_checksum_device>.
2041 To get the checksums for many files, use C<guestfs_checksums_out>.");
2043 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2044 [InitBasicFS, Always, TestOutput (
2045 [["tar_in"; "../images/helloworld.tar"; "/"];
2046 ["cat"; "/hello"]], "hello\n")],
2047 "unpack tarfile to directory",
2049 This command uploads and unpacks local file C<tarfile> (an
2050 I<uncompressed> tar file) into C<directory>.
2052 To upload a compressed tarball, use C<guestfs_tgz_in>
2053 or C<guestfs_txz_in>.");
2055 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2057 "pack directory into tarfile",
2059 This command packs the contents of C<directory> and downloads
2060 it to local file C<tarfile>.
2062 To download a compressed tarball, use C<guestfs_tgz_out>
2063 or C<guestfs_txz_out>.");
2065 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2066 [InitBasicFS, Always, TestOutput (
2067 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2068 ["cat"; "/hello"]], "hello\n")],
2069 "unpack compressed tarball to directory",
2071 This command uploads and unpacks local file C<tarball> (a
2072 I<gzip compressed> tar file) into C<directory>.
2074 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2076 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2078 "pack directory into compressed tarball",
2080 This command packs the contents of C<directory> and downloads
2081 it to local file C<tarball>.
2083 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2085 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2086 [InitBasicFS, Always, TestLastFail (
2088 ["mount_ro"; "/dev/sda1"; "/"];
2089 ["touch"; "/new"]]);
2090 InitBasicFS, Always, TestOutput (
2091 [["write_file"; "/new"; "data"; "0"];
2093 ["mount_ro"; "/dev/sda1"; "/"];
2094 ["cat"; "/new"]], "data")],
2095 "mount a guest disk, read-only",
2097 This is the same as the C<guestfs_mount> command, but it
2098 mounts the filesystem with the read-only (I<-o ro>) flag.");
2100 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2102 "mount a guest disk with mount options",
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set the mount options as for the
2106 L<mount(8)> I<-o> flag.
2108 If the C<options> parameter is an empty string, then
2109 no options are passed (all options default to whatever
2110 the filesystem uses).");
2112 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2114 "mount a guest disk with mount options and vfstype",
2116 This is the same as the C<guestfs_mount> command, but it
2117 allows you to set both the mount options and the vfstype
2118 as for the L<mount(8)> I<-o> and I<-t> flags.");
2120 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2122 "debugging and internals",
2124 The C<guestfs_debug> command exposes some internals of
2125 C<guestfsd> (the guestfs daemon) that runs inside the
2128 There is no comprehensive help for this command. You have
2129 to look at the file C<daemon/debug.c> in the libguestfs source
2130 to find out what you can do.");
2132 ("lvremove", (RErr, [Device "device"]), 77, [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"];
2139 ["lvremove"; "/dev/VG/LV1"];
2140 ["lvs"]], ["/dev/VG/LV2"]);
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"];
2147 ["lvremove"; "/dev/VG"];
2149 InitEmpty, Always, TestOutputList (
2150 [["part_disk"; "/dev/sda"; "mbr"];
2151 ["pvcreate"; "/dev/sda1"];
2152 ["vgcreate"; "VG"; "/dev/sda1"];
2153 ["lvcreate"; "LV1"; "VG"; "50"];
2154 ["lvcreate"; "LV2"; "VG"; "50"];
2155 ["lvremove"; "/dev/VG"];
2157 "remove an LVM logical volume",
2159 Remove an LVM logical volume C<device>, where C<device> is
2160 the path to the LV, such as C</dev/VG/LV>.
2162 You can also remove all LVs in a volume group by specifying
2163 the VG name, C</dev/VG>.");
2165 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2166 [InitEmpty, Always, TestOutputList (
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"];
2174 InitEmpty, Always, TestOutputList (
2175 [["part_disk"; "/dev/sda"; "mbr"];
2176 ["pvcreate"; "/dev/sda1"];
2177 ["vgcreate"; "VG"; "/dev/sda1"];
2178 ["lvcreate"; "LV1"; "VG"; "50"];
2179 ["lvcreate"; "LV2"; "VG"; "50"];
2182 "remove an LVM volume group",
2184 Remove an LVM volume group C<vgname>, (for example C<VG>).
2186 This also forcibly removes all logical volumes in the volume
2189 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2190 [InitEmpty, Always, TestOutputListOfDevices (
2191 [["part_disk"; "/dev/sda"; "mbr"];
2192 ["pvcreate"; "/dev/sda1"];
2193 ["vgcreate"; "VG"; "/dev/sda1"];
2194 ["lvcreate"; "LV1"; "VG"; "50"];
2195 ["lvcreate"; "LV2"; "VG"; "50"];
2197 ["pvremove"; "/dev/sda1"];
2199 InitEmpty, Always, TestOutputListOfDevices (
2200 [["part_disk"; "/dev/sda"; "mbr"];
2201 ["pvcreate"; "/dev/sda1"];
2202 ["vgcreate"; "VG"; "/dev/sda1"];
2203 ["lvcreate"; "LV1"; "VG"; "50"];
2204 ["lvcreate"; "LV2"; "VG"; "50"];
2206 ["pvremove"; "/dev/sda1"];
2208 InitEmpty, Always, TestOutputListOfDevices (
2209 [["part_disk"; "/dev/sda"; "mbr"];
2210 ["pvcreate"; "/dev/sda1"];
2211 ["vgcreate"; "VG"; "/dev/sda1"];
2212 ["lvcreate"; "LV1"; "VG"; "50"];
2213 ["lvcreate"; "LV2"; "VG"; "50"];
2215 ["pvremove"; "/dev/sda1"];
2217 "remove an LVM physical volume",
2219 This wipes a physical volume C<device> so that LVM will no longer
2222 The implementation uses the C<pvremove> command which refuses to
2223 wipe physical volumes that contain any volume groups, so you have
2224 to remove those first.");
2226 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2227 [InitBasicFS, Always, TestOutput (
2228 [["set_e2label"; "/dev/sda1"; "testlabel"];
2229 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2230 "set the ext2/3/4 filesystem label",
2232 This sets the ext2/3/4 filesystem label of the filesystem on
2233 C<device> to C<label>. Filesystem labels are limited to
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2237 to return the existing label on a filesystem.");
2239 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2241 "get the ext2/3/4 filesystem label",
2243 This returns the ext2/3/4 filesystem label of the filesystem on
2246 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2247 (let uuid = uuidgen () in
2248 [InitBasicFS, Always, TestOutput (
2249 [["set_e2uuid"; "/dev/sda1"; uuid];
2250 ["get_e2uuid"; "/dev/sda1"]], uuid);
2251 InitBasicFS, Always, TestOutput (
2252 [["set_e2uuid"; "/dev/sda1"; "clear"];
2253 ["get_e2uuid"; "/dev/sda1"]], "");
2254 (* We can't predict what UUIDs will be, so just check the commands run. *)
2255 InitBasicFS, Always, TestRun (
2256 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2257 InitBasicFS, Always, TestRun (
2258 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2259 "set the ext2/3/4 filesystem UUID",
2261 This sets the ext2/3/4 filesystem UUID of the filesystem on
2262 C<device> to C<uuid>. The format of the UUID and alternatives
2263 such as C<clear>, C<random> and C<time> are described in the
2264 L<tune2fs(8)> manpage.
2266 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2267 to return the existing UUID of a filesystem.");
2269 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2271 "get the ext2/3/4 filesystem UUID",
2273 This returns the ext2/3/4 filesystem UUID of the filesystem on
2276 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2277 [InitBasicFS, Always, TestOutputInt (
2278 [["umount"; "/dev/sda1"];
2279 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2280 InitBasicFS, Always, TestOutputInt (
2281 [["umount"; "/dev/sda1"];
2282 ["zero"; "/dev/sda1"];
2283 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2284 "run the filesystem checker",
2286 This runs the filesystem checker (fsck) on C<device> which
2287 should have filesystem type C<fstype>.
2289 The returned integer is the status. See L<fsck(8)> for the
2290 list of status codes from C<fsck>.
2298 Multiple status codes can be summed together.
2302 A non-zero return code can mean \"success\", for example if
2303 errors have been corrected on the filesystem.
2307 Checking or repairing NTFS volumes is not supported
2312 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2314 ("zero", (RErr, [Device "device"]), 85, [],
2315 [InitBasicFS, Always, TestOutput (
2316 [["umount"; "/dev/sda1"];
2317 ["zero"; "/dev/sda1"];
2318 ["file"; "/dev/sda1"]], "data")],
2319 "write zeroes to the device",
2321 This command writes zeroes over the first few blocks of C<device>.
2323 How many blocks are zeroed isn't specified (but it's I<not> enough
2324 to securely wipe the device). It should be sufficient to remove
2325 any partition tables, filesystem superblocks and so on.
2327 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2329 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2330 (* Test disabled because grub-install incompatible with virtio-blk driver.
2331 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2333 [InitBasicFS, Disabled, TestOutputTrue (
2334 [["grub_install"; "/"; "/dev/sda1"];
2335 ["is_dir"; "/boot"]])],
2338 This command installs GRUB (the Grand Unified Bootloader) on
2339 C<device>, with the root directory being C<root>.");
2341 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2342 [InitBasicFS, Always, TestOutput (
2343 [["write_file"; "/old"; "file content"; "0"];
2344 ["cp"; "/old"; "/new"];
2345 ["cat"; "/new"]], "file content");
2346 InitBasicFS, Always, TestOutputTrue (
2347 [["write_file"; "/old"; "file content"; "0"];
2348 ["cp"; "/old"; "/new"];
2349 ["is_file"; "/old"]]);
2350 InitBasicFS, Always, TestOutput (
2351 [["write_file"; "/old"; "file content"; "0"];
2353 ["cp"; "/old"; "/dir/new"];
2354 ["cat"; "/dir/new"]], "file content")],
2357 This copies a file from C<src> to C<dest> where C<dest> is
2358 either a destination filename or destination directory.");
2360 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2361 [InitBasicFS, Always, TestOutput (
2362 [["mkdir"; "/olddir"];
2363 ["mkdir"; "/newdir"];
2364 ["write_file"; "/olddir/file"; "file content"; "0"];
2365 ["cp_a"; "/olddir"; "/newdir"];
2366 ["cat"; "/newdir/olddir/file"]], "file content")],
2367 "copy a file or directory recursively",
2369 This copies a file or directory from C<src> to C<dest>
2370 recursively using the C<cp -a> command.");
2372 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2373 [InitBasicFS, Always, TestOutput (
2374 [["write_file"; "/old"; "file content"; "0"];
2375 ["mv"; "/old"; "/new"];
2376 ["cat"; "/new"]], "file content");
2377 InitBasicFS, Always, TestOutputFalse (
2378 [["write_file"; "/old"; "file content"; "0"];
2379 ["mv"; "/old"; "/new"];
2380 ["is_file"; "/old"]])],
2383 This moves a file from C<src> to C<dest> where C<dest> is
2384 either a destination filename or destination directory.");
2386 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2387 [InitEmpty, Always, TestRun (
2388 [["drop_caches"; "3"]])],
2389 "drop kernel page cache, dentries and inodes",
2391 This instructs the guest kernel to drop its page cache,
2392 and/or dentries and inode caches. The parameter C<whattodrop>
2393 tells the kernel what precisely to drop, see
2394 L<http://linux-mm.org/Drop_Caches>
2396 Setting C<whattodrop> to 3 should drop everything.
2398 This automatically calls L<sync(2)> before the operation,
2399 so that the maximum guest memory is freed.");
2401 ("dmesg", (RString "kmsgs", []), 91, [],
2402 [InitEmpty, Always, TestRun (
2404 "return kernel messages",
2406 This returns the kernel messages (C<dmesg> output) from
2407 the guest kernel. This is sometimes useful for extended
2408 debugging of problems.
2410 Another way to get the same information is to enable
2411 verbose messages with C<guestfs_set_verbose> or by setting
2412 the environment variable C<LIBGUESTFS_DEBUG=1> before
2413 running the program.");
2415 ("ping_daemon", (RErr, []), 92, [],
2416 [InitEmpty, Always, TestRun (
2417 [["ping_daemon"]])],
2418 "ping the guest daemon",
2420 This is a test probe into the guestfs daemon running inside
2421 the qemu subprocess. Calling this function checks that the
2422 daemon responds to the ping message, without affecting the daemon
2423 or attached block device(s) in any other way.");
2425 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2426 [InitBasicFS, Always, TestOutputTrue (
2427 [["write_file"; "/file1"; "contents of a file"; "0"];
2428 ["cp"; "/file1"; "/file2"];
2429 ["equal"; "/file1"; "/file2"]]);
2430 InitBasicFS, Always, TestOutputFalse (
2431 [["write_file"; "/file1"; "contents of a file"; "0"];
2432 ["write_file"; "/file2"; "contents of another file"; "0"];
2433 ["equal"; "/file1"; "/file2"]]);
2434 InitBasicFS, Always, TestLastFail (
2435 [["equal"; "/file1"; "/file2"]])],
2436 "test if two files have equal contents",
2438 This compares the two files C<file1> and C<file2> and returns
2439 true if their content is exactly equal, or false otherwise.
2441 The external L<cmp(1)> program is used for the comparison.");
2443 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2444 [InitISOFS, Always, TestOutputList (
2445 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2446 InitISOFS, Always, TestOutputList (
2447 [["strings"; "/empty"]], []);
2448 (* Test for RHBZ#579608, absolute symbolic links. *)
2449 InitISOFS, Always, TestRun (
2450 [["strings"; "/abssymlink"]])],
2451 "print the printable strings in a file",
2453 This runs the L<strings(1)> command on a file and returns
2454 the list of printable strings found.");
2456 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2457 [InitISOFS, Always, TestOutputList (
2458 [["strings_e"; "b"; "/known-5"]], []);
2459 InitBasicFS, Disabled, TestOutputList (
2460 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2461 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2462 "print the printable strings in a file",
2464 This is like the C<guestfs_strings> command, but allows you to
2465 specify the encoding of strings that are looked for in
2466 the source file C<path>.
2468 Allowed encodings are:
2474 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2475 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2479 Single 8-bit-byte characters.
2483 16-bit big endian strings such as those encoded in
2484 UTF-16BE or UCS-2BE.
2486 =item l (lower case letter L)
2488 16-bit little endian such as UTF-16LE and UCS-2LE.
2489 This is useful for examining binaries in Windows guests.
2493 32-bit big endian such as UCS-4BE.
2497 32-bit little endian such as UCS-4LE.
2501 The returned strings are transcoded to UTF-8.");
2503 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2504 [InitISOFS, Always, TestOutput (
2505 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2506 (* Test for RHBZ#501888c2 regression which caused large hexdump
2507 * commands to segfault.
2509 InitISOFS, Always, TestRun (
2510 [["hexdump"; "/100krandom"]]);
2511 (* Test for RHBZ#579608, absolute symbolic links. *)
2512 InitISOFS, Always, TestRun (
2513 [["hexdump"; "/abssymlink"]])],
2514 "dump a file in hexadecimal",
2516 This runs C<hexdump -C> on the given C<path>. The result is
2517 the human-readable, canonical hex dump of the file.");
2519 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2520 [InitNone, Always, TestOutput (
2521 [["part_disk"; "/dev/sda"; "mbr"];
2522 ["mkfs"; "ext3"; "/dev/sda1"];
2523 ["mount_options"; ""; "/dev/sda1"; "/"];
2524 ["write_file"; "/new"; "test file"; "0"];
2525 ["umount"; "/dev/sda1"];
2526 ["zerofree"; "/dev/sda1"];
2527 ["mount_options"; ""; "/dev/sda1"; "/"];
2528 ["cat"; "/new"]], "test file")],
2529 "zero unused inodes and disk blocks on ext2/3 filesystem",
2531 This runs the I<zerofree> program on C<device>. This program
2532 claims to zero unused inodes and disk blocks on an ext2/3
2533 filesystem, thus making it possible to compress the filesystem
2536 You should B<not> run this program if the filesystem is
2539 It is possible that using this program can damage the filesystem
2540 or data on the filesystem.");
2542 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2544 "resize an LVM physical volume",
2546 This resizes (expands or shrinks) an existing LVM physical
2547 volume to match the new size of the underlying device.");
2549 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2550 Int "cyls"; Int "heads"; Int "sectors";
2551 String "line"]), 99, [DangerWillRobinson],
2553 "modify a single partition on a block device",
2555 This runs L<sfdisk(8)> option to modify just the single
2556 partition C<n> (note: C<n> counts from 1).
2558 For other parameters, see C<guestfs_sfdisk>. You should usually
2559 pass C<0> for the cyls/heads/sectors parameters.
2561 See also: C<guestfs_part_add>");
2563 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2565 "display the partition table",
2567 This displays the partition table on C<device>, in the
2568 human-readable output of the L<sfdisk(8)> command. It is
2569 not intended to be parsed.
2571 See also: C<guestfs_part_list>");
2573 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2575 "display the kernel geometry",
2577 This displays the kernel's idea of the geometry of C<device>.
2579 The result is in human-readable format, and not designed to
2582 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2584 "display the disk geometry from the partition table",
2586 This displays the disk geometry of C<device> read from the
2587 partition table. Especially in the case where the underlying
2588 block device has been resized, this can be different from the
2589 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2591 The result is in human-readable format, and not designed to
2594 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2596 "activate or deactivate all volume groups",
2598 This command activates or (if C<activate> is false) deactivates
2599 all logical volumes in all volume groups.
2600 If activated, then they are made known to the
2601 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2602 then those devices disappear.
2604 This command is the same as running C<vgchange -a y|n>");
2606 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2608 "activate or deactivate some volume groups",
2610 This command activates or (if C<activate> is false) deactivates
2611 all logical volumes in the listed volume groups C<volgroups>.
2612 If activated, then they are made known to the
2613 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2614 then those devices disappear.
2616 This command is the same as running C<vgchange -a y|n volgroups...>
2618 Note that if C<volgroups> is an empty list then B<all> volume groups
2619 are activated or deactivated.");
2621 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2622 [InitNone, Always, TestOutput (
2623 [["part_disk"; "/dev/sda"; "mbr"];
2624 ["pvcreate"; "/dev/sda1"];
2625 ["vgcreate"; "VG"; "/dev/sda1"];
2626 ["lvcreate"; "LV"; "VG"; "10"];
2627 ["mkfs"; "ext2"; "/dev/VG/LV"];
2628 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2629 ["write_file"; "/new"; "test content"; "0"];
2631 ["lvresize"; "/dev/VG/LV"; "20"];
2632 ["e2fsck_f"; "/dev/VG/LV"];
2633 ["resize2fs"; "/dev/VG/LV"];
2634 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2635 ["cat"; "/new"]], "test content");
2636 InitNone, Always, TestRun (
2637 (* Make an LV smaller to test RHBZ#587484. *)
2638 [["part_disk"; "/dev/sda"; "mbr"];
2639 ["pvcreate"; "/dev/sda1"];
2640 ["vgcreate"; "VG"; "/dev/sda1"];
2641 ["lvcreate"; "LV"; "VG"; "20"];
2642 ["lvresize"; "/dev/VG/LV"; "10"]])],
2643 "resize an LVM logical volume",
2645 This resizes (expands or shrinks) an existing LVM logical
2646 volume to C<mbytes>. When reducing, data in the reduced part
2649 ("resize2fs", (RErr, [Device "device"]), 106, [],
2650 [], (* lvresize tests this *)
2651 "resize an ext2/ext3 filesystem",
2653 This resizes an ext2 or ext3 filesystem to match the size of
2654 the underlying device.
2656 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2657 on the C<device> before calling this command. For unknown reasons
2658 C<resize2fs> sometimes gives an error about this and sometimes not.
2659 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2660 calling this function.");
2662 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2663 [InitBasicFS, Always, TestOutputList (
2664 [["find"; "/"]], ["lost+found"]);
2665 InitBasicFS, Always, TestOutputList (
2669 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2670 InitBasicFS, Always, TestOutputList (
2671 [["mkdir_p"; "/a/b/c"];
2672 ["touch"; "/a/b/c/d"];
2673 ["find"; "/a/b/"]], ["c"; "c/d"])],
2674 "find all files and directories",
2676 This command lists out all files and directories, recursively,
2677 starting at C<directory>. It is essentially equivalent to
2678 running the shell command C<find directory -print> but some
2679 post-processing happens on the output, described below.
2681 This returns a list of strings I<without any prefix>. Thus
2682 if the directory structure was:
2688 then the returned list from C<guestfs_find> C</tmp> would be
2696 If C<directory> is not a directory, then this command returns
2699 The returned list is sorted.
2701 See also C<guestfs_find0>.");
2703 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2704 [], (* lvresize tests this *)
2705 "check an ext2/ext3 filesystem",
2707 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2708 filesystem checker on C<device>, noninteractively (C<-p>),
2709 even if the filesystem appears to be clean (C<-f>).
2711 This command is only needed because of C<guestfs_resize2fs>
2712 (q.v.). Normally you should use C<guestfs_fsck>.");
2714 ("sleep", (RErr, [Int "secs"]), 109, [],
2715 [InitNone, Always, TestRun (
2717 "sleep for some seconds",
2719 Sleep for C<secs> seconds.");
2721 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2722 [InitNone, Always, TestOutputInt (
2723 [["part_disk"; "/dev/sda"; "mbr"];
2724 ["mkfs"; "ntfs"; "/dev/sda1"];
2725 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2726 InitNone, Always, TestOutputInt (
2727 [["part_disk"; "/dev/sda"; "mbr"];
2728 ["mkfs"; "ext2"; "/dev/sda1"];
2729 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2730 "probe NTFS volume",
2732 This command runs the L<ntfs-3g.probe(8)> command which probes
2733 an NTFS C<device> for mountability. (Not all NTFS volumes can
2734 be mounted read-write, and some cannot be mounted at all).
2736 C<rw> is a boolean flag. Set it to true if you want to test
2737 if the volume can be mounted read-write. Set it to false if
2738 you want to test if the volume can be mounted read-only.
2740 The return value is an integer which C<0> if the operation
2741 would succeed, or some non-zero value documented in the
2742 L<ntfs-3g.probe(8)> manual page.");
2744 ("sh", (RString "output", [String "command"]), 111, [],
2745 [], (* XXX needs tests *)
2746 "run a command via the shell",
2748 This call runs a command from the guest filesystem via the
2751 This is like C<guestfs_command>, but passes the command to:
2753 /bin/sh -c \"command\"
2755 Depending on the guest's shell, this usually results in
2756 wildcards being expanded, shell expressions being interpolated
2759 All the provisos about C<guestfs_command> apply to this call.");
2761 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2762 [], (* XXX needs tests *)
2763 "run a command via the shell returning lines",
2765 This is the same as C<guestfs_sh>, but splits the result
2766 into a list of lines.
2768 See also: C<guestfs_command_lines>");
2770 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2771 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2772 * code in stubs.c, since all valid glob patterns must start with "/".
2773 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2775 [InitBasicFS, Always, TestOutputList (
2776 [["mkdir_p"; "/a/b/c"];
2777 ["touch"; "/a/b/c/d"];
2778 ["touch"; "/a/b/c/e"];
2779 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2780 InitBasicFS, Always, TestOutputList (
2781 [["mkdir_p"; "/a/b/c"];
2782 ["touch"; "/a/b/c/d"];
2783 ["touch"; "/a/b/c/e"];
2784 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2785 InitBasicFS, Always, TestOutputList (
2786 [["mkdir_p"; "/a/b/c"];
2787 ["touch"; "/a/b/c/d"];
2788 ["touch"; "/a/b/c/e"];
2789 ["glob_expand"; "/a/*/x/*"]], [])],
2790 "expand a wildcard path",
2792 This command searches for all the pathnames matching
2793 C<pattern> according to the wildcard expansion rules
2796 If no paths match, then this returns an empty list
2797 (note: not an error).
2799 It is just a wrapper around the C L<glob(3)> function
2800 with flags C<GLOB_MARK|GLOB_BRACE>.
2801 See that manual page for more details.");
2803 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2804 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2805 [["scrub_device"; "/dev/sdc"]])],
2806 "scrub (securely wipe) a device",
2808 This command writes patterns over C<device> to make data retrieval
2811 It is an interface to the L<scrub(1)> program. See that
2812 manual page for more details.");
2814 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2815 [InitBasicFS, Always, TestRun (
2816 [["write_file"; "/file"; "content"; "0"];
2817 ["scrub_file"; "/file"]])],
2818 "scrub (securely wipe) a file",
2820 This command writes patterns over a file to make data retrieval
2823 The file is I<removed> after scrubbing.
2825 It is an interface to the L<scrub(1)> program. See that
2826 manual page for more details.");
2828 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2829 [], (* XXX needs testing *)
2830 "scrub (securely wipe) free space",
2832 This command creates the directory C<dir> and then fills it
2833 with files until the filesystem is full, and scrubs the files
2834 as for C<guestfs_scrub_file>, and deletes them.
2835 The intention is to scrub any free space on the partition
2838 It is an interface to the L<scrub(1)> program. See that
2839 manual page for more details.");
2841 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2842 [InitBasicFS, Always, TestRun (
2844 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2845 "create a temporary directory",
2847 This command creates a temporary directory. The
2848 C<template> parameter should be a full pathname for the
2849 temporary directory name with the final six characters being
2852 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2853 the second one being suitable for Windows filesystems.
2855 The name of the temporary directory that was created
2858 The temporary directory is created with mode 0700
2859 and is owned by root.
2861 The caller is responsible for deleting the temporary
2862 directory and its contents after use.
2864 See also: L<mkdtemp(3)>");
2866 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2867 [InitISOFS, Always, TestOutputInt (
2868 [["wc_l"; "/10klines"]], 10000);
2869 (* Test for RHBZ#579608, absolute symbolic links. *)
2870 InitISOFS, Always, TestOutputInt (
2871 [["wc_l"; "/abssymlink"]], 10000)],
2872 "count lines in a file",
2874 This command counts the lines in a file, using the
2875 C<wc -l> external command.");
2877 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2878 [InitISOFS, Always, TestOutputInt (
2879 [["wc_w"; "/10klines"]], 10000)],
2880 "count words in a file",
2882 This command counts the words in a file, using the
2883 C<wc -w> external command.");
2885 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2886 [InitISOFS, Always, TestOutputInt (
2887 [["wc_c"; "/100kallspaces"]], 102400)],
2888 "count characters in a file",
2890 This command counts the characters in a file, using the
2891 C<wc -c> external command.");
2893 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2894 [InitISOFS, Always, TestOutputList (
2895 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2896 (* Test for RHBZ#579608, absolute symbolic links. *)
2897 InitISOFS, Always, TestOutputList (
2898 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2899 "return first 10 lines of a file",
2901 This command returns up to the first 10 lines of a file as
2902 a list of strings.");
2904 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2905 [InitISOFS, Always, TestOutputList (
2906 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2907 InitISOFS, Always, TestOutputList (
2908 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2909 InitISOFS, Always, TestOutputList (
2910 [["head_n"; "0"; "/10klines"]], [])],
2911 "return first N lines of a file",
2913 If the parameter C<nrlines> is a positive number, this returns the first
2914 C<nrlines> lines of the file C<path>.
2916 If the parameter C<nrlines> is a negative number, this returns lines
2917 from the file C<path>, excluding the last C<nrlines> lines.
2919 If the parameter C<nrlines> is zero, this returns an empty list.");
2921 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2922 [InitISOFS, Always, TestOutputList (
2923 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2924 "return last 10 lines of a file",
2926 This command returns up to the last 10 lines of a file as
2927 a list of strings.");
2929 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2930 [InitISOFS, Always, TestOutputList (
2931 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2932 InitISOFS, Always, TestOutputList (
2933 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2934 InitISOFS, Always, TestOutputList (
2935 [["tail_n"; "0"; "/10klines"]], [])],
2936 "return last N lines of a file",
2938 If the parameter C<nrlines> is a positive number, this returns the last
2939 C<nrlines> lines of the file C<path>.
2941 If the parameter C<nrlines> is a negative number, this returns lines
2942 from the file C<path>, starting with the C<-nrlines>th line.
2944 If the parameter C<nrlines> is zero, this returns an empty list.");
2946 ("df", (RString "output", []), 125, [],
2947 [], (* XXX Tricky to test because it depends on the exact format
2948 * of the 'df' command and other imponderables.
2950 "report file system disk space usage",
2952 This command runs the C<df> command to report disk space used.
2954 This command is mostly useful for interactive sessions. It
2955 is I<not> intended that you try to parse the output string.
2956 Use C<statvfs> from programs.");
2958 ("df_h", (RString "output", []), 126, [],
2959 [], (* XXX Tricky to test because it depends on the exact format
2960 * of the 'df' command and other imponderables.
2962 "report file system disk space usage (human readable)",
2964 This command runs the C<df -h> command to report disk space used
2965 in human-readable format.
2967 This command is mostly useful for interactive sessions. It
2968 is I<not> intended that you try to parse the output string.
2969 Use C<statvfs> from programs.");
2971 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2972 [InitISOFS, Always, TestOutputInt (
2973 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2974 "estimate file space usage",
2976 This command runs the C<du -s> command to estimate file space
2979 C<path> can be a file or a directory. If C<path> is a directory
2980 then the estimate includes the contents of the directory and all
2981 subdirectories (recursively).
2983 The result is the estimated size in I<kilobytes>
2984 (ie. units of 1024 bytes).");
2986 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2987 [InitISOFS, Always, TestOutputList (
2988 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2989 "list files in an initrd",
2991 This command lists out files contained in an initrd.
2993 The files are listed without any initial C</> character. The
2994 files are listed in the order they appear (not necessarily
2995 alphabetical). Directory names are listed as separate items.
2997 Old Linux kernels (2.4 and earlier) used a compressed ext2
2998 filesystem as initrd. We I<only> support the newer initramfs
2999 format (compressed cpio files).");
3001 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3003 "mount a file using the loop device",
3005 This command lets you mount C<file> (a filesystem image
3006 in a file) on a mount point. It is entirely equivalent to
3007 the command C<mount -o loop file mountpoint>.");
3009 ("mkswap", (RErr, [Device "device"]), 130, [],
3010 [InitEmpty, Always, TestRun (
3011 [["part_disk"; "/dev/sda"; "mbr"];
3012 ["mkswap"; "/dev/sda1"]])],
3013 "create a swap partition",
3015 Create a swap partition on C<device>.");
3017 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3018 [InitEmpty, Always, TestRun (
3019 [["part_disk"; "/dev/sda"; "mbr"];
3020 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3021 "create a swap partition with a label",
3023 Create a swap partition on C<device> with label C<label>.
3025 Note that you cannot attach a swap label to a block device
3026 (eg. C</dev/sda>), just to a partition. This appears to be
3027 a limitation of the kernel or swap tools.");
3029 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3030 (let uuid = uuidgen () in
3031 [InitEmpty, Always, TestRun (
3032 [["part_disk"; "/dev/sda"; "mbr"];
3033 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3034 "create a swap partition with an explicit UUID",
3036 Create a swap partition on C<device> with UUID C<uuid>.");
3038 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3039 [InitBasicFS, Always, TestOutputStruct (
3040 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3041 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3042 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3043 InitBasicFS, Always, TestOutputStruct (
3044 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3045 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3046 "make block, character or FIFO devices",
3048 This call creates block or character special devices, or
3049 named pipes (FIFOs).
3051 The C<mode> parameter should be the mode, using the standard
3052 constants. C<devmajor> and C<devminor> are the
3053 device major and minor numbers, only used when creating block
3054 and character special devices.
3056 Note that, just like L<mknod(2)>, the mode must be bitwise
3057 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3058 just creates a regular file). These constants are
3059 available in the standard Linux header files, or you can use
3060 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3061 which are wrappers around this command which bitwise OR
3062 in the appropriate constant for you.
3064 The mode actually set is affected by the umask.");
3066 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3067 [InitBasicFS, Always, TestOutputStruct (
3068 [["mkfifo"; "0o777"; "/node"];
3069 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3070 "make FIFO (named pipe)",
3072 This call creates a FIFO (named pipe) called C<path> with
3073 mode C<mode>. It is just a convenient wrapper around
3076 The mode actually set is affected by the umask.");
3078 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3079 [InitBasicFS, Always, TestOutputStruct (
3080 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3081 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3082 "make block device node",
3084 This call creates a block device node called C<path> with
3085 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3086 It is just a convenient wrapper around C<guestfs_mknod>.
3088 The mode actually set is affected by the umask.");
3090 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3091 [InitBasicFS, Always, TestOutputStruct (
3092 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3093 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3094 "make char device node",
3096 This call creates a char device node called C<path> with
3097 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3098 It is just a convenient wrapper around C<guestfs_mknod>.
3100 The mode actually set is affected by the umask.");
3102 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3103 [InitEmpty, Always, TestOutputInt (
3104 [["umask"; "0o22"]], 0o22)],
3105 "set file mode creation mask (umask)",
3107 This function sets the mask used for creating new files and
3108 device nodes to C<mask & 0777>.
3110 Typical umask values would be C<022> which creates new files
3111 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3112 C<002> which creates new files with permissions like
3113 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3115 The default umask is C<022>. This is important because it
3116 means that directories and device nodes will be created with
3117 C<0644> or C<0755> mode even if you specify C<0777>.
3119 See also C<guestfs_get_umask>,
3120 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3122 This call returns the previous umask.");
3124 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3126 "read directories entries",
3128 This returns the list of directory entries in directory C<dir>.
3130 All entries in the directory are returned, including C<.> and
3131 C<..>. The entries are I<not> sorted, but returned in the same
3132 order as the underlying filesystem.
3134 Also this call returns basic file type information about each
3135 file. The C<ftyp> field will contain one of the following characters:
3173 The L<readdir(3)> returned a C<d_type> field with an
3178 This function is primarily intended for use by programs. To
3179 get a simple list of names, use C<guestfs_ls>. To get a printable
3180 directory for human consumption, use C<guestfs_ll>.");
3182 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3184 "create partitions on a block device",
3186 This is a simplified interface to the C<guestfs_sfdisk>
3187 command, where partition sizes are specified in megabytes
3188 only (rounded to the nearest cylinder) and you don't need
3189 to specify the cyls, heads and sectors parameters which
3190 were rarely if ever used anyway.
3192 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3193 and C<guestfs_part_disk>");
3195 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3197 "determine file type inside a compressed file",
3199 This command runs C<file> after first decompressing C<path>
3202 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3204 Since 1.0.63, use C<guestfs_file> instead which can now
3205 process compressed files.");
3207 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3209 "list extended attributes of a file or directory",
3211 This call lists the extended attributes of the file or directory
3214 At the system call level, this is a combination of the
3215 L<listxattr(2)> and L<getxattr(2)> calls.
3217 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3219 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3221 "list extended attributes of a file or directory",
3223 This is the same as C<guestfs_getxattrs>, but if C<path>
3224 is a symbolic link, then it returns the extended attributes
3225 of the link itself.");
3227 ("setxattr", (RErr, [String "xattr";
3228 String "val"; Int "vallen"; (* will be BufferIn *)
3229 Pathname "path"]), 143, [Optional "linuxxattrs"],
3231 "set extended attribute of a file or directory",
3233 This call sets the extended attribute named C<xattr>
3234 of the file C<path> to the value C<val> (of length C<vallen>).
3235 The value is arbitrary 8 bit data.
3237 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3239 ("lsetxattr", (RErr, [String "xattr";
3240 String "val"; Int "vallen"; (* will be BufferIn *)
3241 Pathname "path"]), 144, [Optional "linuxxattrs"],
3243 "set extended attribute of a file or directory",
3245 This is the same as C<guestfs_setxattr>, but if C<path>
3246 is a symbolic link, then it sets an extended attribute
3247 of the link itself.");
3249 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3251 "remove extended attribute of a file or directory",
3253 This call removes the extended attribute named C<xattr>
3254 of the file C<path>.
3256 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3258 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3260 "remove extended attribute of a file or directory",
3262 This is the same as C<guestfs_removexattr>, but if C<path>
3263 is a symbolic link, then it removes an extended attribute
3264 of the link itself.");
3266 ("mountpoints", (RHashtable "mps", []), 147, [],
3270 This call is similar to C<guestfs_mounts>. That call returns
3271 a list of devices. This one returns a hash table (map) of
3272 device name to directory where the device is mounted.");
3274 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3275 (* This is a special case: while you would expect a parameter
3276 * of type "Pathname", that doesn't work, because it implies
3277 * NEED_ROOT in the generated calling code in stubs.c, and
3278 * this function cannot use NEED_ROOT.
3281 "create a mountpoint",
3283 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3284 specialized calls that can be used to create extra mountpoints
3285 before mounting the first filesystem.
3287 These calls are I<only> necessary in some very limited circumstances,
3288 mainly the case where you want to mount a mix of unrelated and/or
3289 read-only filesystems together.
3291 For example, live CDs often contain a \"Russian doll\" nest of
3292 filesystems, an ISO outer layer, with a squashfs image inside, with
3293 an ext2/3 image inside that. You can unpack this as follows
3296 add-ro Fedora-11-i686-Live.iso
3299 mkmountpoint /squash
3302 mount-loop /cd/LiveOS/squashfs.img /squash
3303 mount-loop /squash/LiveOS/ext3fs.img /ext3
3305 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3307 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3309 "remove a mountpoint",
3311 This calls removes a mountpoint that was previously created
3312 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3313 for full details.");
3315 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3316 [InitISOFS, Always, TestOutputBuffer (
3317 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3318 (* Test various near large, large and too large files (RHBZ#589039). *)
3319 InitBasicFS, Always, TestLastFail (
3321 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3322 ["read_file"; "/a"]]);
3323 InitBasicFS, Always, TestLastFail (
3325 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3326 ["read_file"; "/a"]]);
3327 InitBasicFS, Always, TestLastFail (
3329 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3330 ["read_file"; "/a"]])],
3333 This calls returns the contents of the file C<path> as a
3336 Unlike C<guestfs_cat>, this function can correctly
3337 handle files that contain embedded ASCII NUL characters.
3338 However unlike C<guestfs_download>, this function is limited
3339 in the total size of file that can be handled.");
3341 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3342 [InitISOFS, Always, TestOutputList (
3343 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3344 InitISOFS, Always, TestOutputList (
3345 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3346 (* Test for RHBZ#579608, absolute symbolic links. *)
3347 InitISOFS, Always, TestOutputList (
3348 [["grep"; "nomatch"; "/abssymlink"]], [])],
3349 "return lines matching a pattern",
3351 This calls the external C<grep> program and returns the
3354 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3355 [InitISOFS, Always, TestOutputList (
3356 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3357 "return lines matching a pattern",
3359 This calls the external C<egrep> program and returns the
3362 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3363 [InitISOFS, Always, TestOutputList (
3364 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3365 "return lines matching a pattern",
3367 This calls the external C<fgrep> program and returns the
3370 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3371 [InitISOFS, Always, TestOutputList (
3372 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3373 "return lines matching a pattern",
3375 This calls the external C<grep -i> program and returns the
3378 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3379 [InitISOFS, Always, TestOutputList (
3380 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3381 "return lines matching a pattern",
3383 This calls the external C<egrep -i> program and returns the
3386 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3387 [InitISOFS, Always, TestOutputList (
3388 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3389 "return lines matching a pattern",
3391 This calls the external C<fgrep -i> program and returns the
3394 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3395 [InitISOFS, Always, TestOutputList (
3396 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3397 "return lines matching a pattern",
3399 This calls the external C<zgrep> program and returns the
3402 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3403 [InitISOFS, Always, TestOutputList (
3404 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3405 "return lines matching a pattern",
3407 This calls the external C<zegrep> program and returns the
3410 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3411 [InitISOFS, Always, TestOutputList (
3412 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3413 "return lines matching a pattern",
3415 This calls the external C<zfgrep> program and returns the
3418 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3419 [InitISOFS, Always, TestOutputList (
3420 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3421 "return lines matching a pattern",
3423 This calls the external C<zgrep -i> program and returns the
3426 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3427 [InitISOFS, Always, TestOutputList (
3428 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3429 "return lines matching a pattern",
3431 This calls the external C<zegrep -i> program and returns the
3434 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3435 [InitISOFS, Always, TestOutputList (
3436 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3437 "return lines matching a pattern",
3439 This calls the external C<zfgrep -i> program and returns the
3442 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3443 [InitISOFS, Always, TestOutput (
3444 [["realpath"; "/../directory"]], "/directory")],
3445 "canonicalized absolute pathname",
3447 Return the canonicalized absolute pathname of C<path>. The
3448 returned path has no C<.>, C<..> or symbolic link path elements.");
3450 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3451 [InitBasicFS, Always, TestOutputStruct (
3454 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3455 "create a hard link",
3457 This command creates a hard link using the C<ln> command.");
3459 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3460 [InitBasicFS, Always, TestOutputStruct (
3463 ["ln_f"; "/a"; "/b"];
3464 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3465 "create a hard link",
3467 This command creates a hard link using the C<ln -f> command.
3468 The C<-f> option removes the link (C<linkname>) if it exists already.");
3470 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3471 [InitBasicFS, Always, TestOutputStruct (
3473 ["ln_s"; "a"; "/b"];
3474 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3475 "create a symbolic link",
3477 This command creates a symbolic link using the C<ln -s> command.");
3479 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3480 [InitBasicFS, Always, TestOutput (
3481 [["mkdir_p"; "/a/b"];
3482 ["touch"; "/a/b/c"];
3483 ["ln_sf"; "../d"; "/a/b/c"];
3484 ["readlink"; "/a/b/c"]], "../d")],
3485 "create a symbolic link",
3487 This command creates a symbolic link using the C<ln -sf> command,
3488 The C<-f> option removes the link (C<linkname>) if it exists already.");
3490 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3491 [] (* XXX tested above *),
3492 "read the target of a symbolic link",
3494 This command reads the target of a symbolic link.");
3496 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3497 [InitBasicFS, Always, TestOutputStruct (
3498 [["fallocate"; "/a"; "1000000"];
3499 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3500 "preallocate a file in the guest filesystem",
3502 This command preallocates a file (containing zero bytes) named
3503 C<path> of size C<len> bytes. If the file exists already, it
3506 Do not confuse this with the guestfish-specific
3507 C<alloc> command which allocates a file in the host and
3508 attaches it as a device.");
3510 ("swapon_device", (RErr, [Device "device"]), 170, [],
3511 [InitPartition, Always, TestRun (
3512 [["mkswap"; "/dev/sda1"];
3513 ["swapon_device"; "/dev/sda1"];
3514 ["swapoff_device"; "/dev/sda1"]])],
3515 "enable swap on device",
3517 This command enables the libguestfs appliance to use the
3518 swap device or partition named C<device>. The increased
3519 memory is made available for all commands, for example
3520 those run using C<guestfs_command> or C<guestfs_sh>.
3522 Note that you should not swap to existing guest swap
3523 partitions unless you know what you are doing. They may
3524 contain hibernation information, or other information that
3525 the guest doesn't want you to trash. You also risk leaking
3526 information about the host to the guest this way. Instead,
3527 attach a new host device to the guest and swap on that.");
3529 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3530 [], (* XXX tested by swapon_device *)
3531 "disable swap on device",
3533 This command disables the libguestfs appliance swap
3534 device or partition named C<device>.
3535 See C<guestfs_swapon_device>.");
3537 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3538 [InitBasicFS, Always, TestRun (
3539 [["fallocate"; "/swap"; "8388608"];
3540 ["mkswap_file"; "/swap"];
3541 ["swapon_file"; "/swap"];
3542 ["swapoff_file"; "/swap"]])],
3543 "enable swap on file",
3545 This command enables swap to a file.
3546 See C<guestfs_swapon_device> for other notes.");
3548 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3549 [], (* XXX tested by swapon_file *)
3550 "disable swap on file",
3552 This command disables the libguestfs appliance swap on file.");
3554 ("swapon_label", (RErr, [String "label"]), 174, [],
3555 [InitEmpty, Always, TestRun (
3556 [["part_disk"; "/dev/sdb"; "mbr"];
3557 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3558 ["swapon_label"; "swapit"];
3559 ["swapoff_label"; "swapit"];
3560 ["zero"; "/dev/sdb"];
3561 ["blockdev_rereadpt"; "/dev/sdb"]])],
3562 "enable swap on labeled swap partition",
3564 This command enables swap to a labeled swap partition.
3565 See C<guestfs_swapon_device> for other notes.");
3567 ("swapoff_label", (RErr, [String "label"]), 175, [],
3568 [], (* XXX tested by swapon_label *)
3569 "disable swap on labeled swap partition",
3571 This command disables the libguestfs appliance swap on
3572 labeled swap partition.");
3574 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3575 (let uuid = uuidgen () in
3576 [InitEmpty, Always, TestRun (
3577 [["mkswap_U"; uuid; "/dev/sdb"];
3578 ["swapon_uuid"; uuid];
3579 ["swapoff_uuid"; uuid]])]),
3580 "enable swap on swap partition by UUID",
3582 This command enables swap to a swap partition with the given UUID.
3583 See C<guestfs_swapon_device> for other notes.");
3585 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3586 [], (* XXX tested by swapon_uuid *)
3587 "disable swap on swap partition by UUID",
3589 This command disables the libguestfs appliance swap partition
3590 with the given UUID.");
3592 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3593 [InitBasicFS, Always, TestRun (
3594 [["fallocate"; "/swap"; "8388608"];
3595 ["mkswap_file"; "/swap"]])],
3596 "create a swap file",
3600 This command just writes a swap file signature to an existing
3601 file. To create the file itself, use something like C<guestfs_fallocate>.");
3603 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3604 [InitISOFS, Always, TestRun (
3605 [["inotify_init"; "0"]])],
3606 "create an inotify handle",
3608 This command creates a new inotify handle.
3609 The inotify subsystem can be used to notify events which happen to
3610 objects in the guest filesystem.
3612 C<maxevents> is the maximum number of events which will be
3613 queued up between calls to C<guestfs_inotify_read> or
3614 C<guestfs_inotify_files>.
3615 If this is passed as C<0>, then the kernel (or previously set)
3616 default is used. For Linux 2.6.29 the default was 16384 events.
3617 Beyond this limit, the kernel throws away events, but records
3618 the fact that it threw them away by setting a flag
3619 C<IN_Q_OVERFLOW> in the returned structure list (see
3620 C<guestfs_inotify_read>).
3622 Before any events are generated, you have to add some
3623 watches to the internal watch list. See:
3624 C<guestfs_inotify_add_watch>,
3625 C<guestfs_inotify_rm_watch> and
3626 C<guestfs_inotify_watch_all>.
3628 Queued up events should be read periodically by calling
3629 C<guestfs_inotify_read>
3630 (or C<guestfs_inotify_files> which is just a helpful
3631 wrapper around C<guestfs_inotify_read>). If you don't
3632 read the events out often enough then you risk the internal
3635 The handle should be closed after use by calling
3636 C<guestfs_inotify_close>. This also removes any
3637 watches automatically.
3639 See also L<inotify(7)> for an overview of the inotify interface
3640 as exposed by the Linux kernel, which is roughly what we expose
3641 via libguestfs. Note that there is one global inotify handle
3642 per libguestfs instance.");
3644 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3645 [InitBasicFS, Always, TestOutputList (
3646 [["inotify_init"; "0"];
3647 ["inotify_add_watch"; "/"; "1073741823"];
3650 ["inotify_files"]], ["a"; "b"])],
3651 "add an inotify watch",
3653 Watch C<path> for the events listed in C<mask>.
3655 Note that if C<path> is a directory then events within that
3656 directory are watched, but this does I<not> happen recursively
3657 (in subdirectories).
3659 Note for non-C or non-Linux callers: the inotify events are
3660 defined by the Linux kernel ABI and are listed in
3661 C</usr/include/sys/inotify.h>.");
3663 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3665 "remove an inotify watch",
3667 Remove a previously defined inotify watch.
3668 See C<guestfs_inotify_add_watch>.");
3670 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3672 "return list of inotify events",
3674 Return the complete queue of events that have happened
3675 since the previous read call.
3677 If no events have happened, this returns an empty list.
3679 I<Note>: In order to make sure that all events have been
3680 read, you must call this function repeatedly until it
3681 returns an empty list. The reason is that the call will
3682 read events up to the maximum appliance-to-host message
3683 size and leave remaining events in the queue.");
3685 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3687 "return list of watched files that had events",
3689 This function is a helpful wrapper around C<guestfs_inotify_read>
3690 which just returns a list of pathnames of objects that were
3691 touched. The returned pathnames are sorted and deduplicated.");
3693 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3695 "close the inotify handle",
3697 This closes the inotify handle which was previously
3698 opened by inotify_init. It removes all watches, throws
3699 away any pending events, and deallocates all resources.");
3701 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3703 "set SELinux security context",
3705 This sets the SELinux security context of the daemon
3706 to the string C<context>.
3708 See the documentation about SELINUX in L<guestfs(3)>.");
3710 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3712 "get SELinux security context",
3714 This gets the SELinux security context of the daemon.
3716 See the documentation about SELINUX in L<guestfs(3)>,
3717 and C<guestfs_setcon>");
3719 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3720 [InitEmpty, Always, TestOutput (
3721 [["part_disk"; "/dev/sda"; "mbr"];
3722 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3723 ["mount_options"; ""; "/dev/sda1"; "/"];
3724 ["write_file"; "/new"; "new file contents"; "0"];
3725 ["cat"; "/new"]], "new file contents")],
3726 "make a filesystem with block size",
3728 This call is similar to C<guestfs_mkfs>, but it allows you to
3729 control the block size of the resulting filesystem. Supported
3730 block sizes depend on the filesystem type, but typically they
3731 are C<1024>, C<2048> or C<4096> only.");
3733 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3734 [InitEmpty, Always, TestOutput (
3735 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3736 ["mke2journal"; "4096"; "/dev/sda1"];
3737 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3738 ["mount_options"; ""; "/dev/sda2"; "/"];
3739 ["write_file"; "/new"; "new file contents"; "0"];
3740 ["cat"; "/new"]], "new file contents")],
3741 "make ext2/3/4 external journal",
3743 This creates an ext2 external journal on C<device>. It is equivalent
3746 mke2fs -O journal_dev -b blocksize device");
3748 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3749 [InitEmpty, Always, TestOutput (
3750 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3751 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3752 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3753 ["mount_options"; ""; "/dev/sda2"; "/"];
3754 ["write_file"; "/new"; "new file contents"; "0"];
3755 ["cat"; "/new"]], "new file contents")],
3756 "make ext2/3/4 external journal with label",
3758 This creates an ext2 external journal on C<device> with label C<label>.");
3760 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3761 (let uuid = uuidgen () in
3762 [InitEmpty, Always, TestOutput (
3763 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3764 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3765 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3766 ["mount_options"; ""; "/dev/sda2"; "/"];
3767 ["write_file"; "/new"; "new file contents"; "0"];
3768 ["cat"; "/new"]], "new file contents")]),
3769 "make ext2/3/4 external journal with UUID",
3771 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3773 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3775 "make ext2/3/4 filesystem with external journal",
3777 This creates an ext2/3/4 filesystem on C<device> with
3778 an external journal on C<journal>. It is equivalent
3781 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3783 See also C<guestfs_mke2journal>.");
3785 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3787 "make ext2/3/4 filesystem with external journal",
3789 This creates an ext2/3/4 filesystem on C<device> with
3790 an external journal on the journal labeled C<label>.
3792 See also C<guestfs_mke2journal_L>.");
3794 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3796 "make ext2/3/4 filesystem with external journal",
3798 This creates an ext2/3/4 filesystem on C<device> with
3799 an external journal on the journal with UUID C<uuid>.
3801 See also C<guestfs_mke2journal_U>.");
3803 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3804 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3805 "load a kernel module",
3807 This loads a kernel module in the appliance.
3809 The kernel module must have been whitelisted when libguestfs
3810 was built (see C<appliance/kmod.whitelist.in> in the source).");
3812 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3813 [InitNone, Always, TestOutput (
3814 [["echo_daemon"; "This is a test"]], "This is a test"
3816 "echo arguments back to the client",
3818 This command concatenate the list of C<words> passed with single spaces between
3819 them and returns the resulting string.
3821 You can use this command to test the connection through to the daemon.
3823 See also C<guestfs_ping_daemon>.");
3825 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3826 [], (* There is a regression test for this. *)
3827 "find all files and directories, returning NUL-separated list",
3829 This command lists out all files and directories, recursively,
3830 starting at C<directory>, placing the resulting list in the
3831 external file called C<files>.
3833 This command works the same way as C<guestfs_find> with the
3834 following exceptions:
3840 The resulting list is written to an external file.
3844 Items (filenames) in the result are separated
3845 by C<\\0> characters. See L<find(1)> option I<-print0>.
3849 This command is not limited in the number of names that it
3854 The result list is not sorted.
3858 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3859 [InitISOFS, Always, TestOutput (
3860 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3861 InitISOFS, Always, TestOutput (
3862 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3863 InitISOFS, Always, TestOutput (
3864 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3865 InitISOFS, Always, TestLastFail (
3866 [["case_sensitive_path"; "/Known-1/"]]);
3867 InitBasicFS, Always, TestOutput (
3869 ["mkdir"; "/a/bbb"];
3870 ["touch"; "/a/bbb/c"];
3871 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3872 InitBasicFS, Always, TestOutput (
3874 ["mkdir"; "/a/bbb"];
3875 ["touch"; "/a/bbb/c"];
3876 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3877 InitBasicFS, Always, TestLastFail (
3879 ["mkdir"; "/a/bbb"];
3880 ["touch"; "/a/bbb/c"];
3881 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3882 "return true path on case-insensitive filesystem",
3884 This can be used to resolve case insensitive paths on
3885 a filesystem which is case sensitive. The use case is
3886 to resolve paths which you have read from Windows configuration
3887 files or the Windows Registry, to the true path.
3889 The command handles a peculiarity of the Linux ntfs-3g
3890 filesystem driver (and probably others), which is that although
3891 the underlying filesystem is case-insensitive, the driver
3892 exports the filesystem to Linux as case-sensitive.
3894 One consequence of this is that special directories such
3895 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3896 (or other things) depending on the precise details of how
3897 they were created. In Windows itself this would not be
3900 Bug or feature? You decide:
3901 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3903 This function resolves the true case of each element in the
3904 path and returns the case-sensitive path.
3906 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3907 might return C<\"/WINDOWS/system32\"> (the exact return value
3908 would depend on details of how the directories were originally
3909 created under Windows).
3912 This function does not handle drive names, backslashes etc.
3914 See also C<guestfs_realpath>.");
3916 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3917 [InitBasicFS, Always, TestOutput (
3918 [["vfs_type"; "/dev/sda1"]], "ext2")],
3919 "get the Linux VFS type corresponding to a mounted device",
3921 This command gets the block device type corresponding to
3922 a mounted device called C<device>.
3924 Usually the result is the name of the Linux VFS module that
3925 is used to mount this device (probably determined automatically
3926 if you used the C<guestfs_mount> call).");
3928 ("truncate", (RErr, [Pathname "path"]), 199, [],
3929 [InitBasicFS, Always, TestOutputStruct (
3930 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3931 ["truncate"; "/test"];
3932 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3933 "truncate a file to zero size",
3935 This command truncates C<path> to a zero-length file. The
3936 file must exist already.");
3938 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3939 [InitBasicFS, Always, TestOutputStruct (
3940 [["touch"; "/test"];
3941 ["truncate_size"; "/test"; "1000"];
3942 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3943 "truncate a file to a particular size",
3945 This command truncates C<path> to size C<size> bytes. The file
3946 must exist already. If the file is smaller than C<size> then
3947 the file is extended to the required size with null bytes.");
3949 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3950 [InitBasicFS, Always, TestOutputStruct (
3951 [["touch"; "/test"];
3952 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3953 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3954 "set timestamp of a file with nanosecond precision",
3956 This command sets the timestamps of a file with nanosecond
3959 C<atsecs, atnsecs> are the last access time (atime) in secs and
3960 nanoseconds from the epoch.
3962 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3963 secs and nanoseconds from the epoch.
3965 If the C<*nsecs> field contains the special value C<-1> then
3966 the corresponding timestamp is set to the current time. (The
3967 C<*secs> field is ignored in this case).
3969 If the C<*nsecs> field contains the special value C<-2> then
3970 the corresponding timestamp is left unchanged. (The
3971 C<*secs> field is ignored in this case).");
3973 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3974 [InitBasicFS, Always, TestOutputStruct (
3975 [["mkdir_mode"; "/test"; "0o111"];
3976 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3977 "create a directory with a particular mode",
3979 This command creates a directory, setting the initial permissions
3980 of the directory to C<mode>.
3982 For common Linux filesystems, the actual mode which is set will
3983 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3984 interpret the mode in other ways.
3986 See also C<guestfs_mkdir>, C<guestfs_umask>");
3988 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3990 "change file owner and group",
3992 Change the file owner to C<owner> and group to C<group>.
3993 This is like C<guestfs_chown> but if C<path> is a symlink then
3994 the link itself is changed, not the target.
3996 Only numeric uid and gid are supported. If you want to use
3997 names, you will need to locate and parse the password file
3998 yourself (Augeas support makes this relatively easy).");
4000 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4002 "lstat on multiple files",
4004 This call allows you to perform the C<guestfs_lstat> operation
4005 on multiple files, where all files are in the directory C<path>.
4006 C<names> is the list of files from this directory.
4008 On return you get a list of stat structs, with a one-to-one
4009 correspondence to the C<names> list. If any name did not exist
4010 or could not be lstat'd, then the C<ino> field of that structure
4013 This call is intended for programs that want to efficiently
4014 list a directory contents without making many round-trips.
4015 See also C<guestfs_lxattrlist> for a similarly efficient call
4016 for getting extended attributes. Very long directory listings
4017 might cause the protocol message size to be exceeded, causing
4018 this call to fail. The caller must split up such requests
4019 into smaller groups of names.");
4021 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4023 "lgetxattr on multiple files",
4025 This call allows you to get the extended attributes
4026 of multiple files, where all files are in the directory C<path>.
4027 C<names> is the list of files from this directory.
4029 On return you get a flat list of xattr structs which must be
4030 interpreted sequentially. The first xattr struct always has a zero-length
4031 C<attrname>. C<attrval> in this struct is zero-length
4032 to indicate there was an error doing C<lgetxattr> for this
4033 file, I<or> is a C string which is a decimal number
4034 (the number of following attributes for this file, which could
4035 be C<\"0\">). Then after the first xattr struct are the
4036 zero or more attributes for the first named file.
4037 This repeats for the second and subsequent files.
4039 This call is intended for programs that want to efficiently
4040 list a directory contents without making many round-trips.
4041 See also C<guestfs_lstatlist> for a similarly efficient call
4042 for getting standard stats. Very long directory listings
4043 might cause the protocol message size to be exceeded, causing
4044 this call to fail. The caller must split up such requests
4045 into smaller groups of names.");
4047 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4049 "readlink on multiple files",
4051 This call allows you to do a C<readlink> operation
4052 on multiple files, where all files are in the directory C<path>.
4053 C<names> is the list of files from this directory.
4055 On return you get a list of strings, with a one-to-one
4056 correspondence to the C<names> list. Each string is the
4057 value of the symbol link.
4059 If the C<readlink(2)> operation fails on any name, then
4060 the corresponding result string is the empty string C<\"\">.
4061 However the whole operation is completed even if there
4062 were C<readlink(2)> errors, and so you can call this
4063 function with names where you don't know if they are
4064 symbolic links already (albeit slightly less efficient).
4066 This call is intended for programs that want to efficiently
4067 list a directory contents without making many round-trips.
4068 Very long directory listings might cause the protocol
4069 message size to be exceeded, causing
4070 this call to fail. The caller must split up such requests
4071 into smaller groups of names.");
4073 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4074 [InitISOFS, Always, TestOutputBuffer (
4075 [["pread"; "/known-4"; "1"; "3"]], "\n");
4076 InitISOFS, Always, TestOutputBuffer (
4077 [["pread"; "/empty"; "0"; "100"]], "")],
4078 "read part of a file",
4080 This command lets you read part of a file. It reads C<count>
4081 bytes of the file, starting at C<offset>, from file C<path>.
4083 This may read fewer bytes than requested. For further details
4084 see the L<pread(2)> system call.");
4086 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4087 [InitEmpty, Always, TestRun (
4088 [["part_init"; "/dev/sda"; "gpt"]])],
4089 "create an empty partition table",
4091 This creates an empty partition table on C<device> of one of the
4092 partition types listed below. Usually C<parttype> should be
4093 either C<msdos> or C<gpt> (for large disks).
4095 Initially there are no partitions. Following this, you should
4096 call C<guestfs_part_add> for each partition required.
4098 Possible values for C<parttype> are:
4102 =item B<efi> | B<gpt>
4104 Intel EFI / GPT partition table.
4106 This is recommended for >= 2 TB partitions that will be accessed
4107 from Linux and Intel-based Mac OS X. It also has limited backwards
4108 compatibility with the C<mbr> format.
4110 =item B<mbr> | B<msdos>
4112 The standard PC \"Master Boot Record\" (MBR) format used
4113 by MS-DOS and Windows. This partition type will B<only> work
4114 for device sizes up to 2 TB. For large disks we recommend
4119 Other partition table types that may work but are not
4128 =item B<amiga> | B<rdb>
4130 Amiga \"Rigid Disk Block\" format.
4138 DASD, used on IBM mainframes.
4146 Old Mac partition format. Modern Macs use C<gpt>.
4150 NEC PC-98 format, common in Japan apparently.
4158 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4159 [InitEmpty, Always, TestRun (
4160 [["part_init"; "/dev/sda"; "mbr"];
4161 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4162 InitEmpty, Always, TestRun (
4163 [["part_init"; "/dev/sda"; "gpt"];
4164 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4165 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4166 InitEmpty, Always, TestRun (
4167 [["part_init"; "/dev/sda"; "mbr"];
4168 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4169 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4170 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4171 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4172 "add a partition to the device",
4174 This command adds a partition to C<device>. If there is no partition
4175 table on the device, call C<guestfs_part_init> first.
4177 The C<prlogex> parameter is the type of partition. Normally you
4178 should pass C<p> or C<primary> here, but MBR partition tables also
4179 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4182 C<startsect> and C<endsect> are the start and end of the partition
4183 in I<sectors>. C<endsect> may be negative, which means it counts
4184 backwards from the end of the disk (C<-1> is the last sector).
4186 Creating a partition which covers the whole disk is not so easy.
4187 Use C<guestfs_part_disk> to do that.");
4189 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4190 [InitEmpty, Always, TestRun (
4191 [["part_disk"; "/dev/sda"; "mbr"]]);
4192 InitEmpty, Always, TestRun (
4193 [["part_disk"; "/dev/sda"; "gpt"]])],
4194 "partition whole disk with a single primary partition",
4196 This command is simply a combination of C<guestfs_part_init>
4197 followed by C<guestfs_part_add> to create a single primary partition
4198 covering the whole disk.
4200 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4201 but other possible values are described in C<guestfs_part_init>.");
4203 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4204 [InitEmpty, Always, TestRun (
4205 [["part_disk"; "/dev/sda"; "mbr"];
4206 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4207 "make a partition bootable",
4209 This sets the bootable flag on partition numbered C<partnum> on
4210 device C<device>. Note that partitions are numbered from 1.
4212 The bootable flag is used by some operating systems (notably
4213 Windows) to determine which partition to boot from. It is by
4214 no means universally recognized.");
4216 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4217 [InitEmpty, Always, TestRun (
4218 [["part_disk"; "/dev/sda"; "gpt"];
4219 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4220 "set partition name",
4222 This sets the partition name on partition numbered C<partnum> on
4223 device C<device>. Note that partitions are numbered from 1.
4225 The partition name can only be set on certain types of partition
4226 table. This works on C<gpt> but not on C<mbr> partitions.");
4228 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4229 [], (* XXX Add a regression test for this. *)
4230 "list partitions on a device",
4232 This command parses the partition table on C<device> and
4233 returns the list of partitions found.
4235 The fields in the returned structure are:
4241 Partition number, counting from 1.
4245 Start of the partition I<in bytes>. To get sectors you have to
4246 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4250 End of the partition in bytes.
4254 Size of the partition in bytes.
4258 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4259 [InitEmpty, Always, TestOutput (
4260 [["part_disk"; "/dev/sda"; "gpt"];
4261 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4262 "get the partition table type",
4264 This command examines the partition table on C<device> and
4265 returns the partition table type (format) being used.
4267 Common return values include: C<msdos> (a DOS/Windows style MBR
4268 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4269 values are possible, although unusual. See C<guestfs_part_init>
4272 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4273 [InitBasicFS, Always, TestOutputBuffer (
4274 [["fill"; "0x63"; "10"; "/test"];
4275 ["read_file"; "/test"]], "cccccccccc")],
4276 "fill a file with octets",
4278 This command creates a new file called C<path>. The initial
4279 content of the file is C<len> octets of C<c>, where C<c>
4280 must be a number in the range C<[0..255]>.
4282 To fill a file with zero bytes (sparsely), it is
4283 much more efficient to use C<guestfs_truncate_size>.
4284 To create a file with a pattern of repeating bytes
4285 use C<guestfs_fill_pattern>.");
4287 ("available", (RErr, [StringList "groups"]), 216, [],
4288 [InitNone, Always, TestRun [["available"; ""]]],
4289 "test availability of some parts of the API",
4291 This command is used to check the availability of some
4292 groups of functionality in the appliance, which not all builds of
4293 the libguestfs appliance will be able to provide.
4295 The libguestfs groups, and the functions that those
4296 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4298 The argument C<groups> is a list of group names, eg:
4299 C<[\"inotify\", \"augeas\"]> would check for the availability of
4300 the Linux inotify functions and Augeas (configuration file
4303 The command returns no error if I<all> requested groups are available.
4305 It fails with an error if one or more of the requested
4306 groups is unavailable in the appliance.
4308 If an unknown group name is included in the
4309 list of groups then an error is always returned.
4317 You must call C<guestfs_launch> before calling this function.
4319 The reason is because we don't know what groups are
4320 supported by the appliance/daemon until it is running and can
4325 If a group of functions is available, this does not necessarily
4326 mean that they will work. You still have to check for errors
4327 when calling individual API functions even if they are
4332 It is usually the job of distro packagers to build
4333 complete functionality into the libguestfs appliance.
4334 Upstream libguestfs, if built from source with all
4335 requirements satisfied, will support everything.
4339 This call was added in version C<1.0.80>. In previous
4340 versions of libguestfs all you could do would be to speculatively
4341 execute a command to find out if the daemon implemented it.
4342 See also C<guestfs_version>.
4346 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4347 [InitBasicFS, Always, TestOutputBuffer (
4348 [["write_file"; "/src"; "hello, world"; "0"];
4349 ["dd"; "/src"; "/dest"];
4350 ["read_file"; "/dest"]], "hello, world")],
4351 "copy from source to destination using dd",
4353 This command copies from one source device or file C<src>
4354 to another destination device or file C<dest>. Normally you
4355 would use this to copy to or from a device or partition, for
4356 example to duplicate a filesystem.
4358 If the destination is a device, it must be as large or larger
4359 than the source file or device, otherwise the copy will fail.
4360 This command cannot do partial copies (see C<guestfs_copy_size>).");
4362 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4363 [InitBasicFS, Always, TestOutputInt (
4364 [["write_file"; "/file"; "hello, world"; "0"];
4365 ["filesize"; "/file"]], 12)],
4366 "return the size of the file in bytes",
4368 This command returns the size of C<file> in bytes.
4370 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4371 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4372 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4374 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4375 [InitBasicFSonLVM, Always, TestOutputList (
4376 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4377 ["lvs"]], ["/dev/VG/LV2"])],
4378 "rename an LVM logical volume",
4380 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4382 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4383 [InitBasicFSonLVM, Always, TestOutputList (
4385 ["vg_activate"; "false"; "VG"];
4386 ["vgrename"; "VG"; "VG2"];
4387 ["vg_activate"; "true"; "VG2"];
4388 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4389 ["vgs"]], ["VG2"])],
4390 "rename an LVM volume group",
4392 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4394 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4395 [InitISOFS, Always, TestOutputBuffer (
4396 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4397 "list the contents of a single file in an initrd",
4399 This command unpacks the file C<filename> from the initrd file
4400 called C<initrdpath>. The filename must be given I<without> the
4401 initial C</> character.
4403 For example, in guestfish you could use the following command
4404 to examine the boot script (usually called C</init>)
4405 contained in a Linux initrd or initramfs image:
4407 initrd-cat /boot/initrd-<version>.img init
4409 See also C<guestfs_initrd_list>.");
4411 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4413 "get the UUID of a physical volume",
4415 This command returns the UUID of the LVM PV C<device>.");
4417 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4419 "get the UUID of a volume group",
4421 This command returns the UUID of the LVM VG named C<vgname>.");
4423 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4425 "get the UUID of a logical volume",
4427 This command returns the UUID of the LVM LV C<device>.");
4429 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4431 "get the PV UUIDs containing the volume group",
4433 Given a VG called C<vgname>, this returns the UUIDs of all
4434 the physical volumes that this volume group resides on.
4436 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4437 calls to associate physical volumes and volume groups.
4439 See also C<guestfs_vglvuuids>.");
4441 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4443 "get the LV UUIDs of all LVs in the volume group",
4445 Given a VG called C<vgname>, this returns the UUIDs of all
4446 the logical volumes created in this volume group.
4448 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4449 calls to associate logical volumes and volume groups.
4451 See also C<guestfs_vgpvuuids>.");
4453 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4454 [InitBasicFS, Always, TestOutputBuffer (
4455 [["write_file"; "/src"; "hello, world"; "0"];
4456 ["copy_size"; "/src"; "/dest"; "5"];
4457 ["read_file"; "/dest"]], "hello")],
4458 "copy size bytes from source to destination using dd",
4460 This command copies exactly C<size> bytes from one source device
4461 or file C<src> to another destination device or file C<dest>.
4463 Note this will fail if the source is too short or if the destination
4464 is not large enough.");
4466 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4467 [InitBasicFSonLVM, Always, TestRun (
4468 [["zero_device"; "/dev/VG/LV"]])],
4469 "write zeroes to an entire device",
4471 This command writes zeroes over the entire C<device>. Compare
4472 with C<guestfs_zero> which just zeroes the first few blocks of
4475 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4476 [InitBasicFS, Always, TestOutput (
4477 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4478 ["cat"; "/hello"]], "hello\n")],
4479 "unpack compressed tarball to directory",
4481 This command uploads and unpacks local file C<tarball> (an
4482 I<xz compressed> tar file) into C<directory>.");
4484 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4486 "pack directory into compressed tarball",
4488 This command packs the contents of C<directory> and downloads
4489 it to local file C<tarball> (as an xz compressed tar archive).");
4491 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4493 "resize an NTFS filesystem",
4495 This command resizes an NTFS filesystem, expanding or
4496 shrinking it to the size of the underlying device.
4497 See also L<ntfsresize(8)>.");
4499 ("vgscan", (RErr, []), 232, [],
4500 [InitEmpty, Always, TestRun (
4502 "rescan for LVM physical volumes, volume groups and logical volumes",
4504 This rescans all block devices and rebuilds the list of LVM
4505 physical volumes, volume groups and logical volumes.");
4507 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4508 [InitEmpty, Always, TestRun (
4509 [["part_init"; "/dev/sda"; "mbr"];
4510 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4511 ["part_del"; "/dev/sda"; "1"]])],
4512 "delete a partition",
4514 This command deletes the partition numbered C<partnum> on C<device>.
4516 Note that in the case of MBR partitioning, deleting an
4517 extended partition also deletes any logical partitions
4520 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4521 [InitEmpty, Always, TestOutputTrue (
4522 [["part_init"; "/dev/sda"; "mbr"];
4523 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4524 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4525 ["part_get_bootable"; "/dev/sda"; "1"]])],
4526 "return true if a partition is bootable",
4528 This command returns true if the partition C<partnum> on
4529 C<device> has the bootable flag set.
4531 See also C<guestfs_part_set_bootable>.");
4533 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4534 [InitEmpty, Always, TestOutputInt (
4535 [["part_init"; "/dev/sda"; "mbr"];
4536 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4537 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4538 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4539 "get the MBR type byte (ID byte) from a partition",
4541 Returns the MBR type byte (also known as the ID byte) from
4542 the numbered partition C<partnum>.
4544 Note that only MBR (old DOS-style) partitions have type bytes.
4545 You will get undefined results for other partition table
4546 types (see C<guestfs_part_get_parttype>).");
4548 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4549 [], (* tested by part_get_mbr_id *)
4550 "set the MBR type byte (ID byte) of a partition",
4552 Sets the MBR type byte (also known as the ID byte) of
4553 the numbered partition C<partnum> to C<idbyte>. Note
4554 that the type bytes quoted in most documentation are
4555 in fact hexadecimal numbers, but usually documented
4556 without any leading \"0x\" which might be confusing.
4558 Note that only MBR (old DOS-style) partitions have type bytes.
4559 You will get undefined results for other partition table
4560 types (see C<guestfs_part_get_parttype>).");
4562 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4563 [InitISOFS, Always, TestOutput (
4564 [["checksum_device"; "md5"; "/dev/sdd"]],
4565 (Digest.to_hex (Digest.file "images/test.iso")))],
4566 "compute MD5, SHAx or CRC checksum of the contents of a device",
4568 This call computes the MD5, SHAx or CRC checksum of the
4569 contents of the device named C<device>. For the types of
4570 checksums supported see the C<guestfs_checksum> command.");
4572 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4573 [InitNone, Always, TestRun (
4574 [["part_disk"; "/dev/sda"; "mbr"];
4575 ["pvcreate"; "/dev/sda1"];
4576 ["vgcreate"; "VG"; "/dev/sda1"];
4577 ["lvcreate"; "LV"; "VG"; "10"];
4578 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4579 "expand an LV to fill free space",
4581 This expands an existing logical volume C<lv> so that it fills
4582 C<pc>% of the remaining free space in the volume group. Commonly
4583 you would call this with pc = 100 which expands the logical volume
4584 as much as possible, using all remaining free space in the volume
4587 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4588 [], (* XXX Augeas code needs tests. *)
4589 "clear Augeas path",
4591 Set the value associated with C<path> to C<NULL>. This
4592 is the same as the L<augtool(1)> C<clear> command.");
4594 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4595 [InitEmpty, Always, TestOutputInt (
4596 [["get_umask"]], 0o22)],
4597 "get the current umask",
4599 Return the current umask. By default the umask is C<022>
4600 unless it has been set by calling C<guestfs_umask>.");
4602 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4604 "upload a file to the appliance (internal use only)",
4606 The C<guestfs_debug_upload> command uploads a file to
4607 the libguestfs appliance.
4609 There is no comprehensive help for this command. You have
4610 to look at the file C<daemon/debug.c> in the libguestfs source
4611 to find out what it is for.");
4613 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4614 [InitBasicFS, Always, TestOutput (
4615 [["base64_in"; "../images/hello.b64"; "/hello"];
4616 ["cat"; "/hello"]], "hello\n")],
4617 "upload base64-encoded data to file",
4619 This command uploads base64-encoded data from C<base64file>
4622 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4624 "download file and encode as base64",
4626 This command downloads the contents of C<filename>, writing
4627 it out to local file C<base64file> encoded as base64.");
4629 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4631 "compute MD5, SHAx or CRC checksum of files in a directory",
4633 This command computes the checksums of all regular files in
4634 C<directory> and then emits a list of those checksums to
4635 the local output file C<sumsfile>.
4637 This can be used for verifying the integrity of a virtual
4638 machine. However to be properly secure you should pay
4639 attention to the output of the checksum command (it uses
4640 the ones from GNU coreutils). In particular when the
4641 filename is not printable, coreutils uses a special
4642 backslash syntax. For more information, see the GNU
4643 coreutils info file.");
4645 ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4646 [InitBasicFS, Always, TestOutputBuffer (
4647 [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4648 ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4649 "fill a file with a repeating pattern of bytes",
4651 This function is like C<guestfs_fill> except that it creates
4652 a new file of length C<len> containing the repeating pattern
4653 of bytes in C<pattern>. The pattern is truncated if necessary
4654 to ensure the length of the file is exactly C<len> bytes.");
4658 let all_functions = non_daemon_functions @ daemon_functions
4660 (* In some places we want the functions to be displayed sorted
4661 * alphabetically, so this is useful:
4663 let all_functions_sorted =
4664 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4665 compare n1 n2) all_functions
4667 (* This is used to generate the src/MAX_PROC_NR file which
4668 * contains the maximum procedure number, a surrogate for the
4669 * ABI version number. See src/Makefile.am for the details.
4672 let proc_nrs = List.map (
4673 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4674 ) daemon_functions in
4675 List.fold_left max 0 proc_nrs
4677 (* Field types for structures. *)
4679 | FChar (* C 'char' (really, a 7 bit byte). *)
4680 | FString (* nul-terminated ASCII string, NOT NULL. *)
4681 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4686 | FBytes (* Any int measure that counts bytes. *)
4687 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4688 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4690 (* Because we generate extra parsing code for LVM command line tools,
4691 * we have to pull out the LVM columns separately here.
4701 "pv_attr", FString (* XXX *);
4702 "pv_pe_count", FInt64;
4703 "pv_pe_alloc_count", FInt64;
4706 "pv_mda_count", FInt64;
4707 "pv_mda_free", FBytes;
4708 (* Not in Fedora 10:
4709 "pv_mda_size", FBytes;
4716 "vg_attr", FString (* XXX *);
4719 "vg_sysid", FString;
4720 "vg_extent_size", FBytes;
4721 "vg_extent_count", FInt64;
4722 "vg_free_count", FInt64;
4727 "snap_count", FInt64;
4730 "vg_mda_count", FInt64;
4731 "vg_mda_free", FBytes;
4732 (* Not in Fedora 10:
4733 "vg_mda_size", FBytes;
4739 "lv_attr", FString (* XXX *);
4742 "lv_kernel_major", FInt64;
4743 "lv_kernel_minor", FInt64;
4745 "seg_count", FInt64;
4747 "snap_percent", FOptPercent;
4748 "copy_percent", FOptPercent;
4751 "mirror_log", FString;
4755 (* Names and fields in all structures (in RStruct and RStructList)
4759 (* The old RIntBool return type, only ever used for aug_defnode. Do
4760 * not use this struct in any new code.
4763 "i", FInt32; (* for historical compatibility *)
4764 "b", FInt32; (* for historical compatibility *)
4767 (* LVM PVs, VGs, LVs. *)
4768 "lvm_pv", lvm_pv_cols;
4769 "lvm_vg", lvm_vg_cols;
4770 "lvm_lv", lvm_lv_cols;
4772 (* Column names and types from stat structures.
4773 * NB. Can't use things like 'st_atime' because glibc header files
4774 * define some of these as macros. Ugh.
4805 (* Column names in dirent structure. *)
4808 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4813 (* Version numbers. *)
4821 (* Extended attribute. *)
4823 "attrname", FString;
4827 (* Inotify events. *)
4831 "in_cookie", FUInt32;
4835 (* Partition table entry. *)
4838 "part_start", FBytes;
4840 "part_size", FBytes;
4842 ] (* end of structs *)
4844 (* Ugh, Java has to be different ..
4845 * These names are also used by the Haskell bindings.
4847 let java_structs = [
4848 "int_bool", "IntBool";
4853 "statvfs", "StatVFS";
4855 "version", "Version";
4857 "inotify_event", "INotifyEvent";
4858 "partition", "Partition";
4861 (* What structs are actually returned. *)
4862 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4864 (* Returns a list of RStruct/RStructList structs that are returned
4865 * by any function. Each element of returned list is a pair:
4867 * (structname, RStructOnly)
4868 * == there exists function which returns RStruct (_, structname)
4869 * (structname, RStructListOnly)
4870 * == there exists function which returns RStructList (_, structname)
4871 * (structname, RStructAndList)
4872 * == there are functions returning both RStruct (_, structname)
4873 * and RStructList (_, structname)
4875 let rstructs_used_by functions =
4876 (* ||| is a "logical OR" for rstructs_used_t *)
4880 | _, RStructAndList -> RStructAndList
4881 | RStructOnly, RStructListOnly
4882 | RStructListOnly, RStructOnly -> RStructAndList
4883 | RStructOnly, RStructOnly -> RStructOnly
4884 | RStructListOnly, RStructListOnly -> RStructListOnly
4887 let h = Hashtbl.create 13 in
4889 (* if elem->oldv exists, update entry using ||| operator,
4890 * else just add elem->newv to the hash
4892 let update elem newv =
4893 try let oldv = Hashtbl.find h elem in
4894 Hashtbl.replace h elem (newv ||| oldv)
4895 with Not_found -> Hashtbl.add h elem newv
4899 fun (_, style, _, _, _, _, _) ->
4900 match fst style with
4901 | RStruct (_, structname) -> update structname RStructOnly
4902 | RStructList (_, structname) -> update structname RStructListOnly
4906 (* return key->values as a list of (key,value) *)
4907 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4909 (* Used for testing language bindings. *)
4911 | CallString of string
4912 | CallOptString of string option
4913 | CallStringList of string list
4915 | CallInt64 of int64
4917 | CallBuffer of string
4919 (* Used to memoize the result of pod2text. *)
4920 let pod2text_memo_filename = "src/.pod2text.data"
4921 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4923 let chan = open_in pod2text_memo_filename in
4924 let v = input_value chan in
4928 _ -> Hashtbl.create 13
4929 let pod2text_memo_updated () =
4930 let chan = open_out pod2text_memo_filename in
4931 output_value chan pod2text_memo;
4934 (* Useful functions.
4935 * Note we don't want to use any external OCaml libraries which
4936 * makes this a bit harder than it should be.
4938 module StringMap = Map.Make (String)
4940 let failwithf fs = ksprintf failwith fs
4942 let unique = let i = ref 0 in fun () -> incr i; !i
4944 let replace_char s c1 c2 =
4945 let s2 = String.copy s in
4946 let r = ref false in
4947 for i = 0 to String.length s2 - 1 do
4948 if String.unsafe_get s2 i = c1 then (
4949 String.unsafe_set s2 i c2;
4953 if not !r then s else s2
4957 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4959 let triml ?(test = isspace) str =
4961 let n = ref (String.length str) in
4962 while !n > 0 && test str.[!i]; do
4967 else String.sub str !i !n
4969 let trimr ?(test = isspace) str =
4970 let n = ref (String.length str) in
4971 while !n > 0 && test str.[!n-1]; do
4974 if !n = String.length str then str
4975 else String.sub str 0 !n
4977 let trim ?(test = isspace) str =
4978 trimr ~test (triml ~test str)
4980 let rec find s sub =
4981 let len = String.length s in
4982 let sublen = String.length sub in
4984 if i <= len-sublen then (
4986 if j < sublen then (
4987 if s.[i+j] = sub.[j] then loop2 (j+1)
4993 if r = -1 then loop (i+1) else r
4999 let rec replace_str s s1 s2 =
5000 let len = String.length s in
5001 let sublen = String.length s1 in
5002 let i = find s s1 in
5005 let s' = String.sub s 0 i in
5006 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5007 s' ^ s2 ^ replace_str s'' s1 s2
5010 let rec string_split sep str =
5011 let len = String.length str in
5012 let seplen = String.length sep in
5013 let i = find str sep in
5014 if i = -1 then [str]
5016 let s' = String.sub str 0 i in
5017 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5018 s' :: string_split sep s''
5021 let files_equal n1 n2 =
5022 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5023 match Sys.command cmd with
5026 | i -> failwithf "%s: failed with error code %d" cmd i
5028 let rec filter_map f = function
5032 | Some y -> y :: filter_map f xs
5033 | None -> filter_map f xs
5035 let rec find_map f = function
5036 | [] -> raise Not_found
5040 | None -> find_map f xs
5043 let rec loop i = function
5045 | x :: xs -> f i x; loop (i+1) xs
5050 let rec loop i = function
5052 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5056 let count_chars c str =
5057 let count = ref 0 in
5058 for i = 0 to String.length str - 1 do
5059 if c = String.unsafe_get str i then incr count
5065 for i = 0 to String.length str - 1 do
5066 let c = String.unsafe_get str i in
5071 let map_chars f str =
5072 List.map f (explode str)
5074 let name_of_argt = function
5075 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5076 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5077 | FileIn n | FileOut n | BufferIn n -> n
5079 let java_name_of_struct typ =
5080 try List.assoc typ java_structs
5083 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5085 let cols_of_struct typ =
5086 try List.assoc typ structs
5088 failwithf "cols_of_struct: unknown struct %s" typ
5090 let seq_of_test = function
5091 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5092 | TestOutputListOfDevices (s, _)
5093 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5094 | TestOutputTrue s | TestOutputFalse s
5095 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5096 | TestOutputStruct (s, _)
5097 | TestLastFail s -> s
5099 (* Handling for function flags. *)
5100 let protocol_limit_warning =
5101 "Because of the message protocol, there is a transfer limit
5102 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5104 let danger_will_robinson =
5105 "B<This command is dangerous. Without careful use you
5106 can easily destroy all your data>."
5108 let deprecation_notice flags =
5111 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5113 sprintf "This function is deprecated.
5114 In new code, use the C<%s> call instead.
5116 Deprecated functions will not be removed from the API, but the
5117 fact that they are deprecated indicates that there are problems
5118 with correct use of these functions." alt in
5123 (* Create list of optional groups. *)
5125 let h = Hashtbl.create 13 in
5127 fun (name, _, _, flags, _, _, _) ->
5131 let names = try Hashtbl.find h group with Not_found -> [] in
5132 Hashtbl.replace h group (name :: names)
5136 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5139 fun group -> group, List.sort compare (Hashtbl.find h group)
5141 List.sort (fun x y -> compare (fst x) (fst y)) groups
5143 (* Check function names etc. for consistency. *)
5144 let check_functions () =
5145 let contains_uppercase str =
5146 let len = String.length str in
5148 if i >= len then false
5151 if c >= 'A' && c <= 'Z' then true
5158 (* Check function names. *)
5160 fun (name, _, _, _, _, _, _) ->
5161 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5162 failwithf "function name %s does not need 'guestfs' prefix" name;
5164 failwithf "function name is empty";
5165 if name.[0] < 'a' || name.[0] > 'z' then
5166 failwithf "function name %s must start with lowercase a-z" name;
5167 if String.contains name '-' then
5168 failwithf "function name %s should not contain '-', use '_' instead."
5172 (* Check function parameter/return names. *)
5174 fun (name, style, _, _, _, _, _) ->
5175 let check_arg_ret_name n =
5176 if contains_uppercase n then
5177 failwithf "%s param/ret %s should not contain uppercase chars"
5179 if String.contains n '-' || String.contains n '_' then
5180 failwithf "%s param/ret %s should not contain '-' or '_'"
5183 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;
5184 if n = "int" || n = "char" || n = "short" || n = "long" then
5185 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5186 if n = "i" || n = "n" then
5187 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5188 if n = "argv" || n = "args" then
5189 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5191 (* List Haskell, OCaml and C keywords here.
5192 * http://www.haskell.org/haskellwiki/Keywords
5193 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5194 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5195 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5196 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5197 * Omitting _-containing words, since they're handled above.
5198 * Omitting the OCaml reserved word, "val", is ok,
5199 * and saves us from renaming several parameters.
5202 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5203 "char"; "class"; "const"; "constraint"; "continue"; "data";
5204 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5205 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5206 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5207 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5208 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5210 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5211 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5212 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5213 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5214 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5215 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5216 "volatile"; "when"; "where"; "while";
5218 if List.mem n reserved then
5219 failwithf "%s has param/ret using reserved word %s" name n;
5222 (match fst style with
5224 | RInt n | RInt64 n | RBool n
5225 | RConstString n | RConstOptString n | RString n
5226 | RStringList n | RStruct (n, _) | RStructList (n, _)
5227 | RHashtable n | RBufferOut n ->
5228 check_arg_ret_name n
5230 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5233 (* Check short descriptions. *)
5235 fun (name, _, _, _, _, shortdesc, _) ->
5236 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5237 failwithf "short description of %s should begin with lowercase." name;
5238 let c = shortdesc.[String.length shortdesc-1] in
5239 if c = '\n' || c = '.' then
5240 failwithf "short description of %s should not end with . or \\n." name
5243 (* Check long descriptions. *)
5245 fun (name, _, _, _, _, _, longdesc) ->
5246 if longdesc.[String.length longdesc-1] = '\n' then
5247 failwithf "long description of %s should not end with \\n." name
5250 (* Check proc_nrs. *)
5252 fun (name, _, proc_nr, _, _, _, _) ->
5253 if proc_nr <= 0 then
5254 failwithf "daemon function %s should have proc_nr > 0" name
5258 fun (name, _, proc_nr, _, _, _, _) ->
5259 if proc_nr <> -1 then
5260 failwithf "non-daemon function %s should have proc_nr -1" name
5261 ) non_daemon_functions;
5264 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5267 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5268 let rec loop = function
5271 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5273 | (name1,nr1) :: (name2,nr2) :: _ ->
5274 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5282 (* Ignore functions that have no tests. We generate a
5283 * warning when the user does 'make check' instead.
5285 | name, _, _, _, [], _, _ -> ()
5286 | name, _, _, _, tests, _, _ ->
5290 match seq_of_test test with
5292 failwithf "%s has a test containing an empty sequence" name
5293 | cmds -> List.map List.hd cmds
5295 let funcs = List.flatten funcs in
5297 let tested = List.mem name funcs in
5300 failwithf "function %s has tests but does not test itself" name
5303 (* 'pr' prints to the current output file. *)
5304 let chan = ref Pervasives.stdout
5309 let i = count_chars '\n' str in
5310 lines := !lines + i;
5311 output_string !chan str
5314 let copyright_years =
5315 let this_year = 1900 + (localtime (time ())).tm_year in
5316 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5318 (* Generate a header block in a number of standard styles. *)
5319 type comment_style =
5320 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5321 type license = GPLv2plus | LGPLv2plus
5323 let generate_header ?(extra_inputs = []) comment license =
5324 let inputs = "src/generator.ml" :: extra_inputs in
5325 let c = match comment with
5326 | CStyle -> pr "/* "; " *"
5327 | CPlusPlusStyle -> pr "// "; "//"
5328 | HashStyle -> pr "# "; "#"
5329 | OCamlStyle -> pr "(* "; " *"
5330 | HaskellStyle -> pr "{- "; " " in
5331 pr "libguestfs generated file\n";
5332 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5333 List.iter (pr "%s %s\n" c) inputs;
5334 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5336 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5340 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5341 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5342 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5343 pr "%s (at your option) any later version.\n" c;
5345 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5346 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5347 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5348 pr "%s GNU General Public License for more details.\n" c;
5350 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5351 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5352 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5355 pr "%s This library is free software; you can redistribute it and/or\n" c;
5356 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5357 pr "%s License as published by the Free Software Foundation; either\n" c;
5358 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5360 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5361 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5362 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5363 pr "%s Lesser General Public License for more details.\n" c;
5365 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5366 pr "%s License along with this library; if not, write to the Free Software\n" c;
5367 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5370 | CStyle -> pr " */\n"
5373 | OCamlStyle -> pr " *)\n"
5374 | HaskellStyle -> pr "-}\n"
5378 (* Start of main code generation functions below this line. *)
5380 (* Generate the pod documentation for the C API. *)
5381 let rec generate_actions_pod () =
5383 fun (shortname, style, _, flags, _, _, longdesc) ->
5384 if not (List.mem NotInDocs flags) then (
5385 let name = "guestfs_" ^ shortname in
5386 pr "=head2 %s\n\n" name;
5388 generate_prototype ~extern:false ~handle:"g" name style;
5390 pr "%s\n\n" longdesc;
5391 (match fst style with
5393 pr "This function returns 0 on success or -1 on error.\n\n"
5395 pr "On error this function returns -1.\n\n"
5397 pr "On error this function returns -1.\n\n"
5399 pr "This function returns a C truth value on success or -1 on error.\n\n"
5401 pr "This function returns a string, or NULL on error.
5402 The string is owned by the guest handle and must I<not> be freed.\n\n"
5403 | RConstOptString _ ->
5404 pr "This function returns a string which may be NULL.
5405 There is way to return an error from this function.
5406 The string is owned by the guest handle and must I<not> be freed.\n\n"
5408 pr "This function returns a string, or NULL on error.
5409 I<The caller must free the returned string after use>.\n\n"
5411 pr "This function returns a NULL-terminated array of strings
5412 (like L<environ(3)>), or NULL if there was an error.
5413 I<The caller must free the strings and the array after use>.\n\n"
5414 | RStruct (_, typ) ->
5415 pr "This function returns a C<struct guestfs_%s *>,
5416 or NULL if there was an error.
5417 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5418 | RStructList (_, typ) ->
5419 pr "This function returns a C<struct guestfs_%s_list *>
5420 (see E<lt>guestfs-structs.hE<gt>),
5421 or NULL if there was an error.
5422 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5424 pr "This function returns a NULL-terminated array of
5425 strings, or NULL if there was an error.
5426 The array of strings will always have length C<2n+1>, where
5427 C<n> keys and values alternate, followed by the trailing NULL entry.
5428 I<The caller must free the strings and the array after use>.\n\n"
5430 pr "This function returns a buffer, or NULL on error.
5431 The size of the returned buffer is written to C<*size_r>.
5432 I<The caller must free the returned buffer after use>.\n\n"
5434 if List.mem ProtocolLimitWarning flags then
5435 pr "%s\n\n" protocol_limit_warning;
5436 if List.mem DangerWillRobinson flags then
5437 pr "%s\n\n" danger_will_robinson;
5438 match deprecation_notice flags with
5440 | Some txt -> pr "%s\n\n" txt
5442 ) all_functions_sorted
5444 and generate_structs_pod () =
5445 (* Structs documentation. *)
5448 pr "=head2 guestfs_%s\n" typ;
5450 pr " struct guestfs_%s {\n" typ;
5453 | name, FChar -> pr " char %s;\n" name
5454 | name, FUInt32 -> pr " uint32_t %s;\n" name
5455 | name, FInt32 -> pr " int32_t %s;\n" name
5456 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5457 | name, FInt64 -> pr " int64_t %s;\n" name
5458 | name, FString -> pr " char *%s;\n" name
5460 pr " /* The next two fields describe a byte array. */\n";
5461 pr " uint32_t %s_len;\n" name;
5462 pr " char *%s;\n" name
5464 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5465 pr " char %s[32];\n" name
5466 | name, FOptPercent ->
5467 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5468 pr " float %s;\n" name
5472 pr " struct guestfs_%s_list {\n" typ;
5473 pr " uint32_t len; /* Number of elements in list. */\n";
5474 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5477 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5478 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5483 and generate_availability_pod () =
5484 (* Availability documentation. *)
5488 fun (group, functions) ->
5489 pr "=item B<%s>\n" group;
5491 pr "The following functions:\n";
5492 List.iter (pr "L</guestfs_%s>\n") functions;
5498 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5499 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5501 * We have to use an underscore instead of a dash because otherwise
5502 * rpcgen generates incorrect code.
5504 * This header is NOT exported to clients, but see also generate_structs_h.
5506 and generate_xdr () =
5507 generate_header CStyle LGPLv2plus;
5509 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5510 pr "typedef string str<>;\n";
5513 (* Internal structures. *)
5517 pr "struct guestfs_int_%s {\n" typ;
5519 | name, FChar -> pr " char %s;\n" name
5520 | name, FString -> pr " string %s<>;\n" name
5521 | name, FBuffer -> pr " opaque %s<>;\n" name
5522 | name, FUUID -> pr " opaque %s[32];\n" name
5523 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5524 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5525 | name, FOptPercent -> pr " float %s;\n" name
5529 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5534 fun (shortname, style, _, _, _, _, _) ->
5535 let name = "guestfs_" ^ shortname in
5537 (match snd style with
5540 pr "struct %s_args {\n" name;
5543 | Pathname n | Device n | Dev_or_Path n | String n ->
5544 pr " string %s<>;\n" n
5545 | OptString n -> pr " str *%s;\n" n
5546 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5547 | Bool n -> pr " bool %s;\n" n
5548 | Int n -> pr " int %s;\n" n
5549 | Int64 n -> pr " hyper %s;\n" n
5551 pr " opaque %s<>;\n" n
5552 | FileIn _ | FileOut _ -> ()
5556 (match fst style with
5559 pr "struct %s_ret {\n" name;
5563 pr "struct %s_ret {\n" name;
5564 pr " hyper %s;\n" n;
5567 pr "struct %s_ret {\n" name;
5570 | RConstString _ | RConstOptString _ ->
5571 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5573 pr "struct %s_ret {\n" name;
5574 pr " string %s<>;\n" n;
5577 pr "struct %s_ret {\n" name;
5578 pr " str %s<>;\n" n;
5580 | RStruct (n, typ) ->
5581 pr "struct %s_ret {\n" name;
5582 pr " guestfs_int_%s %s;\n" typ n;
5584 | RStructList (n, typ) ->
5585 pr "struct %s_ret {\n" name;
5586 pr " guestfs_int_%s_list %s;\n" typ n;
5589 pr "struct %s_ret {\n" name;
5590 pr " str %s<>;\n" n;
5593 pr "struct %s_ret {\n" name;
5594 pr " opaque %s<>;\n" n;
5599 (* Table of procedure numbers. *)
5600 pr "enum guestfs_procedure {\n";
5602 fun (shortname, _, proc_nr, _, _, _, _) ->
5603 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5605 pr " GUESTFS_PROC_NR_PROCS\n";
5609 (* Having to choose a maximum message size is annoying for several
5610 * reasons (it limits what we can do in the API), but it (a) makes
5611 * the protocol a lot simpler, and (b) provides a bound on the size
5612 * of the daemon which operates in limited memory space.
5614 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5617 (* Message header, etc. *)
5619 /* The communication protocol is now documented in the guestfs(3)
5623 const GUESTFS_PROGRAM = 0x2000F5F5;
5624 const GUESTFS_PROTOCOL_VERSION = 1;
5626 /* These constants must be larger than any possible message length. */
5627 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5628 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5630 enum guestfs_message_direction {
5631 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5632 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5635 enum guestfs_message_status {
5636 GUESTFS_STATUS_OK = 0,
5637 GUESTFS_STATUS_ERROR = 1
5640 const GUESTFS_ERROR_LEN = 256;
5642 struct guestfs_message_error {
5643 string error_message<GUESTFS_ERROR_LEN>;
5646 struct guestfs_message_header {
5647 unsigned prog; /* GUESTFS_PROGRAM */
5648 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5649 guestfs_procedure proc; /* GUESTFS_PROC_x */
5650 guestfs_message_direction direction;
5651 unsigned serial; /* message serial number */
5652 guestfs_message_status status;
5655 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5657 struct guestfs_chunk {
5658 int cancel; /* if non-zero, transfer is cancelled */
5659 /* data size is 0 bytes if the transfer has finished successfully */
5660 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5664 (* Generate the guestfs-structs.h file. *)
5665 and generate_structs_h () =
5666 generate_header CStyle LGPLv2plus;
5668 (* This is a public exported header file containing various
5669 * structures. The structures are carefully written to have
5670 * exactly the same in-memory format as the XDR structures that
5671 * we use on the wire to the daemon. The reason for creating
5672 * copies of these structures here is just so we don't have to
5673 * export the whole of guestfs_protocol.h (which includes much
5674 * unrelated and XDR-dependent stuff that we don't want to be
5675 * public, or required by clients).
5677 * To reiterate, we will pass these structures to and from the
5678 * client with a simple assignment or memcpy, so the format
5679 * must be identical to what rpcgen / the RFC defines.
5682 (* Public structures. *)
5685 pr "struct guestfs_%s {\n" typ;
5688 | name, FChar -> pr " char %s;\n" name
5689 | name, FString -> pr " char *%s;\n" name
5691 pr " uint32_t %s_len;\n" name;
5692 pr " char *%s;\n" name
5693 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5694 | name, FUInt32 -> pr " uint32_t %s;\n" name
5695 | name, FInt32 -> pr " int32_t %s;\n" name
5696 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5697 | name, FInt64 -> pr " int64_t %s;\n" name
5698 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5702 pr "struct guestfs_%s_list {\n" typ;
5703 pr " uint32_t len;\n";
5704 pr " struct guestfs_%s *val;\n" typ;
5707 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5708 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5712 (* Generate the guestfs-actions.h file. *)
5713 and generate_actions_h () =
5714 generate_header CStyle LGPLv2plus;
5716 fun (shortname, style, _, _, _, _, _) ->
5717 let name = "guestfs_" ^ shortname in
5718 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5722 (* Generate the guestfs-internal-actions.h file. *)
5723 and generate_internal_actions_h () =
5724 generate_header CStyle LGPLv2plus;
5726 fun (shortname, style, _, _, _, _, _) ->
5727 let name = "guestfs__" ^ shortname in
5728 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5730 ) non_daemon_functions
5732 (* Generate the client-side dispatch stubs. *)
5733 and generate_client_actions () =
5734 generate_header CStyle LGPLv2plus;
5741 #include <inttypes.h>
5743 #include \"guestfs.h\"
5744 #include \"guestfs-internal.h\"
5745 #include \"guestfs-internal-actions.h\"
5746 #include \"guestfs_protocol.h\"
5748 #define error guestfs_error
5749 //#define perrorf guestfs_perrorf
5750 #define safe_malloc guestfs_safe_malloc
5751 #define safe_realloc guestfs_safe_realloc
5752 //#define safe_strdup guestfs_safe_strdup
5753 #define safe_memdup guestfs_safe_memdup
5755 /* Check the return message from a call for validity. */
5757 check_reply_header (guestfs_h *g,
5758 const struct guestfs_message_header *hdr,
5759 unsigned int proc_nr, unsigned int serial)
5761 if (hdr->prog != GUESTFS_PROGRAM) {
5762 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5765 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5766 error (g, \"wrong protocol version (%%d/%%d)\",
5767 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5770 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5771 error (g, \"unexpected message direction (%%d/%%d)\",
5772 hdr->direction, GUESTFS_DIRECTION_REPLY);
5775 if (hdr->proc != proc_nr) {
5776 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5779 if (hdr->serial != serial) {
5780 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5787 /* Check we are in the right state to run a high-level action. */
5789 check_state (guestfs_h *g, const char *caller)
5791 if (!guestfs__is_ready (g)) {
5792 if (guestfs__is_config (g) || guestfs__is_launching (g))
5793 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5796 error (g, \"%%s called from the wrong state, %%d != READY\",
5797 caller, guestfs__get_state (g));
5805 (* Generate code to generate guestfish call traces. *)
5806 let trace_call shortname style =
5807 pr " if (guestfs__get_trace (g)) {\n";
5810 List.exists (function
5811 | StringList _ | DeviceList _ -> true
5812 | _ -> false) (snd style) in
5818 pr " printf (\"%s\");\n" shortname;
5821 | String n (* strings *)
5828 (* guestfish doesn't support string escaping, so neither do we *)
5829 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5830 | OptString n -> (* string option *)
5831 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5832 pr " else printf (\" null\");\n"
5834 | DeviceList n -> (* string list *)
5835 pr " putchar (' ');\n";
5836 pr " putchar ('\"');\n";
5837 pr " for (i = 0; %s[i]; ++i) {\n" n;
5838 pr " if (i > 0) putchar (' ');\n";
5839 pr " fputs (%s[i], stdout);\n" n;
5841 pr " putchar ('\"');\n";
5842 | Bool n -> (* boolean *)
5843 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5844 | Int n -> (* int *)
5845 pr " printf (\" %%d\", %s);\n" n
5847 pr " printf (\" %%\" PRIi64, %s);\n" n
5849 pr " putchar ('\\n');\n";
5854 (* For non-daemon functions, generate a wrapper around each function. *)
5856 fun (shortname, style, _, _, _, _, _) ->
5857 let name = "guestfs_" ^ shortname in
5859 generate_prototype ~extern:false ~semicolon:false ~newline:true
5860 ~handle:"g" name style;
5862 trace_call shortname style;
5863 pr " return guestfs__%s " shortname;
5864 generate_c_call_args ~handle:"g" style;
5868 ) non_daemon_functions;
5870 (* Client-side stubs for each function. *)
5872 fun (shortname, style, _, _, _, _, _) ->
5873 let name = "guestfs_" ^ shortname in
5875 (* Generate the action stub. *)
5876 generate_prototype ~extern:false ~semicolon:false ~newline:true
5877 ~handle:"g" name style;
5880 match fst style with
5881 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5882 | RConstString _ | RConstOptString _ ->
5883 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5884 | RString _ | RStringList _
5885 | RStruct _ | RStructList _
5886 | RHashtable _ | RBufferOut _ ->
5891 (match snd style with
5893 | _ -> pr " struct %s_args args;\n" name
5896 pr " guestfs_message_header hdr;\n";
5897 pr " guestfs_message_error err;\n";
5899 match fst style with
5901 | RConstString _ | RConstOptString _ ->
5902 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5904 | RBool _ | RString _ | RStringList _
5905 | RStruct _ | RStructList _
5906 | RHashtable _ | RBufferOut _ ->
5907 pr " struct %s_ret ret;\n" name;
5910 pr " int serial;\n";
5913 trace_call shortname style;
5914 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5915 shortname error_code;
5916 pr " guestfs___set_busy (g);\n";
5919 (* Send the main header and arguments. *)
5920 (match snd style with
5922 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5923 (String.uppercase shortname)
5927 | Pathname n | Device n | Dev_or_Path n | String n ->
5928 pr " args.%s = (char *) %s;\n" n n
5930 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5931 | StringList n | DeviceList n ->
5932 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5933 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5935 pr " args.%s = %s;\n" n n
5937 pr " args.%s = %s;\n" n n
5939 pr " args.%s = %s;\n" n n
5940 | FileIn _ | FileOut _ -> ()
5942 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
5943 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
5944 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
5946 pr " guestfs___end_busy (g);\n";
5947 pr " return %s;\n" error_code;
5949 pr " args.%s.%s_val = (char *) %s;\n" n n n;
5950 pr " args.%s.%s_len = %s_size;\n" n n n
5952 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5953 (String.uppercase shortname);
5954 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5957 pr " if (serial == -1) {\n";
5958 pr " guestfs___end_busy (g);\n";
5959 pr " return %s;\n" error_code;
5963 (* Send any additional files (FileIn) requested. *)
5964 let need_read_reply_label = ref false in
5968 pr " r = guestfs___send_file (g, %s);\n" n;
5969 pr " if (r == -1) {\n";
5970 pr " guestfs___end_busy (g);\n";
5971 pr " return %s;\n" error_code;
5973 pr " if (r == -2) /* daemon cancelled */\n";
5974 pr " goto read_reply;\n";
5975 need_read_reply_label := true;
5980 (* Wait for the reply from the remote end. *)
5981 if !need_read_reply_label then pr " read_reply:\n";
5982 pr " memset (&hdr, 0, sizeof hdr);\n";
5983 pr " memset (&err, 0, sizeof err);\n";
5984 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5986 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5990 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5993 pr " if (r == -1) {\n";
5994 pr " guestfs___end_busy (g);\n";
5995 pr " return %s;\n" error_code;
5999 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6000 (String.uppercase shortname);
6001 pr " guestfs___end_busy (g);\n";
6002 pr " return %s;\n" error_code;
6006 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6007 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6008 pr " free (err.error_message);\n";
6009 pr " guestfs___end_busy (g);\n";
6010 pr " return %s;\n" error_code;
6014 (* Expecting to receive further files (FileOut)? *)
6018 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6019 pr " guestfs___end_busy (g);\n";
6020 pr " return %s;\n" error_code;
6026 pr " guestfs___end_busy (g);\n";
6028 (match fst style with
6029 | RErr -> pr " return 0;\n"
6030 | RInt n | RInt64 n | RBool n ->
6031 pr " return ret.%s;\n" n
6032 | RConstString _ | RConstOptString _ ->
6033 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6035 pr " return ret.%s; /* caller will free */\n" n
6036 | RStringList n | RHashtable n ->
6037 pr " /* caller will free this, but we need to add a NULL entry */\n";
6038 pr " ret.%s.%s_val =\n" n n;
6039 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6040 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6042 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6043 pr " return ret.%s.%s_val;\n" n n
6045 pr " /* caller will free this */\n";
6046 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6047 | RStructList (n, _) ->
6048 pr " /* caller will free this */\n";
6049 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6051 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6052 pr " * _val might be NULL here. To make the API saner for\n";
6053 pr " * callers, we turn this case into a unique pointer (using\n";
6054 pr " * malloc(1)).\n";
6056 pr " if (ret.%s.%s_len > 0) {\n" n n;
6057 pr " *size_r = ret.%s.%s_len;\n" n n;
6058 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6060 pr " free (ret.%s.%s_val);\n" n n;
6061 pr " char *p = safe_malloc (g, 1);\n";
6062 pr " *size_r = ret.%s.%s_len;\n" n n;
6070 (* Functions to free structures. *)
6071 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6072 pr " * structure format is identical to the XDR format. See note in\n";
6073 pr " * generator.ml.\n";
6080 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6082 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6088 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6090 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6097 (* Generate daemon/actions.h. *)
6098 and generate_daemon_actions_h () =
6099 generate_header CStyle GPLv2plus;
6101 pr "#include \"../src/guestfs_protocol.h\"\n";
6105 fun (name, style, _, _, _, _, _) ->
6107 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6111 (* Generate the linker script which controls the visibility of
6112 * symbols in the public ABI and ensures no other symbols get
6113 * exported accidentally.
6115 and generate_linker_script () =
6116 generate_header HashStyle GPLv2plus;
6121 "guestfs_get_error_handler";
6122 "guestfs_get_out_of_memory_handler";
6123 "guestfs_last_error";
6124 "guestfs_set_error_handler";
6125 "guestfs_set_launch_done_callback";
6126 "guestfs_set_log_message_callback";
6127 "guestfs_set_out_of_memory_handler";
6128 "guestfs_set_subprocess_quit_callback";
6130 (* Unofficial parts of the API: the bindings code use these
6131 * functions, so it is useful to export them.
6133 "guestfs_safe_calloc";
6134 "guestfs_safe_malloc";
6137 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6141 List.map (fun (typ, _) ->
6142 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6145 let globals = List.sort compare (globals @ functions @ structs) in
6149 List.iter (pr " %s;\n") globals;
6156 (* Generate the server-side stubs. *)
6157 and generate_daemon_actions () =
6158 generate_header CStyle GPLv2plus;
6160 pr "#include <config.h>\n";
6162 pr "#include <stdio.h>\n";
6163 pr "#include <stdlib.h>\n";
6164 pr "#include <string.h>\n";
6165 pr "#include <inttypes.h>\n";
6166 pr "#include <rpc/types.h>\n";
6167 pr "#include <rpc/xdr.h>\n";
6169 pr "#include \"daemon.h\"\n";
6170 pr "#include \"c-ctype.h\"\n";
6171 pr "#include \"../src/guestfs_protocol.h\"\n";
6172 pr "#include \"actions.h\"\n";
6176 fun (name, style, _, _, _, _, _) ->
6177 (* Generate server-side stubs. *)
6178 pr "static void %s_stub (XDR *xdr_in)\n" name;
6181 match fst style with
6182 | RErr | RInt _ -> pr " int r;\n"; "-1"
6183 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6184 | RBool _ -> pr " int r;\n"; "-1"
6185 | RConstString _ | RConstOptString _ ->
6186 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6187 | RString _ -> pr " char *r;\n"; "NULL"
6188 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6189 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6190 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6192 pr " size_t size = 1;\n";
6196 (match snd style with
6199 pr " struct guestfs_%s_args args;\n" name;
6202 | Device n | Dev_or_Path n
6205 | OptString n -> pr " char *%s;\n" n
6206 | StringList n | DeviceList n -> pr " char **%s;\n" n
6207 | Bool n -> pr " int %s;\n" n
6208 | Int n -> pr " int %s;\n" n
6209 | Int64 n -> pr " int64_t %s;\n" n
6210 | FileIn _ | FileOut _ -> ()
6212 pr " const char *%s;\n" n;
6213 pr " size_t %s_size;\n" n
6219 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6221 (match snd style with
6224 pr " memset (&args, 0, sizeof args);\n";
6226 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6228 pr " if (cancel_receive () != -2)\n";
6229 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6233 pr " char *%s = args.%s;\n" n n
6235 let pr_list_handling_code n =
6236 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6237 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6238 pr " if (%s == NULL) {\n" n;
6240 pr " if (cancel_receive () != -2)\n";
6241 pr " reply_with_perror (\"realloc\");\n";
6244 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6245 pr " args.%s.%s_val = %s;\n" n n n;
6251 pr " ABS_PATH (%s, %s, goto done);\n"
6252 n (if is_filein then "cancel_receive ()" else "0");
6255 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6256 n (if is_filein then "cancel_receive ()" else "0");
6259 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6260 n (if is_filein then "cancel_receive ()" else "0");
6261 | String n -> pr_args n
6262 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6264 pr_list_handling_code n;
6266 pr_list_handling_code n;
6267 pr " /* Ensure that each is a device,\n";
6268 pr " * and perform device name translation. */\n";
6269 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6270 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6271 (if is_filein then "cancel_receive ()" else "0");
6273 | Bool n -> pr " %s = args.%s;\n" n n
6274 | Int n -> pr " %s = args.%s;\n" n n
6275 | Int64 n -> pr " %s = args.%s;\n" n n
6276 | FileIn _ | FileOut _ -> ()
6278 pr " %s = args.%s.%s_val;\n" n n n;
6279 pr " %s_size = args.%s.%s_len;\n" n n n
6284 (* this is used at least for do_equal *)
6285 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6286 (* Emit NEED_ROOT just once, even when there are two or
6287 more Pathname args *)
6288 pr " NEED_ROOT (%s, goto done);\n"
6289 (if is_filein then "cancel_receive ()" else "0");
6292 (* Don't want to call the impl with any FileIn or FileOut
6293 * parameters, since these go "outside" the RPC protocol.
6296 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6298 pr " r = do_%s " name;
6299 generate_c_call_args (fst style, args');
6302 (match fst style with
6303 | RErr | RInt _ | RInt64 _ | RBool _
6304 | RConstString _ | RConstOptString _
6305 | RString _ | RStringList _ | RHashtable _
6306 | RStruct (_, _) | RStructList (_, _) ->
6307 pr " if (r == %s)\n" error_code;
6308 pr " /* do_%s has already called reply_with_error */\n" name;
6312 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6313 pr " * an ordinary zero-length buffer), so be careful ...\n";
6315 pr " if (size == 1 && r == %s)\n" error_code;
6316 pr " /* do_%s has already called reply_with_error */\n" name;
6321 (* If there are any FileOut parameters, then the impl must
6322 * send its own reply.
6325 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6327 pr " /* do_%s has already sent a reply */\n" name
6329 match fst style with
6330 | RErr -> pr " reply (NULL, NULL);\n"
6331 | RInt n | RInt64 n | RBool n ->
6332 pr " struct guestfs_%s_ret ret;\n" name;
6333 pr " ret.%s = r;\n" n;
6334 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6336 | RConstString _ | RConstOptString _ ->
6337 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6339 pr " struct guestfs_%s_ret ret;\n" name;
6340 pr " ret.%s = r;\n" n;
6341 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6344 | RStringList n | RHashtable n ->
6345 pr " struct guestfs_%s_ret ret;\n" name;
6346 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6347 pr " ret.%s.%s_val = r;\n" n n;
6348 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6350 pr " free_strings (r);\n"
6352 pr " struct guestfs_%s_ret ret;\n" name;
6353 pr " ret.%s = *r;\n" n;
6354 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6356 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6358 | RStructList (n, _) ->
6359 pr " struct guestfs_%s_ret ret;\n" name;
6360 pr " ret.%s = *r;\n" n;
6361 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6363 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6366 pr " struct guestfs_%s_ret ret;\n" name;
6367 pr " ret.%s.%s_val = r;\n" n n;
6368 pr " ret.%s.%s_len = size;\n" n n;
6369 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6374 (* Free the args. *)
6376 (match snd style with
6379 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6386 (* Dispatch function. *)
6387 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6389 pr " switch (proc_nr) {\n";
6392 fun (name, style, _, _, _, _, _) ->
6393 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6394 pr " %s_stub (xdr_in);\n" name;
6399 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";
6404 (* LVM columns and tokenization functions. *)
6405 (* XXX This generates crap code. We should rethink how we
6411 pr "static const char *lvm_%s_cols = \"%s\";\n"
6412 typ (String.concat "," (List.map fst cols));
6415 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6417 pr " char *tok, *p, *next;\n";
6421 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6424 pr " if (!str) {\n";
6425 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6428 pr " if (!*str || c_isspace (*str)) {\n";
6429 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6434 fun (name, coltype) ->
6435 pr " if (!tok) {\n";
6436 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6439 pr " p = strchrnul (tok, ',');\n";
6440 pr " if (*p) next = p+1; else next = NULL;\n";
6441 pr " *p = '\\0';\n";
6444 pr " r->%s = strdup (tok);\n" name;
6445 pr " if (r->%s == NULL) {\n" name;
6446 pr " perror (\"strdup\");\n";
6450 pr " for (i = j = 0; i < 32; ++j) {\n";
6451 pr " if (tok[j] == '\\0') {\n";
6452 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6454 pr " } else if (tok[j] != '-')\n";
6455 pr " r->%s[i++] = tok[j];\n" name;
6458 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6459 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6463 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6464 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6468 pr " if (tok[0] == '\\0')\n";
6469 pr " r->%s = -1;\n" name;
6470 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6471 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6474 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6475 assert false (* can never be an LVM column *)
6477 pr " tok = next;\n";
6480 pr " if (tok != NULL) {\n";
6481 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6488 pr "guestfs_int_lvm_%s_list *\n" typ;
6489 pr "parse_command_line_%ss (void)\n" typ;
6491 pr " char *out, *err;\n";
6492 pr " char *p, *pend;\n";
6494 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6495 pr " void *newp;\n";
6497 pr " ret = malloc (sizeof *ret);\n";
6498 pr " if (!ret) {\n";
6499 pr " reply_with_perror (\"malloc\");\n";
6500 pr " return NULL;\n";
6503 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6504 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6506 pr " r = command (&out, &err,\n";
6507 pr " \"lvm\", \"%ss\",\n" typ;
6508 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6509 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6510 pr " if (r == -1) {\n";
6511 pr " reply_with_error (\"%%s\", err);\n";
6512 pr " free (out);\n";
6513 pr " free (err);\n";
6514 pr " free (ret);\n";
6515 pr " return NULL;\n";
6518 pr " free (err);\n";
6520 pr " /* Tokenize each line of the output. */\n";
6523 pr " while (p) {\n";
6524 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6525 pr " if (pend) {\n";
6526 pr " *pend = '\\0';\n";
6530 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6533 pr " if (!*p) { /* Empty line? Skip it. */\n";
6538 pr " /* Allocate some space to store this next entry. */\n";
6539 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6540 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6541 pr " if (newp == NULL) {\n";
6542 pr " reply_with_perror (\"realloc\");\n";
6543 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6544 pr " free (ret);\n";
6545 pr " free (out);\n";
6546 pr " return NULL;\n";
6548 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6550 pr " /* Tokenize the next entry. */\n";
6551 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6552 pr " if (r == -1) {\n";
6553 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6554 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6555 pr " free (ret);\n";
6556 pr " free (out);\n";
6557 pr " return NULL;\n";
6564 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6566 pr " free (out);\n";
6567 pr " return ret;\n";
6570 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6572 (* Generate a list of function names, for debugging in the daemon.. *)
6573 and generate_daemon_names () =
6574 generate_header CStyle GPLv2plus;
6576 pr "#include <config.h>\n";
6578 pr "#include \"daemon.h\"\n";
6581 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6582 pr "const char *function_names[] = {\n";
6584 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6588 (* Generate the optional groups for the daemon to implement
6589 * guestfs_available.
6591 and generate_daemon_optgroups_c () =
6592 generate_header CStyle GPLv2plus;
6594 pr "#include <config.h>\n";
6596 pr "#include \"daemon.h\"\n";
6597 pr "#include \"optgroups.h\"\n";
6600 pr "struct optgroup optgroups[] = {\n";
6603 pr " { \"%s\", optgroup_%s_available },\n" group group
6605 pr " { NULL, NULL }\n";
6608 and generate_daemon_optgroups_h () =
6609 generate_header CStyle GPLv2plus;
6613 pr "extern int optgroup_%s_available (void);\n" group
6616 (* Generate the tests. *)
6617 and generate_tests () =
6618 generate_header CStyle GPLv2plus;
6625 #include <sys/types.h>
6628 #include \"guestfs.h\"
6629 #include \"guestfs-internal.h\"
6631 static guestfs_h *g;
6632 static int suppress_error = 0;
6634 static void print_error (guestfs_h *g, void *data, const char *msg)
6636 if (!suppress_error)
6637 fprintf (stderr, \"%%s\\n\", msg);
6640 /* FIXME: nearly identical code appears in fish.c */
6641 static void print_strings (char *const *argv)
6645 for (argc = 0; argv[argc] != NULL; ++argc)
6646 printf (\"\\t%%s\\n\", argv[argc]);
6650 static void print_table (char const *const *argv)
6654 for (i = 0; argv[i] != NULL; i += 2)
6655 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6661 (* Generate a list of commands which are not tested anywhere. *)
6662 pr "static void no_test_warnings (void)\n";
6665 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6667 fun (_, _, _, _, tests, _, _) ->
6668 let tests = filter_map (
6670 | (_, (Always|If _|Unless _), test) -> Some test
6671 | (_, Disabled, _) -> None
6673 let seq = List.concat (List.map seq_of_test tests) in
6674 let cmds_tested = List.map List.hd seq in
6675 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6679 fun (name, _, _, _, _, _, _) ->
6680 if not (Hashtbl.mem hash name) then
6681 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6687 (* Generate the actual tests. Note that we generate the tests
6688 * in reverse order, deliberately, so that (in general) the
6689 * newest tests run first. This makes it quicker and easier to
6694 fun (name, _, _, flags, tests, _, _) ->
6695 mapi (generate_one_test name flags) tests
6696 ) (List.rev all_functions) in
6697 let test_names = List.concat test_names in
6698 let nr_tests = List.length test_names in
6701 int main (int argc, char *argv[])
6704 unsigned long int n_failed = 0;
6705 const char *filename;
6707 int nr_tests, test_num = 0;
6709 setbuf (stdout, NULL);
6711 no_test_warnings ();
6713 g = guestfs_create ();
6715 printf (\"guestfs_create FAILED\\n\");
6716 exit (EXIT_FAILURE);
6719 guestfs_set_error_handler (g, print_error, NULL);
6721 guestfs_set_path (g, \"../appliance\");
6723 filename = \"test1.img\";
6724 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6727 exit (EXIT_FAILURE);
6729 if (lseek (fd, %d, SEEK_SET) == -1) {
6733 exit (EXIT_FAILURE);
6735 if (write (fd, &c, 1) == -1) {
6739 exit (EXIT_FAILURE);
6741 if (close (fd) == -1) {
6744 exit (EXIT_FAILURE);
6746 if (guestfs_add_drive (g, filename) == -1) {
6747 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6748 exit (EXIT_FAILURE);
6751 filename = \"test2.img\";
6752 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6755 exit (EXIT_FAILURE);
6757 if (lseek (fd, %d, SEEK_SET) == -1) {
6761 exit (EXIT_FAILURE);
6763 if (write (fd, &c, 1) == -1) {
6767 exit (EXIT_FAILURE);
6769 if (close (fd) == -1) {
6772 exit (EXIT_FAILURE);
6774 if (guestfs_add_drive (g, filename) == -1) {
6775 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6776 exit (EXIT_FAILURE);
6779 filename = \"test3.img\";
6780 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6783 exit (EXIT_FAILURE);
6785 if (lseek (fd, %d, SEEK_SET) == -1) {
6789 exit (EXIT_FAILURE);
6791 if (write (fd, &c, 1) == -1) {
6795 exit (EXIT_FAILURE);
6797 if (close (fd) == -1) {
6800 exit (EXIT_FAILURE);
6802 if (guestfs_add_drive (g, filename) == -1) {
6803 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6804 exit (EXIT_FAILURE);
6807 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6808 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6809 exit (EXIT_FAILURE);
6812 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6815 if (guestfs_launch (g) == -1) {
6816 printf (\"guestfs_launch FAILED\\n\");
6817 exit (EXIT_FAILURE);
6820 /* Cancel previous alarm. */
6825 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6829 pr " test_num++;\n";
6830 pr " if (guestfs_get_verbose (g))\n";
6831 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6832 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6833 pr " if (%s () == -1) {\n" test_name;
6834 pr " printf (\"%s FAILED\\n\");\n" test_name;
6835 pr " n_failed++;\n";
6840 pr " guestfs_close (g);\n";
6841 pr " unlink (\"test1.img\");\n";
6842 pr " unlink (\"test2.img\");\n";
6843 pr " unlink (\"test3.img\");\n";
6846 pr " if (n_failed > 0) {\n";
6847 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6848 pr " exit (EXIT_FAILURE);\n";
6852 pr " exit (EXIT_SUCCESS);\n";
6855 and generate_one_test name flags i (init, prereq, test) =
6856 let test_name = sprintf "test_%s_%d" name i in
6859 static int %s_skip (void)
6863 str = getenv (\"TEST_ONLY\");
6865 return strstr (str, \"%s\") == NULL;
6866 str = getenv (\"SKIP_%s\");
6867 if (str && STREQ (str, \"1\")) return 1;
6868 str = getenv (\"SKIP_TEST_%s\");
6869 if (str && STREQ (str, \"1\")) return 1;
6873 " test_name name (String.uppercase test_name) (String.uppercase name);
6876 | Disabled | Always -> ()
6877 | If code | Unless code ->
6878 pr "static int %s_prereq (void)\n" test_name;
6886 static int %s (void)
6889 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6893 " test_name test_name test_name;
6895 (* Optional functions should only be tested if the relevant
6896 * support is available in the daemon.
6902 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6904 pr " suppress_error = 1;\n";
6905 pr " r = guestfs_available (g, (char **) groups);\n";
6906 pr " suppress_error = 0;\n";
6907 pr " if (r == -1) {\n";
6908 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6917 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6919 pr " if (! %s_prereq ()) {\n" test_name;
6920 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6924 generate_one_test_body name i test_name init test;
6926 pr " if (%s_prereq ()) {\n" test_name;
6927 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6931 generate_one_test_body name i test_name init test;
6933 generate_one_test_body name i test_name init test
6941 and generate_one_test_body name i test_name init test =
6943 | InitNone (* XXX at some point, InitNone and InitEmpty became
6944 * folded together as the same thing. Really we should
6945 * make InitNone do nothing at all, but the tests may
6946 * need to be checked to make sure this is OK.
6949 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6950 List.iter (generate_test_command_call test_name)
6951 [["blockdev_setrw"; "/dev/sda"];
6955 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6956 List.iter (generate_test_command_call test_name)
6957 [["blockdev_setrw"; "/dev/sda"];
6960 ["part_disk"; "/dev/sda"; "mbr"]]
6962 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6963 List.iter (generate_test_command_call test_name)
6964 [["blockdev_setrw"; "/dev/sda"];
6967 ["part_disk"; "/dev/sda"; "mbr"];
6968 ["mkfs"; "ext2"; "/dev/sda1"];
6969 ["mount_options"; ""; "/dev/sda1"; "/"]]
6970 | InitBasicFSonLVM ->
6971 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6973 List.iter (generate_test_command_call test_name)
6974 [["blockdev_setrw"; "/dev/sda"];
6977 ["part_disk"; "/dev/sda"; "mbr"];
6978 ["pvcreate"; "/dev/sda1"];
6979 ["vgcreate"; "VG"; "/dev/sda1"];
6980 ["lvcreate"; "LV"; "VG"; "8"];
6981 ["mkfs"; "ext2"; "/dev/VG/LV"];
6982 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6984 pr " /* InitISOFS for %s */\n" test_name;
6985 List.iter (generate_test_command_call test_name)
6986 [["blockdev_setrw"; "/dev/sda"];
6989 ["mount_ro"; "/dev/sdd"; "/"]]
6992 let get_seq_last = function
6994 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6997 let seq = List.rev seq in
6998 List.rev (List.tl seq), List.hd seq
7003 pr " /* TestRun for %s (%d) */\n" name i;
7004 List.iter (generate_test_command_call test_name) seq
7005 | TestOutput (seq, expected) ->
7006 pr " /* TestOutput for %s (%d) */\n" name i;
7007 pr " const char *expected = \"%s\";\n" (c_quote expected);
7008 let seq, last = get_seq_last seq in
7010 pr " if (STRNEQ (r, expected)) {\n";
7011 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7015 List.iter (generate_test_command_call test_name) seq;
7016 generate_test_command_call ~test test_name last
7017 | TestOutputList (seq, expected) ->
7018 pr " /* TestOutputList for %s (%d) */\n" name i;
7019 let seq, last = get_seq_last seq in
7023 pr " if (!r[%d]) {\n" i;
7024 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7025 pr " print_strings (r);\n";
7029 pr " const char *expected = \"%s\";\n" (c_quote str);
7030 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7031 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7036 pr " if (r[%d] != NULL) {\n" (List.length expected);
7037 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7039 pr " print_strings (r);\n";
7043 List.iter (generate_test_command_call test_name) seq;
7044 generate_test_command_call ~test test_name last
7045 | TestOutputListOfDevices (seq, expected) ->
7046 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7047 let seq, last = get_seq_last seq in
7051 pr " if (!r[%d]) {\n" i;
7052 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7053 pr " print_strings (r);\n";
7057 pr " const char *expected = \"%s\";\n" (c_quote str);
7058 pr " r[%d][5] = 's';\n" i;
7059 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7060 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7065 pr " if (r[%d] != NULL) {\n" (List.length expected);
7066 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7068 pr " print_strings (r);\n";
7072 List.iter (generate_test_command_call test_name) seq;
7073 generate_test_command_call ~test test_name last
7074 | TestOutputInt (seq, expected) ->
7075 pr " /* TestOutputInt for %s (%d) */\n" name i;
7076 let seq, last = get_seq_last seq in
7078 pr " if (r != %d) {\n" expected;
7079 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7085 List.iter (generate_test_command_call test_name) seq;
7086 generate_test_command_call ~test test_name last
7087 | TestOutputIntOp (seq, op, expected) ->
7088 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7089 let seq, last = get_seq_last seq in
7091 pr " if (! (r %s %d)) {\n" op expected;
7092 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7093 test_name op expected;
7098 List.iter (generate_test_command_call test_name) seq;
7099 generate_test_command_call ~test test_name last
7100 | TestOutputTrue seq ->
7101 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7102 let seq, last = get_seq_last seq in
7105 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7110 List.iter (generate_test_command_call test_name) seq;
7111 generate_test_command_call ~test test_name last
7112 | TestOutputFalse seq ->
7113 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7114 let seq, last = get_seq_last seq in
7117 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7122 List.iter (generate_test_command_call test_name) seq;
7123 generate_test_command_call ~test test_name last
7124 | TestOutputLength (seq, expected) ->
7125 pr " /* TestOutputLength for %s (%d) */\n" name i;
7126 let seq, last = get_seq_last seq in
7129 pr " for (j = 0; j < %d; ++j)\n" expected;
7130 pr " if (r[j] == NULL) {\n";
7131 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7133 pr " print_strings (r);\n";
7136 pr " if (r[j] != NULL) {\n";
7137 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7139 pr " print_strings (r);\n";
7143 List.iter (generate_test_command_call test_name) seq;
7144 generate_test_command_call ~test test_name last
7145 | TestOutputBuffer (seq, expected) ->
7146 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7147 pr " const char *expected = \"%s\";\n" (c_quote expected);
7148 let seq, last = get_seq_last seq in
7149 let len = String.length expected in
7151 pr " if (size != %d) {\n" len;
7152 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7155 pr " if (STRNEQLEN (r, expected, size)) {\n";
7156 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7160 List.iter (generate_test_command_call test_name) seq;
7161 generate_test_command_call ~test test_name last
7162 | TestOutputStruct (seq, checks) ->
7163 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7164 let seq, last = get_seq_last seq in
7168 | CompareWithInt (field, expected) ->
7169 pr " if (r->%s != %d) {\n" field expected;
7170 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7171 test_name field expected;
7172 pr " (int) r->%s);\n" field;
7175 | CompareWithIntOp (field, op, expected) ->
7176 pr " if (!(r->%s %s %d)) {\n" field op expected;
7177 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7178 test_name field op expected;
7179 pr " (int) r->%s);\n" field;
7182 | CompareWithString (field, expected) ->
7183 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7184 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7185 test_name field expected;
7186 pr " r->%s);\n" field;
7189 | CompareFieldsIntEq (field1, field2) ->
7190 pr " if (r->%s != r->%s) {\n" field1 field2;
7191 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7192 test_name field1 field2;
7193 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7196 | CompareFieldsStrEq (field1, field2) ->
7197 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7198 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7199 test_name field1 field2;
7200 pr " r->%s, r->%s);\n" field1 field2;
7205 List.iter (generate_test_command_call test_name) seq;
7206 generate_test_command_call ~test test_name last
7207 | TestLastFail seq ->
7208 pr " /* TestLastFail for %s (%d) */\n" name i;
7209 let seq, last = get_seq_last seq in
7210 List.iter (generate_test_command_call test_name) seq;
7211 generate_test_command_call test_name ~expect_error:true last
7213 (* Generate the code to run a command, leaving the result in 'r'.
7214 * If you expect to get an error then you should set expect_error:true.
7216 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7218 | [] -> assert false
7220 (* Look up the command to find out what args/ret it has. *)
7223 let _, style, _, _, _, _, _ =
7224 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7227 failwithf "%s: in test, command %s was not found" test_name name in
7229 if List.length (snd style) <> List.length args then
7230 failwithf "%s: in test, wrong number of args given to %s"
7237 | OptString n, "NULL" -> ()
7240 | Dev_or_Path n, arg
7242 | OptString n, arg ->
7243 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7244 | BufferIn n, arg ->
7245 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7246 pr " size_t %s_size = %d;\n" n (String.length arg)
7250 | FileIn _, _ | FileOut _, _ -> ()
7251 | StringList n, "" | DeviceList n, "" ->
7252 pr " const char *const %s[1] = { NULL };\n" n
7253 | StringList n, arg | DeviceList n, arg ->
7254 let strs = string_split " " arg in
7257 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7259 pr " const char *const %s[] = {\n" n;
7261 fun i _ -> pr " %s_%d,\n" n i
7265 ) (List.combine (snd style) args);
7268 match fst style with
7269 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7270 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7271 | RConstString _ | RConstOptString _ ->
7272 pr " const char *r;\n"; "NULL"
7273 | RString _ -> pr " char *r;\n"; "NULL"
7274 | RStringList _ | RHashtable _ ->
7278 | RStruct (_, typ) ->
7279 pr " struct guestfs_%s *r;\n" typ; "NULL"
7280 | RStructList (_, typ) ->
7281 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7284 pr " size_t size;\n";
7287 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7288 pr " r = guestfs_%s (g" name;
7290 (* Generate the parameters. *)
7293 | OptString _, "NULL" -> pr ", NULL"
7295 | Device n, _ | Dev_or_Path n, _
7300 pr ", %s, %s_size" n n
7301 | FileIn _, arg | FileOut _, arg ->
7302 pr ", \"%s\"" (c_quote arg)
7303 | StringList n, _ | DeviceList n, _ ->
7304 pr ", (char **) %s" n
7307 try int_of_string arg
7308 with Failure "int_of_string" ->
7309 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7313 try Int64.of_string arg
7314 with Failure "int_of_string" ->
7315 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7318 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7319 ) (List.combine (snd style) args);
7321 (match fst style with
7322 | RBufferOut _ -> pr ", &size"
7328 if not expect_error then
7329 pr " if (r == %s)\n" error_code
7331 pr " if (r != %s)\n" error_code;
7334 (* Insert the test code. *)
7340 (match fst style with
7341 | RErr | RInt _ | RInt64 _ | RBool _
7342 | RConstString _ | RConstOptString _ -> ()
7343 | RString _ | RBufferOut _ -> pr " free (r);\n"
7344 | RStringList _ | RHashtable _ ->
7345 pr " for (i = 0; r[i] != NULL; ++i)\n";
7346 pr " free (r[i]);\n";
7348 | RStruct (_, typ) ->
7349 pr " guestfs_free_%s (r);\n" typ
7350 | RStructList (_, typ) ->
7351 pr " guestfs_free_%s_list (r);\n" typ
7357 let str = replace_str str "\r" "\\r" in
7358 let str = replace_str str "\n" "\\n" in
7359 let str = replace_str str "\t" "\\t" in
7360 let str = replace_str str "\000" "\\0" in
7363 (* Generate a lot of different functions for guestfish. *)
7364 and generate_fish_cmds () =
7365 generate_header CStyle GPLv2plus;
7369 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7371 let all_functions_sorted =
7373 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7374 ) all_functions_sorted in
7376 pr "#include <config.h>\n";
7378 pr "#include <stdio.h>\n";
7379 pr "#include <stdlib.h>\n";
7380 pr "#include <string.h>\n";
7381 pr "#include <inttypes.h>\n";
7383 pr "#include <guestfs.h>\n";
7384 pr "#include \"c-ctype.h\"\n";
7385 pr "#include \"full-write.h\"\n";
7386 pr "#include \"xstrtol.h\"\n";
7387 pr "#include \"fish.h\"\n";
7390 (* list_commands function, which implements guestfish -h *)
7391 pr "void list_commands (void)\n";
7393 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7394 pr " list_builtin_commands ();\n";
7396 fun (name, _, _, flags, _, shortdesc, _) ->
7397 let name = replace_char name '_' '-' in
7398 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7400 ) all_functions_sorted;
7401 pr " printf (\" %%s\\n\",";
7402 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7406 (* display_command function, which implements guestfish -h cmd *)
7407 pr "void display_command (const char *cmd)\n";
7410 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7411 let name2 = replace_char name '_' '-' in
7413 try find_map (function FishAlias n -> Some n | _ -> None) flags
7414 with Not_found -> name in
7415 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7417 match snd style with
7421 name2 (String.concat " " (List.map name_of_argt args)) in
7424 if List.mem ProtocolLimitWarning flags then
7425 ("\n\n" ^ protocol_limit_warning)
7428 (* For DangerWillRobinson commands, we should probably have
7429 * guestfish prompt before allowing you to use them (especially
7430 * in interactive mode). XXX
7434 if List.mem DangerWillRobinson flags then
7435 ("\n\n" ^ danger_will_robinson)
7440 match deprecation_notice flags with
7442 | Some txt -> "\n\n" ^ txt in
7444 let describe_alias =
7445 if name <> alias then
7446 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7450 pr "STRCASEEQ (cmd, \"%s\")" name;
7451 if name <> name2 then
7452 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7453 if name <> alias then
7454 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7456 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7458 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7459 "=head1 DESCRIPTION\n\n" ^
7460 longdesc ^ warnings ^ describe_alias);
7463 pr " display_builtin_command (cmd);\n";
7467 let emit_print_list_function typ =
7468 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7471 pr " unsigned int i;\n";
7473 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7474 pr " printf (\"[%%d] = {\\n\", i);\n";
7475 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7476 pr " printf (\"}\\n\");\n";
7482 (* print_* functions *)
7486 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7488 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7491 pr " unsigned int i;\n";
7497 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7499 pr " printf (\"%%s%s: \", indent);\n" name;
7500 pr " for (i = 0; i < 32; ++i)\n";
7501 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7502 pr " printf (\"\\n\");\n"
7504 pr " printf (\"%%s%s: \", indent);\n" name;
7505 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7506 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7507 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7509 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7510 pr " printf (\"\\n\");\n"
7511 | name, (FUInt64|FBytes) ->
7512 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7515 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7518 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7521 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7524 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7526 | name, FOptPercent ->
7527 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7528 typ name name typ name;
7529 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7535 (* Emit a print_TYPE_list function definition only if that function is used. *)
7538 | typ, (RStructListOnly | RStructAndList) ->
7539 (* generate the function for typ *)
7540 emit_print_list_function typ
7541 | typ, _ -> () (* empty *)
7542 ) (rstructs_used_by all_functions);
7544 (* Emit a print_TYPE function definition only if that function is used. *)
7547 | typ, (RStructOnly | RStructAndList) ->
7548 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7550 pr " print_%s_indent (%s, \"\");\n" typ typ;
7553 | typ, _ -> () (* empty *)
7554 ) (rstructs_used_by all_functions);
7556 (* run_<action> actions *)
7558 fun (name, style, _, flags, _, _, _) ->
7559 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7561 (match fst style with
7564 | RBool _ -> pr " int r;\n"
7565 | RInt64 _ -> pr " int64_t r;\n"
7566 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7567 | RString _ -> pr " char *r;\n"
7568 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7569 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7570 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7573 pr " size_t size;\n";
7579 | OptString n -> pr " const char *%s;\n" n
7583 | FileOut n -> pr " char *%s;\n" n
7585 pr " const char *%s;\n" n;
7586 pr " size_t %s_size;\n" n
7587 | StringList n | DeviceList n -> pr " char **%s;\n" n
7588 | Bool n -> pr " int %s;\n" n
7589 | Int n -> pr " int %s;\n" n
7590 | Int64 n -> pr " int64_t %s;\n" n
7593 (* Check and convert parameters. *)
7594 let argc_expected = List.length (snd style) in
7595 pr " if (argc != %d) {\n" argc_expected;
7596 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7598 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7602 let parse_integer fn fntyp rtyp range name i =
7604 pr " strtol_error xerr;\n";
7605 pr " %s r;\n" fntyp;
7607 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7608 pr " if (xerr != LONGINT_OK) {\n";
7609 pr " fprintf (stderr,\n";
7610 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7611 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7616 | Some (min, max, comment) ->
7617 pr " /* %s */\n" comment;
7618 pr " if (r < %s || r > %s) {\n" min max;
7619 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7623 pr " /* The check above should ensure this assignment does not overflow. */\n";
7625 pr " %s = r;\n" name;
7634 pr " %s = argv[%d];\n" name i
7636 | Dev_or_Path name ->
7637 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7638 pr " if (%s == NULL) return -1;\n" name
7640 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7643 pr " %s = argv[%d];\n" name i;
7644 pr " %s_size = strlen (argv[%d]);\n" name i
7646 pr " %s = file_in (argv[%d]);\n" name i;
7647 pr " if (%s == NULL) return -1;\n" name
7649 pr " %s = file_out (argv[%d]);\n" name i;
7650 pr " if (%s == NULL) return -1;\n" name
7651 | StringList name | DeviceList name ->
7652 pr " %s = parse_string_list (argv[%d]);\n" name i;
7653 pr " if (%s == NULL) return -1;\n" name;
7655 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7658 let min = "(-(2LL<<30))"
7659 and max = "((2LL<<30)-1)"
7661 "The Int type in the generator is a signed 31 bit int." in
7662 Some (min, max, comment) in
7663 parse_integer "xstrtoll" "long long" "int" range name i
7665 parse_integer "xstrtoll" "long long" "int64_t" None name i
7668 (* Call C API function. *)
7669 pr " r = guestfs_%s " name;
7670 generate_c_call_args ~handle:"g" style;
7675 | Device name | String name
7676 | OptString name | Bool name
7677 | Int name | Int64 name
7678 | BufferIn name -> ()
7679 | Pathname name | Dev_or_Path name | FileOut name ->
7680 pr " free (%s);\n" name
7682 pr " free_file_in (%s);\n" name
7683 | StringList name | DeviceList name ->
7684 pr " free_strings (%s);\n" name
7687 (* Any output flags? *)
7689 let flags = filter_map (
7690 function FishOutput flag -> Some flag | _ -> None
7696 failwithf "%s: more than one FishOutput flag is not allowed" name in
7698 (* Check return value for errors and display command results. *)
7699 (match fst style with
7700 | RErr -> pr " return r;\n"
7702 pr " if (r == -1) return -1;\n";
7703 (match fish_output with
7705 pr " printf (\"%%d\\n\", r);\n";
7706 | Some FishOutputOctal ->
7707 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7708 | Some FishOutputHexadecimal ->
7709 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7712 pr " if (r == -1) return -1;\n";
7713 (match fish_output with
7715 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7716 | Some FishOutputOctal ->
7717 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7718 | Some FishOutputHexadecimal ->
7719 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7722 pr " if (r == -1) return -1;\n";
7723 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7726 pr " if (r == NULL) return -1;\n";
7727 pr " printf (\"%%s\\n\", r);\n";
7729 | RConstOptString _ ->
7730 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7733 pr " if (r == NULL) return -1;\n";
7734 pr " printf (\"%%s\\n\", r);\n";
7738 pr " if (r == NULL) return -1;\n";
7739 pr " print_strings (r);\n";
7740 pr " free_strings (r);\n";
7742 | RStruct (_, typ) ->
7743 pr " if (r == NULL) return -1;\n";
7744 pr " print_%s (r);\n" typ;
7745 pr " guestfs_free_%s (r);\n" typ;
7747 | RStructList (_, typ) ->
7748 pr " if (r == NULL) return -1;\n";
7749 pr " print_%s_list (r);\n" typ;
7750 pr " guestfs_free_%s_list (r);\n" typ;
7753 pr " if (r == NULL) return -1;\n";
7754 pr " print_table (r);\n";
7755 pr " free_strings (r);\n";
7758 pr " if (r == NULL) return -1;\n";
7759 pr " if (full_write (1, r, size) != size) {\n";
7760 pr " perror (\"write\");\n";
7771 (* run_action function *)
7772 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7775 fun (name, _, _, flags, _, _, _) ->
7776 let name2 = replace_char name '_' '-' in
7778 try find_map (function FishAlias n -> Some n | _ -> None) flags
7779 with Not_found -> name in
7781 pr "STRCASEEQ (cmd, \"%s\")" name;
7782 if name <> name2 then
7783 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7784 if name <> alias then
7785 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7787 pr " return run_%s (cmd, argc, argv);\n" name;
7791 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7792 pr " if (command_num == 1)\n";
7793 pr " extended_help_message ();\n";
7800 (* Readline completion for guestfish. *)
7801 and generate_fish_completion () =
7802 generate_header CStyle GPLv2plus;
7806 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7816 #ifdef HAVE_LIBREADLINE
7817 #include <readline/readline.h>
7822 #ifdef HAVE_LIBREADLINE
7824 static const char *const commands[] = {
7825 BUILTIN_COMMANDS_FOR_COMPLETION,
7828 (* Get the commands, including the aliases. They don't need to be
7829 * sorted - the generator() function just does a dumb linear search.
7833 fun (name, _, _, flags, _, _, _) ->
7834 let name2 = replace_char name '_' '-' in
7836 try find_map (function FishAlias n -> Some n | _ -> None) flags
7837 with Not_found -> name in
7839 if name <> alias then [name2; alias] else [name2]
7841 let commands = List.flatten commands in
7843 List.iter (pr " \"%s\",\n") commands;
7849 generator (const char *text, int state)
7851 static int index, len;
7856 len = strlen (text);
7859 rl_attempted_completion_over = 1;
7861 while ((name = commands[index]) != NULL) {
7863 if (STRCASEEQLEN (name, text, len))
7864 return strdup (name);
7870 #endif /* HAVE_LIBREADLINE */
7872 #ifdef HAVE_RL_COMPLETION_MATCHES
7873 #define RL_COMPLETION_MATCHES rl_completion_matches
7875 #ifdef HAVE_COMPLETION_MATCHES
7876 #define RL_COMPLETION_MATCHES completion_matches
7878 #endif /* else just fail if we don't have either symbol */
7881 do_completion (const char *text, int start, int end)
7883 char **matches = NULL;
7885 #ifdef HAVE_LIBREADLINE
7886 rl_completion_append_character = ' ';
7889 matches = RL_COMPLETION_MATCHES (text, generator);
7890 else if (complete_dest_paths)
7891 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7898 (* Generate the POD documentation for guestfish. *)
7899 and generate_fish_actions_pod () =
7900 let all_functions_sorted =
7902 fun (_, _, _, flags, _, _, _) ->
7903 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7904 ) all_functions_sorted in
7906 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7909 fun (name, style, _, flags, _, _, longdesc) ->
7911 Str.global_substitute rex (
7914 try Str.matched_group 1 s
7916 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7917 "C<" ^ replace_char sub '_' '-' ^ ">"
7919 let name = replace_char name '_' '-' in
7921 try find_map (function FishAlias n -> Some n | _ -> None) flags
7922 with Not_found -> name in
7924 pr "=head2 %s" name;
7925 if name <> alias then
7932 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7933 | OptString n -> pr " %s" n
7934 | StringList n | DeviceList n -> pr " '%s ...'" n
7935 | Bool _ -> pr " true|false"
7936 | Int n -> pr " %s" n
7937 | Int64 n -> pr " %s" n
7938 | FileIn n | FileOut n -> pr " (%s|-)" n
7939 | BufferIn n -> pr " %s" n
7943 pr "%s\n\n" longdesc;
7945 if List.exists (function FileIn _ | FileOut _ -> true
7946 | _ -> false) (snd style) then
7947 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7949 if List.mem ProtocolLimitWarning flags then
7950 pr "%s\n\n" protocol_limit_warning;
7952 if List.mem DangerWillRobinson flags then
7953 pr "%s\n\n" danger_will_robinson;
7955 match deprecation_notice flags with
7957 | Some txt -> pr "%s\n\n" txt
7958 ) all_functions_sorted
7960 (* Generate a C function prototype. *)
7961 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7962 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7964 ?handle name style =
7965 if extern then pr "extern ";
7966 if static then pr "static ";
7967 (match fst style with
7969 | RInt _ -> pr "int "
7970 | RInt64 _ -> pr "int64_t "
7971 | RBool _ -> pr "int "
7972 | RConstString _ | RConstOptString _ -> pr "const char *"
7973 | RString _ | RBufferOut _ -> pr "char *"
7974 | RStringList _ | RHashtable _ -> pr "char **"
7975 | RStruct (_, typ) ->
7976 if not in_daemon then pr "struct guestfs_%s *" typ
7977 else pr "guestfs_int_%s *" typ
7978 | RStructList (_, typ) ->
7979 if not in_daemon then pr "struct guestfs_%s_list *" typ
7980 else pr "guestfs_int_%s_list *" typ
7982 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7983 pr "%s%s (" prefix name;
7984 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7987 let comma = ref false in
7990 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7994 if single_line then pr ", " else pr ",\n\t\t"
8001 | Device n | Dev_or_Path n
8005 pr "const char *%s" n
8006 | StringList n | DeviceList n ->
8008 pr "char *const *%s" n
8009 | Bool n -> next (); pr "int %s" n
8010 | Int n -> next (); pr "int %s" n
8011 | Int64 n -> next (); pr "int64_t %s" n
8014 if not in_daemon then (next (); pr "const char *%s" n)
8017 pr "const char *%s" n;
8019 pr "size_t %s_size" n
8021 if is_RBufferOut then (next (); pr "size_t *size_r");
8024 if semicolon then pr ";";
8025 if newline then pr "\n"
8027 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8028 and generate_c_call_args ?handle ?(decl = false) style =
8030 let comma = ref false in
8032 if !comma then pr ", ";
8037 | Some handle -> pr "%s" handle; comma := true
8043 pr "%s, %s_size" n n
8046 pr "%s" (name_of_argt arg)
8048 (* For RBufferOut calls, add implicit &size parameter. *)
8050 match fst style with
8058 (* Generate the OCaml bindings interface. *)
8059 and generate_ocaml_mli () =
8060 generate_header OCamlStyle LGPLv2plus;
8063 (** For API documentation you should refer to the C API
8064 in the guestfs(3) manual page. The OCaml API uses almost
8065 exactly the same calls. *)
8068 (** A [guestfs_h] handle. *)
8070 exception Error of string
8071 (** This exception is raised when there is an error. *)
8073 exception Handle_closed of string
8074 (** This exception is raised if you use a {!Guestfs.t} handle
8075 after calling {!close} on it. The string is the name of
8078 val create : unit -> t
8079 (** Create a {!Guestfs.t} handle. *)
8081 val close : t -> unit
8082 (** Close the {!Guestfs.t} handle and free up all resources used
8085 Handles are closed by the garbage collector when they become
8086 unreferenced, but callers can call this in order to provide
8087 predictable cleanup. *)
8090 generate_ocaml_structure_decls ();
8094 fun (name, style, _, _, _, shortdesc, _) ->
8095 generate_ocaml_prototype name style;
8096 pr "(** %s *)\n" shortdesc;
8098 ) all_functions_sorted
8100 (* Generate the OCaml bindings implementation. *)
8101 and generate_ocaml_ml () =
8102 generate_header OCamlStyle LGPLv2plus;
8107 exception Error of string
8108 exception Handle_closed of string
8110 external create : unit -> t = \"ocaml_guestfs_create\"
8111 external close : t -> unit = \"ocaml_guestfs_close\"
8113 (* Give the exceptions names, so they can be raised from the C code. *)
8115 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8116 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8120 generate_ocaml_structure_decls ();
8124 fun (name, style, _, _, _, shortdesc, _) ->
8125 generate_ocaml_prototype ~is_external:true name style;
8126 ) all_functions_sorted
8128 (* Generate the OCaml bindings C implementation. *)
8129 and generate_ocaml_c () =
8130 generate_header CStyle LGPLv2plus;
8137 #include <caml/config.h>
8138 #include <caml/alloc.h>
8139 #include <caml/callback.h>
8140 #include <caml/fail.h>
8141 #include <caml/memory.h>
8142 #include <caml/mlvalues.h>
8143 #include <caml/signals.h>
8145 #include <guestfs.h>
8147 #include \"guestfs_c.h\"
8149 /* Copy a hashtable of string pairs into an assoc-list. We return
8150 * the list in reverse order, but hashtables aren't supposed to be
8153 static CAMLprim value
8154 copy_table (char * const * argv)
8157 CAMLlocal5 (rv, pairv, kv, vv, cons);
8161 for (i = 0; argv[i] != NULL; i += 2) {
8162 kv = caml_copy_string (argv[i]);
8163 vv = caml_copy_string (argv[i+1]);
8164 pairv = caml_alloc (2, 0);
8165 Store_field (pairv, 0, kv);
8166 Store_field (pairv, 1, vv);
8167 cons = caml_alloc (2, 0);
8168 Store_field (cons, 1, rv);
8170 Store_field (cons, 0, pairv);
8178 (* Struct copy functions. *)
8180 let emit_ocaml_copy_list_function typ =
8181 pr "static CAMLprim value\n";
8182 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8184 pr " CAMLparam0 ();\n";
8185 pr " CAMLlocal2 (rv, v);\n";
8186 pr " unsigned int i;\n";
8188 pr " if (%ss->len == 0)\n" typ;
8189 pr " CAMLreturn (Atom (0));\n";
8191 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8192 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8193 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8194 pr " caml_modify (&Field (rv, i), v);\n";
8196 pr " CAMLreturn (rv);\n";
8204 let has_optpercent_col =
8205 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8207 pr "static CAMLprim value\n";
8208 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8210 pr " CAMLparam0 ();\n";
8211 if has_optpercent_col then
8212 pr " CAMLlocal3 (rv, v, v2);\n"
8214 pr " CAMLlocal2 (rv, v);\n";
8216 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8221 pr " v = caml_copy_string (%s->%s);\n" typ name
8223 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8224 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8227 pr " v = caml_alloc_string (32);\n";
8228 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8229 | name, (FBytes|FInt64|FUInt64) ->
8230 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8231 | name, (FInt32|FUInt32) ->
8232 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8233 | name, FOptPercent ->
8234 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8235 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8236 pr " v = caml_alloc (1, 0);\n";
8237 pr " Store_field (v, 0, v2);\n";
8238 pr " } else /* None */\n";
8239 pr " v = Val_int (0);\n";
8241 pr " v = Val_int (%s->%s);\n" typ name
8243 pr " Store_field (rv, %d, v);\n" i
8245 pr " CAMLreturn (rv);\n";
8250 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8253 | typ, (RStructListOnly | RStructAndList) ->
8254 (* generate the function for typ *)
8255 emit_ocaml_copy_list_function typ
8256 | typ, _ -> () (* empty *)
8257 ) (rstructs_used_by all_functions);
8261 fun (name, style, _, _, _, _, _) ->
8262 pr "/* Automatically generated wrapper for function\n";
8264 generate_ocaml_prototype name style;
8269 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8271 let needs_extra_vs =
8272 match fst style with RConstOptString _ -> true | _ -> false in
8274 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8275 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8276 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8279 pr "CAMLprim value\n";
8280 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8281 List.iter (pr ", value %s") (List.tl params);
8286 | [p1; p2; p3; p4; p5] ->
8287 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8288 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8289 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8290 pr " CAMLxparam%d (%s);\n"
8291 (List.length rest) (String.concat ", " rest)
8293 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8295 if not needs_extra_vs then
8296 pr " CAMLlocal1 (rv);\n"
8298 pr " CAMLlocal3 (rv, v, v2);\n";
8301 pr " guestfs_h *g = Guestfs_val (gv);\n";
8302 pr " if (g == NULL)\n";
8303 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8309 | Device n | Dev_or_Path n
8313 pr " const char *%s = String_val (%sv);\n" n n
8315 pr " const char *%s =\n" n;
8316 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8319 pr " const char *%s = String_val (%sv);\n" n n;
8320 pr " size_t %s_size = caml_string_length (%sv);\n" n n
8321 | StringList n | DeviceList n ->
8322 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8324 pr " int %s = Bool_val (%sv);\n" n n
8326 pr " int %s = Int_val (%sv);\n" n n
8328 pr " int64_t %s = Int64_val (%sv);\n" n n
8331 match fst style with
8332 | RErr -> pr " int r;\n"; "-1"
8333 | RInt _ -> pr " int r;\n"; "-1"
8334 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8335 | RBool _ -> pr " int r;\n"; "-1"
8336 | RConstString _ | RConstOptString _ ->
8337 pr " const char *r;\n"; "NULL"
8338 | RString _ -> pr " char *r;\n"; "NULL"
8343 | RStruct (_, typ) ->
8344 pr " struct guestfs_%s *r;\n" typ; "NULL"
8345 | RStructList (_, typ) ->
8346 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8353 pr " size_t size;\n";
8357 pr " caml_enter_blocking_section ();\n";
8358 pr " r = guestfs_%s " name;
8359 generate_c_call_args ~handle:"g" style;
8361 pr " caml_leave_blocking_section ();\n";
8365 | StringList n | DeviceList n ->
8366 pr " ocaml_guestfs_free_strings (%s);\n" n;
8367 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8368 | Bool _ | Int _ | Int64 _
8369 | FileIn _ | FileOut _ | BufferIn _ -> ()
8372 pr " if (r == %s)\n" error_code;
8373 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8376 (match fst style with
8377 | RErr -> pr " rv = Val_unit;\n"
8378 | RInt _ -> pr " rv = Val_int (r);\n"
8380 pr " rv = caml_copy_int64 (r);\n"
8381 | RBool _ -> pr " rv = Val_bool (r);\n"
8383 pr " rv = caml_copy_string (r);\n"
8384 | RConstOptString _ ->
8385 pr " if (r) { /* Some string */\n";
8386 pr " v = caml_alloc (1, 0);\n";
8387 pr " v2 = caml_copy_string (r);\n";
8388 pr " Store_field (v, 0, v2);\n";
8389 pr " } else /* None */\n";
8390 pr " v = Val_int (0);\n";
8392 pr " rv = caml_copy_string (r);\n";
8395 pr " rv = caml_copy_string_array ((const char **) r);\n";
8396 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8398 | RStruct (_, typ) ->
8399 pr " rv = copy_%s (r);\n" typ;
8400 pr " guestfs_free_%s (r);\n" typ;
8401 | RStructList (_, typ) ->
8402 pr " rv = copy_%s_list (r);\n" typ;
8403 pr " guestfs_free_%s_list (r);\n" typ;
8405 pr " rv = copy_table (r);\n";
8406 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8409 pr " rv = caml_alloc_string (size);\n";
8410 pr " memcpy (String_val (rv), r, size);\n";
8413 pr " CAMLreturn (rv);\n";
8417 if List.length params > 5 then (
8418 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8419 pr "CAMLprim value ";
8420 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8421 pr "CAMLprim value\n";
8422 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8424 pr " return ocaml_guestfs_%s (argv[0]" name;
8425 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8430 ) all_functions_sorted
8432 and generate_ocaml_structure_decls () =
8435 pr "type %s = {\n" typ;
8438 | name, FString -> pr " %s : string;\n" name
8439 | name, FBuffer -> pr " %s : string;\n" name
8440 | name, FUUID -> pr " %s : string;\n" name
8441 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8442 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8443 | name, FChar -> pr " %s : char;\n" name
8444 | name, FOptPercent -> pr " %s : float option;\n" name
8450 and generate_ocaml_prototype ?(is_external = false) name style =
8451 if is_external then pr "external " else pr "val ";
8452 pr "%s : t -> " name;
8455 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8456 | BufferIn _ -> pr "string -> "
8457 | OptString _ -> pr "string option -> "
8458 | StringList _ | DeviceList _ -> pr "string array -> "
8459 | Bool _ -> pr "bool -> "
8460 | Int _ -> pr "int -> "
8461 | Int64 _ -> pr "int64 -> "
8463 (match fst style with
8464 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8465 | RInt _ -> pr "int"
8466 | RInt64 _ -> pr "int64"
8467 | RBool _ -> pr "bool"
8468 | RConstString _ -> pr "string"
8469 | RConstOptString _ -> pr "string option"
8470 | RString _ | RBufferOut _ -> pr "string"
8471 | RStringList _ -> pr "string array"
8472 | RStruct (_, typ) -> pr "%s" typ
8473 | RStructList (_, typ) -> pr "%s array" typ
8474 | RHashtable _ -> pr "(string * string) list"
8476 if is_external then (
8478 if List.length (snd style) + 1 > 5 then
8479 pr "\"ocaml_guestfs_%s_byte\" " name;
8480 pr "\"ocaml_guestfs_%s\"" name
8484 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8485 and generate_perl_xs () =
8486 generate_header CStyle LGPLv2plus;
8489 #include \"EXTERN.h\"
8493 #include <guestfs.h>
8496 #define PRId64 \"lld\"
8500 my_newSVll(long long val) {
8501 #ifdef USE_64_BIT_ALL
8502 return newSViv(val);
8506 len = snprintf(buf, 100, \"%%\" PRId64, val);
8507 return newSVpv(buf, len);
8512 #define PRIu64 \"llu\"
8516 my_newSVull(unsigned long long val) {
8517 #ifdef USE_64_BIT_ALL
8518 return newSVuv(val);
8522 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8523 return newSVpv(buf, len);
8527 /* http://www.perlmonks.org/?node_id=680842 */
8529 XS_unpack_charPtrPtr (SV *arg) {
8534 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8535 croak (\"array reference expected\");
8537 av = (AV *)SvRV (arg);
8538 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8540 croak (\"malloc failed\");
8542 for (i = 0; i <= av_len (av); i++) {
8543 SV **elem = av_fetch (av, i, 0);
8545 if (!elem || !*elem)
8546 croak (\"missing element in list\");
8548 ret[i] = SvPV_nolen (*elem);
8556 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8563 RETVAL = guestfs_create ();
8565 croak (\"could not create guestfs handle\");
8566 guestfs_set_error_handler (RETVAL, NULL, NULL);
8579 fun (name, style, _, _, _, _, _) ->
8580 (match fst style with
8581 | RErr -> pr "void\n"
8582 | RInt _ -> pr "SV *\n"
8583 | RInt64 _ -> pr "SV *\n"
8584 | RBool _ -> pr "SV *\n"
8585 | RConstString _ -> pr "SV *\n"
8586 | RConstOptString _ -> pr "SV *\n"
8587 | RString _ -> pr "SV *\n"
8588 | RBufferOut _ -> pr "SV *\n"
8590 | RStruct _ | RStructList _
8592 pr "void\n" (* all lists returned implictly on the stack *)
8594 (* Call and arguments. *)
8597 fun arg -> pr ", %s" (name_of_argt arg)
8600 pr " guestfs_h *g;\n";
8604 | Pathname n | Device n | Dev_or_Path n | String n
8605 | FileIn n | FileOut n ->
8608 pr " char *%s;\n" n;
8609 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8611 (* http://www.perlmonks.org/?node_id=554277
8612 * Note that the implicit handle argument means we have
8613 * to add 1 to the ST(x) operator.
8615 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8616 | StringList n | DeviceList n -> pr " char **%s;\n" n
8617 | Bool n -> pr " int %s;\n" n
8618 | Int n -> pr " int %s;\n" n
8619 | Int64 n -> pr " int64_t %s;\n" n
8622 let do_cleanups () =
8625 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8626 | Bool _ | Int _ | Int64 _
8627 | FileIn _ | FileOut _
8629 | StringList n | DeviceList n -> pr " free (%s);\n" n
8634 (match fst style with
8639 pr " r = guestfs_%s " name;
8640 generate_c_call_args ~handle:"g" style;
8643 pr " if (r == -1)\n";
8644 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8650 pr " %s = guestfs_%s " n name;
8651 generate_c_call_args ~handle:"g" style;
8654 pr " if (%s == -1)\n" n;
8655 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8656 pr " RETVAL = newSViv (%s);\n" n;
8661 pr " int64_t %s;\n" n;
8663 pr " %s = guestfs_%s " n name;
8664 generate_c_call_args ~handle:"g" style;
8667 pr " if (%s == -1)\n" n;
8668 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8669 pr " RETVAL = my_newSVll (%s);\n" n;
8674 pr " const char *%s;\n" n;
8676 pr " %s = guestfs_%s " n name;
8677 generate_c_call_args ~handle:"g" style;
8680 pr " if (%s == NULL)\n" n;
8681 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8682 pr " RETVAL = newSVpv (%s, 0);\n" n;
8685 | RConstOptString n ->
8687 pr " const char *%s;\n" n;
8689 pr " %s = guestfs_%s " n name;
8690 generate_c_call_args ~handle:"g" style;
8693 pr " if (%s == NULL)\n" n;
8694 pr " RETVAL = &PL_sv_undef;\n";
8696 pr " RETVAL = newSVpv (%s, 0);\n" n;
8701 pr " char *%s;\n" n;
8703 pr " %s = guestfs_%s " n name;
8704 generate_c_call_args ~handle:"g" style;
8707 pr " if (%s == NULL)\n" n;
8708 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8709 pr " RETVAL = newSVpv (%s, 0);\n" n;
8710 pr " free (%s);\n" n;
8713 | RStringList n | RHashtable n ->
8715 pr " char **%s;\n" n;
8718 pr " %s = guestfs_%s " n name;
8719 generate_c_call_args ~handle:"g" style;
8722 pr " if (%s == NULL)\n" n;
8723 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8724 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8725 pr " EXTEND (SP, n);\n";
8726 pr " for (i = 0; i < n; ++i) {\n";
8727 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8728 pr " free (%s[i]);\n" n;
8730 pr " free (%s);\n" n;
8731 | RStruct (n, typ) ->
8732 let cols = cols_of_struct typ in
8733 generate_perl_struct_code typ cols name style n do_cleanups
8734 | RStructList (n, typ) ->
8735 let cols = cols_of_struct typ in
8736 generate_perl_struct_list_code typ cols name style n do_cleanups
8739 pr " char *%s;\n" n;
8740 pr " size_t size;\n";
8742 pr " %s = guestfs_%s " n name;
8743 generate_c_call_args ~handle:"g" style;
8746 pr " if (%s == NULL)\n" n;
8747 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8748 pr " RETVAL = newSVpvn (%s, size);\n" n;
8749 pr " free (%s);\n" n;
8757 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8759 pr " struct guestfs_%s_list *%s;\n" typ n;
8763 pr " %s = guestfs_%s " n name;
8764 generate_c_call_args ~handle:"g" style;
8767 pr " if (%s == NULL)\n" n;
8768 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8769 pr " EXTEND (SP, %s->len);\n" n;
8770 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8771 pr " hv = newHV ();\n";
8775 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8776 name (String.length name) n name
8778 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8779 name (String.length name) n name
8781 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8782 name (String.length name) n name n name
8783 | name, (FBytes|FUInt64) ->
8784 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8785 name (String.length name) n name
8787 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8788 name (String.length name) n name
8789 | name, (FInt32|FUInt32) ->
8790 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8791 name (String.length name) n name
8793 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8794 name (String.length name) n name
8795 | name, FOptPercent ->
8796 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8797 name (String.length name) n name
8799 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8801 pr " guestfs_free_%s_list (%s);\n" typ n
8803 and generate_perl_struct_code typ cols name style n do_cleanups =
8805 pr " struct guestfs_%s *%s;\n" typ n;
8807 pr " %s = guestfs_%s " n name;
8808 generate_c_call_args ~handle:"g" style;
8811 pr " if (%s == NULL)\n" n;
8812 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8813 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8815 fun ((name, _) as col) ->
8816 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8820 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8823 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8826 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8828 | name, (FBytes|FUInt64) ->
8829 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8832 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8834 | name, (FInt32|FUInt32) ->
8835 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8838 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8840 | name, FOptPercent ->
8841 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8844 pr " free (%s);\n" n
8846 (* Generate Sys/Guestfs.pm. *)
8847 and generate_perl_pm () =
8848 generate_header HashStyle LGPLv2plus;
8855 Sys::Guestfs - Perl bindings for libguestfs
8861 my $h = Sys::Guestfs->new ();
8862 $h->add_drive ('guest.img');
8864 $h->mount ('/dev/sda1', '/');
8865 $h->touch ('/hello');
8870 The C<Sys::Guestfs> module provides a Perl XS binding to the
8871 libguestfs API for examining and modifying virtual machine
8874 Amongst the things this is good for: making batch configuration
8875 changes to guests, getting disk used/free statistics (see also:
8876 virt-df), migrating between virtualization systems (see also:
8877 virt-p2v), performing partial backups, performing partial guest
8878 clones, cloning guests and changing registry/UUID/hostname info, and
8881 Libguestfs uses Linux kernel and qemu code, and can access any type of
8882 guest filesystem that Linux and qemu can, including but not limited
8883 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8884 schemes, qcow, qcow2, vmdk.
8886 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8887 LVs, what filesystem is in each LV, etc.). It can also run commands
8888 in the context of the guest. Also you can access filesystems over
8891 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8892 functions for using libguestfs from Perl, including integration
8897 All errors turn into calls to C<croak> (see L<Carp(3)>).
8905 package Sys::Guestfs;
8910 # This version number changes whenever a new function
8911 # is added to the libguestfs API. It is not directly
8912 # related to the libguestfs version number.
8913 use vars qw($VERSION);
8917 XSLoader::load ('Sys::Guestfs');
8919 =item $h = Sys::Guestfs->new ();
8921 Create a new guestfs handle.
8927 my $class = ref ($proto) || $proto;
8929 my $self = Sys::Guestfs::_create ();
8930 bless $self, $class;
8936 (* Actions. We only need to print documentation for these as
8937 * they are pulled in from the XS code automatically.
8940 fun (name, style, _, flags, _, _, longdesc) ->
8941 if not (List.mem NotInDocs flags) then (
8942 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8944 generate_perl_prototype name style;
8946 pr "%s\n\n" longdesc;
8947 if List.mem ProtocolLimitWarning flags then
8948 pr "%s\n\n" protocol_limit_warning;
8949 if List.mem DangerWillRobinson flags then
8950 pr "%s\n\n" danger_will_robinson;
8951 match deprecation_notice flags with
8953 | Some txt -> pr "%s\n\n" txt
8955 ) all_functions_sorted;
8967 Copyright (C) %s Red Hat Inc.
8971 Please see the file COPYING.LIB for the full license.
8977 L<http://libguestfs.org>,
8978 L<Sys::Guestfs::Lib(3)>.
8983 and generate_perl_prototype name style =
8984 (match fst style with
8992 | RBufferOut n -> pr "$%s = " n
8994 | RHashtable n -> pr "%%%s = " n
8996 | RStructList (n,_) -> pr "@%s = " n
8999 let comma = ref false in
9002 if !comma then pr ", ";
9005 | Pathname n | Device n | Dev_or_Path n | String n
9006 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9009 | StringList n | DeviceList n ->
9014 (* Generate Python C module. *)
9015 and generate_python_c () =
9016 generate_header CStyle LGPLv2plus;
9019 #define PY_SSIZE_T_CLEAN 1
9026 #include \"guestfs.h\"
9034 get_handle (PyObject *obj)
9037 assert (obj != Py_None);
9038 return ((Pyguestfs_Object *) obj)->g;
9042 put_handle (guestfs_h *g)
9046 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9049 /* This list should be freed (but not the strings) after use. */
9051 get_string_list (PyObject *obj)
9058 if (!PyList_Check (obj)) {
9059 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9063 len = PyList_Size (obj);
9064 r = malloc (sizeof (char *) * (len+1));
9066 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9070 for (i = 0; i < len; ++i)
9071 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9078 put_string_list (char * const * const argv)
9083 for (argc = 0; argv[argc] != NULL; ++argc)
9086 list = PyList_New (argc);
9087 for (i = 0; i < argc; ++i)
9088 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9094 put_table (char * const * const argv)
9096 PyObject *list, *item;
9099 for (argc = 0; argv[argc] != NULL; ++argc)
9102 list = PyList_New (argc >> 1);
9103 for (i = 0; i < argc; i += 2) {
9104 item = PyTuple_New (2);
9105 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9106 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9107 PyList_SetItem (list, i >> 1, item);
9114 free_strings (char **argv)
9118 for (argc = 0; argv[argc] != NULL; ++argc)
9124 py_guestfs_create (PyObject *self, PyObject *args)
9128 g = guestfs_create ();
9130 PyErr_SetString (PyExc_RuntimeError,
9131 \"guestfs.create: failed to allocate handle\");
9134 guestfs_set_error_handler (g, NULL, NULL);
9135 return put_handle (g);
9139 py_guestfs_close (PyObject *self, PyObject *args)
9144 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9146 g = get_handle (py_g);
9150 Py_INCREF (Py_None);
9156 let emit_put_list_function typ =
9157 pr "static PyObject *\n";
9158 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9160 pr " PyObject *list;\n";
9163 pr " list = PyList_New (%ss->len);\n" typ;
9164 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9165 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9166 pr " return list;\n";
9171 (* Structures, turned into Python dictionaries. *)
9174 pr "static PyObject *\n";
9175 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9177 pr " PyObject *dict;\n";
9179 pr " dict = PyDict_New ();\n";
9183 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9184 pr " PyString_FromString (%s->%s));\n"
9187 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9188 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9191 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9192 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9194 | name, (FBytes|FUInt64) ->
9195 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9196 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9199 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9200 pr " PyLong_FromLongLong (%s->%s));\n"
9203 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9204 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9207 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9208 pr " PyLong_FromLong (%s->%s));\n"
9210 | name, FOptPercent ->
9211 pr " if (%s->%s >= 0)\n" typ name;
9212 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9213 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9216 pr " Py_INCREF (Py_None);\n";
9217 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9220 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9221 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9223 pr " return dict;\n";
9229 (* Emit a put_TYPE_list function definition only if that function is used. *)
9232 | typ, (RStructListOnly | RStructAndList) ->
9233 (* generate the function for typ *)
9234 emit_put_list_function typ
9235 | typ, _ -> () (* empty *)
9236 ) (rstructs_used_by all_functions);
9238 (* Python wrapper functions. *)
9240 fun (name, style, _, _, _, _, _) ->
9241 pr "static PyObject *\n";
9242 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9245 pr " PyObject *py_g;\n";
9246 pr " guestfs_h *g;\n";
9247 pr " PyObject *py_r;\n";
9250 match fst style with
9251 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9252 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9253 | RConstString _ | RConstOptString _ ->
9254 pr " const char *r;\n"; "NULL"
9255 | RString _ -> pr " char *r;\n"; "NULL"
9256 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9257 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9258 | RStructList (_, typ) ->
9259 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9262 pr " size_t size;\n";
9267 | Pathname n | Device n | Dev_or_Path n | String n
9268 | FileIn n | FileOut n ->
9269 pr " const char *%s;\n" n
9270 | OptString n -> pr " const char *%s;\n" n
9272 pr " const char *%s;\n" n;
9273 pr " Py_ssize_t %s_size;\n" n
9274 | StringList n | DeviceList n ->
9275 pr " PyObject *py_%s;\n" n;
9276 pr " char **%s;\n" n
9277 | Bool n -> pr " int %s;\n" n
9278 | Int n -> pr " int %s;\n" n
9279 | Int64 n -> pr " long long %s;\n" n
9284 (* Convert the parameters. *)
9285 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9288 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9289 | OptString _ -> pr "z"
9290 | StringList _ | DeviceList _ -> pr "O"
9291 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9293 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9294 * emulate C's int/long/long long in Python?
9296 | BufferIn _ -> pr "s#"
9298 pr ":guestfs_%s\",\n" name;
9302 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9303 | OptString n -> pr ", &%s" n
9304 | StringList n | DeviceList n -> pr ", &py_%s" n
9305 | Bool n -> pr ", &%s" n
9306 | Int n -> pr ", &%s" n
9307 | Int64 n -> pr ", &%s" n
9308 | BufferIn n -> pr ", &%s, &%s_size" n n
9312 pr " return NULL;\n";
9314 pr " g = get_handle (py_g);\n";
9317 | Pathname _ | Device _ | Dev_or_Path _ | String _
9318 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9320 | StringList n | DeviceList n ->
9321 pr " %s = get_string_list (py_%s);\n" n n;
9322 pr " if (!%s) return NULL;\n" n
9327 pr " r = guestfs_%s " name;
9328 generate_c_call_args ~handle:"g" style;
9333 | Pathname _ | Device _ | Dev_or_Path _ | String _
9334 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9336 | StringList n | DeviceList n ->
9337 pr " free (%s);\n" n
9340 pr " if (r == %s) {\n" error_code;
9341 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9342 pr " return NULL;\n";
9346 (match fst style with
9348 pr " Py_INCREF (Py_None);\n";
9349 pr " py_r = Py_None;\n"
9351 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9352 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9353 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9354 | RConstOptString _ ->
9356 pr " py_r = PyString_FromString (r);\n";
9358 pr " Py_INCREF (Py_None);\n";
9359 pr " py_r = Py_None;\n";
9362 pr " py_r = PyString_FromString (r);\n";
9365 pr " py_r = put_string_list (r);\n";
9366 pr " free_strings (r);\n"
9367 | RStruct (_, typ) ->
9368 pr " py_r = put_%s (r);\n" typ;
9369 pr " guestfs_free_%s (r);\n" typ
9370 | RStructList (_, typ) ->
9371 pr " py_r = put_%s_list (r);\n" typ;
9372 pr " guestfs_free_%s_list (r);\n" typ
9374 pr " py_r = put_table (r);\n";
9375 pr " free_strings (r);\n"
9377 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9381 pr " return py_r;\n";
9386 (* Table of functions. *)
9387 pr "static PyMethodDef methods[] = {\n";
9388 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9389 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9391 fun (name, _, _, _, _, _, _) ->
9392 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9395 pr " { NULL, NULL, 0, NULL }\n";
9399 (* Init function. *)
9402 initlibguestfsmod (void)
9404 static int initialized = 0;
9406 if (initialized) return;
9407 Py_InitModule ((char *) \"libguestfsmod\", methods);
9412 (* Generate Python module. *)
9413 and generate_python_py () =
9414 generate_header HashStyle LGPLv2plus;
9417 u\"\"\"Python bindings for libguestfs
9420 g = guestfs.GuestFS ()
9421 g.add_drive (\"guest.img\")
9423 parts = g.list_partitions ()
9425 The guestfs module provides a Python binding to the libguestfs API
9426 for examining and modifying virtual machine disk images.
9428 Amongst the things this is good for: making batch configuration
9429 changes to guests, getting disk used/free statistics (see also:
9430 virt-df), migrating between virtualization systems (see also:
9431 virt-p2v), performing partial backups, performing partial guest
9432 clones, cloning guests and changing registry/UUID/hostname info, and
9435 Libguestfs uses Linux kernel and qemu code, and can access any type of
9436 guest filesystem that Linux and qemu can, including but not limited
9437 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9438 schemes, qcow, qcow2, vmdk.
9440 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9441 LVs, what filesystem is in each LV, etc.). It can also run commands
9442 in the context of the guest. Also you can access filesystems over
9445 Errors which happen while using the API are turned into Python
9446 RuntimeError exceptions.
9448 To create a guestfs handle you usually have to perform the following
9451 # Create the handle, call add_drive at least once, and possibly
9452 # several times if the guest has multiple block devices:
9453 g = guestfs.GuestFS ()
9454 g.add_drive (\"guest.img\")
9456 # Launch the qemu subprocess and wait for it to become ready:
9459 # Now you can issue commands, for example:
9464 import libguestfsmod
9467 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9469 def __init__ (self):
9470 \"\"\"Create a new libguestfs handle.\"\"\"
9471 self._o = libguestfsmod.create ()
9474 libguestfsmod.close (self._o)
9479 fun (name, style, _, flags, _, _, longdesc) ->
9481 generate_py_call_args ~handle:"self" (snd style);
9484 if not (List.mem NotInDocs flags) then (
9485 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9487 match fst style with
9488 | RErr | RInt _ | RInt64 _ | RBool _
9489 | RConstOptString _ | RConstString _
9490 | RString _ | RBufferOut _ -> doc
9492 doc ^ "\n\nThis function returns a list of strings."
9493 | RStruct (_, typ) ->
9494 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9495 | RStructList (_, typ) ->
9496 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9498 doc ^ "\n\nThis function returns a dictionary." in
9500 if List.mem ProtocolLimitWarning flags then
9501 doc ^ "\n\n" ^ protocol_limit_warning
9504 if List.mem DangerWillRobinson flags then
9505 doc ^ "\n\n" ^ danger_will_robinson
9508 match deprecation_notice flags with
9510 | Some txt -> doc ^ "\n\n" ^ txt in
9511 let doc = pod2text ~width:60 name doc in
9512 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9513 let doc = String.concat "\n " doc in
9514 pr " u\"\"\"%s\"\"\"\n" doc;
9516 pr " return libguestfsmod.%s " name;
9517 generate_py_call_args ~handle:"self._o" (snd style);
9522 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9523 and generate_py_call_args ~handle args =
9525 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9528 (* Useful if you need the longdesc POD text as plain text. Returns a
9531 * Because this is very slow (the slowest part of autogeneration),
9532 * we memoize the results.
9534 and pod2text ~width name longdesc =
9535 let key = width, name, longdesc in
9536 try Hashtbl.find pod2text_memo key
9538 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9539 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9541 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9542 let chan = open_process_in cmd in
9543 let lines = ref [] in
9545 let line = input_line chan in
9546 if i = 1 then (* discard the first line of output *)
9549 let line = triml line in
9550 lines := line :: !lines;
9553 let lines = try loop 1 with End_of_file -> List.rev !lines in
9555 (match close_process_in chan with
9558 failwithf "pod2text: process exited with non-zero status (%d)" i
9559 | WSIGNALED i | WSTOPPED i ->
9560 failwithf "pod2text: process signalled or stopped by signal %d" i
9562 Hashtbl.add pod2text_memo key lines;
9563 pod2text_memo_updated ();
9566 (* Generate ruby bindings. *)
9567 and generate_ruby_c () =
9568 generate_header CStyle LGPLv2plus;
9576 #include \"guestfs.h\"
9578 #include \"extconf.h\"
9580 /* For Ruby < 1.9 */
9582 #define RARRAY_LEN(r) (RARRAY((r))->len)
9585 static VALUE m_guestfs; /* guestfs module */
9586 static VALUE c_guestfs; /* guestfs_h handle */
9587 static VALUE e_Error; /* used for all errors */
9589 static void ruby_guestfs_free (void *p)
9592 guestfs_close ((guestfs_h *) p);
9595 static VALUE ruby_guestfs_create (VALUE m)
9599 g = guestfs_create ();
9601 rb_raise (e_Error, \"failed to create guestfs handle\");
9603 /* Don't print error messages to stderr by default. */
9604 guestfs_set_error_handler (g, NULL, NULL);
9606 /* Wrap it, and make sure the close function is called when the
9609 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9612 static VALUE ruby_guestfs_close (VALUE gv)
9615 Data_Get_Struct (gv, guestfs_h, g);
9617 ruby_guestfs_free (g);
9618 DATA_PTR (gv) = NULL;
9626 fun (name, style, _, _, _, _, _) ->
9627 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9628 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9631 pr " guestfs_h *g;\n";
9632 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9634 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9640 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9641 pr " Check_Type (%sv, T_STRING);\n" n;
9642 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9644 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9645 pr " \"%s\", \"%s\");\n" n name
9647 pr " Check_Type (%sv, T_STRING);\n" n;
9648 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
9650 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9651 pr " \"%s\", \"%s\");\n" n name;
9652 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
9654 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9655 | StringList n | DeviceList n ->
9656 pr " char **%s;\n" n;
9657 pr " Check_Type (%sv, T_ARRAY);\n" n;
9659 pr " int i, len;\n";
9660 pr " len = RARRAY_LEN (%sv);\n" n;
9661 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9663 pr " for (i = 0; i < len; ++i) {\n";
9664 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9665 pr " %s[i] = StringValueCStr (v);\n" n;
9667 pr " %s[len] = NULL;\n" n;
9670 pr " int %s = RTEST (%sv);\n" n n
9672 pr " int %s = NUM2INT (%sv);\n" n n
9674 pr " long long %s = NUM2LL (%sv);\n" n n
9679 match fst style with
9680 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9681 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9682 | RConstString _ | RConstOptString _ ->
9683 pr " const char *r;\n"; "NULL"
9684 | RString _ -> pr " char *r;\n"; "NULL"
9685 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9686 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9687 | RStructList (_, typ) ->
9688 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9691 pr " size_t size;\n";
9695 pr " r = guestfs_%s " name;
9696 generate_c_call_args ~handle:"g" style;
9701 | Pathname _ | Device _ | Dev_or_Path _ | String _
9702 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9704 | StringList n | DeviceList n ->
9705 pr " free (%s);\n" n
9708 pr " if (r == %s)\n" error_code;
9709 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9712 (match fst style with
9714 pr " return Qnil;\n"
9715 | RInt _ | RBool _ ->
9716 pr " return INT2NUM (r);\n"
9718 pr " return ULL2NUM (r);\n"
9720 pr " return rb_str_new2 (r);\n";
9721 | RConstOptString _ ->
9723 pr " return rb_str_new2 (r);\n";
9725 pr " return Qnil;\n";
9727 pr " VALUE rv = rb_str_new2 (r);\n";
9731 pr " int i, len = 0;\n";
9732 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9733 pr " VALUE rv = rb_ary_new2 (len);\n";
9734 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9735 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9736 pr " free (r[i]);\n";
9740 | RStruct (_, typ) ->
9741 let cols = cols_of_struct typ in
9742 generate_ruby_struct_code typ cols
9743 | RStructList (_, typ) ->
9744 let cols = cols_of_struct typ in
9745 generate_ruby_struct_list_code typ cols
9747 pr " VALUE rv = rb_hash_new ();\n";
9749 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9750 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9751 pr " free (r[i]);\n";
9752 pr " free (r[i+1]);\n";
9757 pr " VALUE rv = rb_str_new (r, size);\n";
9767 /* Initialize the module. */
9768 void Init__guestfs ()
9770 m_guestfs = rb_define_module (\"Guestfs\");
9771 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9772 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9774 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9775 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9778 (* Define the rest of the methods. *)
9780 fun (name, style, _, _, _, _, _) ->
9781 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9782 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9787 (* Ruby code to return a struct. *)
9788 and generate_ruby_struct_code typ cols =
9789 pr " VALUE rv = rb_hash_new ();\n";
9793 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9795 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9797 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9798 | name, (FBytes|FUInt64) ->
9799 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9801 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9803 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9805 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9806 | name, FOptPercent ->
9807 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9808 | name, FChar -> (* XXX wrong? *)
9809 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9811 pr " guestfs_free_%s (r);\n" typ;
9814 (* Ruby code to return a struct list. *)
9815 and generate_ruby_struct_list_code typ cols =
9816 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9818 pr " for (i = 0; i < r->len; ++i) {\n";
9819 pr " VALUE hv = rb_hash_new ();\n";
9823 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9825 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
9827 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9828 | name, (FBytes|FUInt64) ->
9829 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9831 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9833 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9835 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9836 | name, FOptPercent ->
9837 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9838 | name, FChar -> (* XXX wrong? *)
9839 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9841 pr " rb_ary_push (rv, hv);\n";
9843 pr " guestfs_free_%s_list (r);\n" typ;
9846 (* Generate Java bindings GuestFS.java file. *)
9847 and generate_java_java () =
9848 generate_header CStyle LGPLv2plus;
9851 package com.redhat.et.libguestfs;
9853 import java.util.HashMap;
9854 import com.redhat.et.libguestfs.LibGuestFSException;
9855 import com.redhat.et.libguestfs.PV;
9856 import com.redhat.et.libguestfs.VG;
9857 import com.redhat.et.libguestfs.LV;
9858 import com.redhat.et.libguestfs.Stat;
9859 import com.redhat.et.libguestfs.StatVFS;
9860 import com.redhat.et.libguestfs.IntBool;
9861 import com.redhat.et.libguestfs.Dirent;
9864 * The GuestFS object is a libguestfs handle.
9868 public class GuestFS {
9869 // Load the native code.
9871 System.loadLibrary (\"guestfs_jni\");
9875 * The native guestfs_h pointer.
9880 * Create a libguestfs handle.
9882 * @throws LibGuestFSException
9884 public GuestFS () throws LibGuestFSException
9888 private native long _create () throws LibGuestFSException;
9891 * Close a libguestfs handle.
9893 * You can also leave handles to be collected by the garbage
9894 * collector, but this method ensures that the resources used
9895 * by the handle are freed up immediately. If you call any
9896 * other methods after closing the handle, you will get an
9899 * @throws LibGuestFSException
9901 public void close () throws LibGuestFSException
9907 private native void _close (long g) throws LibGuestFSException;
9909 public void finalize () throws LibGuestFSException
9917 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9918 if not (List.mem NotInDocs flags); then (
9919 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9921 if List.mem ProtocolLimitWarning flags then
9922 doc ^ "\n\n" ^ protocol_limit_warning
9925 if List.mem DangerWillRobinson flags then
9926 doc ^ "\n\n" ^ danger_will_robinson
9929 match deprecation_notice flags with
9931 | Some txt -> doc ^ "\n\n" ^ txt in
9932 let doc = pod2text ~width:60 name doc in
9933 let doc = List.map ( (* RHBZ#501883 *)
9936 | nonempty -> nonempty
9938 let doc = String.concat "\n * " doc in
9941 pr " * %s\n" shortdesc;
9944 pr " * @throws LibGuestFSException\n";
9948 generate_java_prototype ~public:true ~semicolon:false name style;
9951 pr " if (g == 0)\n";
9952 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9955 if fst style <> RErr then pr "return ";
9957 generate_java_call_args ~handle:"g" (snd style);
9961 generate_java_prototype ~privat:true ~native:true name style;
9968 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9969 and generate_java_call_args ~handle args =
9971 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9974 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9975 ?(semicolon=true) name style =
9976 if privat then pr "private ";
9977 if public then pr "public ";
9978 if native then pr "native ";
9981 (match fst style with
9982 | RErr -> pr "void ";
9983 | RInt _ -> pr "int ";
9984 | RInt64 _ -> pr "long ";
9985 | RBool _ -> pr "boolean ";
9986 | RConstString _ | RConstOptString _ | RString _
9987 | RBufferOut _ -> pr "String ";
9988 | RStringList _ -> pr "String[] ";
9989 | RStruct (_, typ) ->
9990 let name = java_name_of_struct typ in
9992 | RStructList (_, typ) ->
9993 let name = java_name_of_struct typ in
9995 | RHashtable _ -> pr "HashMap<String,String> ";
9998 if native then pr "_%s " name else pr "%s " name;
10000 let needs_comma = ref false in
10003 needs_comma := true
10009 if !needs_comma then pr ", ";
10010 needs_comma := true;
10014 | Device n | Dev_or_Path n
10022 | StringList n | DeviceList n ->
10033 pr " throws LibGuestFSException";
10034 if semicolon then pr ";"
10036 and generate_java_struct jtyp cols () =
10037 generate_header CStyle LGPLv2plus;
10040 package com.redhat.et.libguestfs;
10043 * Libguestfs %s structure.
10055 | name, FBuffer -> pr " public String %s;\n" name
10056 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10057 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10058 | name, FChar -> pr " public char %s;\n" name
10059 | name, FOptPercent ->
10060 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10061 pr " public float %s;\n" name
10066 and generate_java_c () =
10067 generate_header CStyle LGPLv2plus;
10071 #include <stdlib.h>
10072 #include <string.h>
10074 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10075 #include \"guestfs.h\"
10077 /* Note that this function returns. The exception is not thrown
10078 * until after the wrapper function returns.
10081 throw_exception (JNIEnv *env, const char *msg)
10084 cl = (*env)->FindClass (env,
10085 \"com/redhat/et/libguestfs/LibGuestFSException\");
10086 (*env)->ThrowNew (env, cl, msg);
10089 JNIEXPORT jlong JNICALL
10090 Java_com_redhat_et_libguestfs_GuestFS__1create
10091 (JNIEnv *env, jobject obj)
10095 g = guestfs_create ();
10097 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10100 guestfs_set_error_handler (g, NULL, NULL);
10101 return (jlong) (long) g;
10104 JNIEXPORT void JNICALL
10105 Java_com_redhat_et_libguestfs_GuestFS__1close
10106 (JNIEnv *env, jobject obj, jlong jg)
10108 guestfs_h *g = (guestfs_h *) (long) jg;
10115 fun (name, style, _, _, _, _, _) ->
10117 (match fst style with
10118 | RErr -> pr "void ";
10119 | RInt _ -> pr "jint ";
10120 | RInt64 _ -> pr "jlong ";
10121 | RBool _ -> pr "jboolean ";
10122 | RConstString _ | RConstOptString _ | RString _
10123 | RBufferOut _ -> pr "jstring ";
10124 | RStruct _ | RHashtable _ ->
10126 | RStringList _ | RStructList _ ->
10127 pr "jobjectArray ";
10130 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10131 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10133 pr " (JNIEnv *env, jobject obj, jlong jg";
10137 | Device n | Dev_or_Path n
10142 pr ", jstring j%s" n
10144 pr ", jbyteArray j%s" n
10145 | StringList n | DeviceList n ->
10146 pr ", jobjectArray j%s" n
10148 pr ", jboolean j%s" n
10156 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10157 let error_code, no_ret =
10158 match fst style with
10159 | RErr -> pr " int r;\n"; "-1", ""
10161 | RInt _ -> pr " int r;\n"; "-1", "0"
10162 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10163 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10164 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10166 pr " jstring jr;\n";
10167 pr " char *r;\n"; "NULL", "NULL"
10169 pr " jobjectArray jr;\n";
10170 pr " int r_len;\n";
10171 pr " jclass cl;\n";
10172 pr " jstring jstr;\n";
10173 pr " char **r;\n"; "NULL", "NULL"
10174 | RStruct (_, typ) ->
10175 pr " jobject jr;\n";
10176 pr " jclass cl;\n";
10177 pr " jfieldID fl;\n";
10178 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10179 | RStructList (_, typ) ->
10180 pr " jobjectArray jr;\n";
10181 pr " jclass cl;\n";
10182 pr " jfieldID fl;\n";
10183 pr " jobject jfl;\n";
10184 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10185 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10187 pr " jstring jr;\n";
10189 pr " size_t size;\n";
10194 | Device n | Dev_or_Path n
10199 pr " const char *%s;\n" n
10201 pr " jbyte *%s;\n" n;
10202 pr " size_t %s_size;\n" n
10203 | StringList n | DeviceList n ->
10204 pr " int %s_len;\n" n;
10205 pr " const char **%s;\n" n
10210 pr " int64_t %s;\n" n
10214 (match fst style with
10215 | RStringList _ | RStructList _ -> true
10216 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10217 | RConstOptString _
10218 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10219 List.exists (function
10220 | StringList _ -> true
10221 | DeviceList _ -> true
10222 | _ -> false) (snd style) in
10228 (* Get the parameters. *)
10232 | Device n | Dev_or_Path n
10236 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10238 (* This is completely undocumented, but Java null becomes
10239 * a NULL parameter.
10241 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10243 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10244 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10245 | StringList n | DeviceList n ->
10246 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10247 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10248 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10249 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10251 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10253 pr " %s[%s_len] = NULL;\n" n n;
10257 pr " %s = j%s;\n" n n
10260 (* Make the call. *)
10261 pr " r = guestfs_%s " name;
10262 generate_c_call_args ~handle:"g" style;
10265 (* Release the parameters. *)
10269 | Device n | Dev_or_Path n
10273 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10275 pr " if (j%s)\n" n;
10276 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10278 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10279 | StringList n | DeviceList n ->
10280 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10281 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10283 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10285 pr " free (%s);\n" n
10291 (* Check for errors. *)
10292 pr " if (r == %s) {\n" error_code;
10293 pr " throw_exception (env, guestfs_last_error (g));\n";
10294 pr " return %s;\n" no_ret;
10297 (* Return value. *)
10298 (match fst style with
10300 | RInt _ -> pr " return (jint) r;\n"
10301 | RBool _ -> pr " return (jboolean) r;\n"
10302 | RInt64 _ -> pr " return (jlong) r;\n"
10303 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10304 | RConstOptString _ ->
10305 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10307 pr " jr = (*env)->NewStringUTF (env, r);\n";
10311 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10312 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10313 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10314 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10315 pr " for (i = 0; i < r_len; ++i) {\n";
10316 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10317 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10318 pr " free (r[i]);\n";
10322 | RStruct (_, typ) ->
10323 let jtyp = java_name_of_struct typ in
10324 let cols = cols_of_struct typ in
10325 generate_java_struct_return typ jtyp cols
10326 | RStructList (_, typ) ->
10327 let jtyp = java_name_of_struct typ in
10328 let cols = cols_of_struct typ in
10329 generate_java_struct_list_return typ jtyp cols
10332 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10333 pr " return NULL;\n"
10335 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10344 and generate_java_struct_return typ jtyp cols =
10345 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10346 pr " jr = (*env)->AllocObject (env, cl);\n";
10350 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10351 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10354 pr " char s[33];\n";
10355 pr " memcpy (s, r->%s, 32);\n" name;
10356 pr " s[32] = 0;\n";
10357 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10358 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10362 pr " int len = r->%s_len;\n" name;
10363 pr " char s[len+1];\n";
10364 pr " memcpy (s, r->%s, len);\n" name;
10365 pr " s[len] = 0;\n";
10366 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10367 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10369 | name, (FBytes|FUInt64|FInt64) ->
10370 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10371 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10372 | name, (FUInt32|FInt32) ->
10373 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10374 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10375 | name, FOptPercent ->
10376 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10377 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10379 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10380 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10385 and generate_java_struct_list_return typ jtyp cols =
10386 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10387 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10388 pr " for (i = 0; i < r->len; ++i) {\n";
10389 pr " jfl = (*env)->AllocObject (env, cl);\n";
10393 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10394 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10397 pr " char s[33];\n";
10398 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10399 pr " s[32] = 0;\n";
10400 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10401 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10405 pr " int len = r->val[i].%s_len;\n" name;
10406 pr " char s[len+1];\n";
10407 pr " memcpy (s, r->val[i].%s, len);\n" name;
10408 pr " s[len] = 0;\n";
10409 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10410 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10412 | name, (FBytes|FUInt64|FInt64) ->
10413 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10414 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10415 | name, (FUInt32|FInt32) ->
10416 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10417 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10418 | name, FOptPercent ->
10419 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10420 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10422 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10423 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10425 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10427 pr " guestfs_free_%s_list (r);\n" typ;
10430 and generate_java_makefile_inc () =
10431 generate_header HashStyle GPLv2plus;
10433 pr "java_built_sources = \\\n";
10436 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10438 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10440 and generate_haskell_hs () =
10441 generate_header HaskellStyle LGPLv2plus;
10443 (* XXX We only know how to generate partial FFI for Haskell
10444 * at the moment. Please help out!
10446 let can_generate style =
10450 | RInt64 _, _ -> true
10452 | RConstString _, _
10453 | RConstOptString _, _
10459 | RBufferOut _, _ -> false in
10462 {-# INCLUDE <guestfs.h> #-}
10463 {-# LANGUAGE ForeignFunctionInterface #-}
10468 (* List out the names of the actions we want to export. *)
10470 fun (name, style, _, _, _, _, _) ->
10471 if can_generate style then pr ",\n %s" name
10477 -- Unfortunately some symbols duplicate ones already present
10478 -- in Prelude. We don't know which, so we hard-code a list
10480 import Prelude hiding (truncate)
10484 import Foreign.C.Types
10486 import Control.Exception
10487 import Data.Typeable
10489 data GuestfsS = GuestfsS -- represents the opaque C struct
10490 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10491 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10493 -- XXX define properly later XXX
10497 data IntBool = IntBool
10499 data StatVFS = StatVFS
10500 data Hashtable = Hashtable
10502 foreign import ccall unsafe \"guestfs_create\" c_create
10504 foreign import ccall unsafe \"&guestfs_close\" c_close
10505 :: FunPtr (GuestfsP -> IO ())
10506 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10507 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10509 create :: IO GuestfsH
10512 c_set_error_handler p nullPtr nullPtr
10513 h <- newForeignPtr c_close p
10516 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10517 :: GuestfsP -> IO CString
10519 -- last_error :: GuestfsH -> IO (Maybe String)
10520 -- last_error h = do
10521 -- str <- withForeignPtr h (\\p -> c_last_error p)
10522 -- maybePeek peekCString str
10524 last_error :: GuestfsH -> IO (String)
10526 str <- withForeignPtr h (\\p -> c_last_error p)
10527 if (str == nullPtr)
10528 then return \"no error\"
10529 else peekCString str
10533 (* Generate wrappers for each foreign function. *)
10535 fun (name, style, _, _, _, _, _) ->
10536 if can_generate style then (
10537 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10539 generate_haskell_prototype ~handle:"GuestfsP" style;
10543 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10545 pr "%s %s = do\n" name
10546 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10548 (* Convert pointer arguments using with* functions. *)
10553 | Pathname n | Device n | Dev_or_Path n | String n ->
10554 pr "withCString %s $ \\%s -> " n n
10556 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10557 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10558 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10559 | Bool _ | Int _ | Int64 _ -> ()
10561 (* Convert integer arguments. *)
10565 | Bool n -> sprintf "(fromBool %s)" n
10566 | Int n -> sprintf "(fromIntegral %s)" n
10567 | Int64 n -> sprintf "(fromIntegral %s)" n
10568 | FileIn n | FileOut n
10569 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10570 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10572 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10573 (String.concat " " ("p" :: args));
10574 (match fst style with
10575 | RErr | RInt _ | RInt64 _ | RBool _ ->
10576 pr " if (r == -1)\n";
10578 pr " err <- last_error h\n";
10580 | RConstString _ | RConstOptString _ | RString _
10581 | RStringList _ | RStruct _
10582 | RStructList _ | RHashtable _ | RBufferOut _ ->
10583 pr " if (r == nullPtr)\n";
10585 pr " err <- last_error h\n";
10588 (match fst style with
10590 pr " else return ()\n"
10592 pr " else return (fromIntegral r)\n"
10594 pr " else return (fromIntegral r)\n"
10596 pr " else return (toBool r)\n"
10598 | RConstOptString _
10605 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10611 and generate_haskell_prototype ~handle ?(hs = false) style =
10612 pr "%s -> " handle;
10613 let string = if hs then "String" else "CString" in
10614 let int = if hs then "Int" else "CInt" in
10615 let bool = if hs then "Bool" else "CInt" in
10616 let int64 = if hs then "Integer" else "Int64" in
10620 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10622 if hs then pr "String"
10623 else pr "CString -> CInt"
10624 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10625 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10626 | Bool _ -> pr "%s" bool
10627 | Int _ -> pr "%s" int
10628 | Int64 _ -> pr "%s" int
10629 | FileIn _ -> pr "%s" string
10630 | FileOut _ -> pr "%s" string
10635 (match fst style with
10636 | RErr -> if not hs then pr "CInt"
10637 | RInt _ -> pr "%s" int
10638 | RInt64 _ -> pr "%s" int64
10639 | RBool _ -> pr "%s" bool
10640 | RConstString _ -> pr "%s" string
10641 | RConstOptString _ -> pr "Maybe %s" string
10642 | RString _ -> pr "%s" string
10643 | RStringList _ -> pr "[%s]" string
10644 | RStruct (_, typ) ->
10645 let name = java_name_of_struct typ in
10647 | RStructList (_, typ) ->
10648 let name = java_name_of_struct typ in
10650 | RHashtable _ -> pr "Hashtable"
10651 | RBufferOut _ -> pr "%s" string
10655 and generate_csharp () =
10656 generate_header CPlusPlusStyle LGPLv2plus;
10658 (* XXX Make this configurable by the C# assembly users. *)
10659 let library = "libguestfs.so.0" in
10662 // These C# bindings are highly experimental at present.
10664 // Firstly they only work on Linux (ie. Mono). In order to get them
10665 // to work on Windows (ie. .Net) you would need to port the library
10666 // itself to Windows first.
10668 // The second issue is that some calls are known to be incorrect and
10669 // can cause Mono to segfault. Particularly: calls which pass or
10670 // return string[], or return any structure value. This is because
10671 // we haven't worked out the correct way to do this from C#.
10673 // The third issue is that when compiling you get a lot of warnings.
10674 // We are not sure whether the warnings are important or not.
10676 // Fourthly we do not routinely build or test these bindings as part
10677 // of the make && make check cycle, which means that regressions might
10680 // Suggestions and patches are welcome.
10684 // gmcs Libguestfs.cs
10685 // mono Libguestfs.exe
10687 // (You'll probably want to add a Test class / static main function
10688 // otherwise this won't do anything useful).
10692 using System.Runtime.InteropServices;
10693 using System.Runtime.Serialization;
10694 using System.Collections;
10698 class Error : System.ApplicationException
10700 public Error (string message) : base (message) {}
10701 protected Error (SerializationInfo info, StreamingContext context) {}
10708 [DllImport (\"%s\")]
10709 static extern IntPtr guestfs_create ();
10713 _handle = guestfs_create ();
10714 if (_handle == IntPtr.Zero)
10715 throw new Error (\"could not create guestfs handle\");
10718 [DllImport (\"%s\")]
10719 static extern void guestfs_close (IntPtr h);
10723 guestfs_close (_handle);
10726 [DllImport (\"%s\")]
10727 static extern string guestfs_last_error (IntPtr h);
10729 " library library library;
10731 (* Generate C# structure bindings. We prefix struct names with
10732 * underscore because C# cannot have conflicting struct names and
10733 * method names (eg. "class stat" and "stat").
10737 pr " [StructLayout (LayoutKind.Sequential)]\n";
10738 pr " public class _%s {\n" typ;
10741 | name, FChar -> pr " char %s;\n" name
10742 | name, FString -> pr " string %s;\n" name
10744 pr " uint %s_len;\n" name;
10745 pr " string %s;\n" name
10747 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10748 pr " string %s;\n" name
10749 | name, FUInt32 -> pr " uint %s;\n" name
10750 | name, FInt32 -> pr " int %s;\n" name
10751 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10752 | name, FInt64 -> pr " long %s;\n" name
10753 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10759 (* Generate C# function bindings. *)
10761 fun (name, style, _, _, _, shortdesc, _) ->
10762 let rec csharp_return_type () =
10763 match fst style with
10765 | RBool n -> "bool"
10767 | RInt64 n -> "long"
10769 | RConstOptString n
10771 | RBufferOut n -> "string"
10772 | RStruct (_,n) -> "_" ^ n
10773 | RHashtable n -> "Hashtable"
10774 | RStringList n -> "string[]"
10775 | RStructList (_,n) -> sprintf "_%s[]" n
10777 and c_return_type () =
10778 match fst style with
10782 | RInt64 _ -> "long"
10784 | RConstOptString _
10786 | RBufferOut _ -> "string"
10787 | RStruct (_,n) -> "_" ^ n
10789 | RStringList _ -> "string[]"
10790 | RStructList (_,n) -> sprintf "_%s[]" n
10792 and c_error_comparison () =
10793 match fst style with
10797 | RInt64 _ -> "== -1"
10799 | RConstOptString _
10805 | RStructList (_,_) -> "== null"
10807 and generate_extern_prototype () =
10808 pr " static extern %s guestfs_%s (IntPtr h"
10809 (c_return_type ()) name;
10812 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10813 | FileIn n | FileOut n
10815 pr ", [In] string %s" n
10816 | StringList n | DeviceList n ->
10817 pr ", [In] string[] %s" n
10827 and generate_public_prototype () =
10828 pr " public %s %s (" (csharp_return_type ()) name;
10829 let comma = ref false in
10831 if !comma then pr ", ";
10836 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10837 | FileIn n | FileOut n
10839 next (); pr "string %s" n
10840 | StringList n | DeviceList n ->
10841 next (); pr "string[] %s" n
10843 next (); pr "bool %s" n
10845 next (); pr "int %s" n
10847 next (); pr "long %s" n
10851 and generate_call () =
10852 pr "guestfs_%s (_handle" name;
10853 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10857 pr " [DllImport (\"%s\")]\n" library;
10858 generate_extern_prototype ();
10860 pr " /// <summary>\n";
10861 pr " /// %s\n" shortdesc;
10862 pr " /// </summary>\n";
10863 generate_public_prototype ();
10865 pr " %s r;\n" (c_return_type ());
10868 pr " if (r %s)\n" (c_error_comparison ());
10869 pr " throw new Error (guestfs_last_error (_handle));\n";
10870 (match fst style with
10873 pr " return r != 0 ? true : false;\n"
10875 pr " Hashtable rr = new Hashtable ();\n";
10876 pr " for (int i = 0; i < r.Length; i += 2)\n";
10877 pr " rr.Add (r[i], r[i+1]);\n";
10879 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10880 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10886 ) all_functions_sorted;
10892 and generate_bindtests () =
10893 generate_header CStyle LGPLv2plus;
10897 #include <stdlib.h>
10898 #include <inttypes.h>
10899 #include <string.h>
10901 #include \"guestfs.h\"
10902 #include \"guestfs-internal.h\"
10903 #include \"guestfs-internal-actions.h\"
10904 #include \"guestfs_protocol.h\"
10906 #define error guestfs_error
10907 #define safe_calloc guestfs_safe_calloc
10908 #define safe_malloc guestfs_safe_malloc
10911 print_strings (char *const *argv)
10916 for (argc = 0; argv[argc] != NULL; ++argc) {
10917 if (argc > 0) printf (\", \");
10918 printf (\"\\\"%%s\\\"\", argv[argc]);
10923 /* The test0 function prints its parameters to stdout. */
10927 match test_functions with
10928 | [] -> assert false
10929 | test0 :: tests -> test0, tests in
10932 let (name, style, _, _, _, _, _) = test0 in
10933 generate_prototype ~extern:false ~semicolon:false ~newline:true
10934 ~handle:"g" ~prefix:"guestfs__" name style;
10939 | Device n | Dev_or_Path n
10942 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10944 pr " for (size_t i = 0; i < %s_size; ++i)\n" n;
10945 pr " printf (\"<%%02x>\", %s[i]);\n" n;
10946 pr " printf (\"\\n\");\n"
10947 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10948 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10949 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10950 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10951 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10953 pr " /* Java changes stdout line buffering so we need this: */\n";
10954 pr " fflush (stdout);\n";
10960 fun (name, style, _, _, _, _, _) ->
10961 if String.sub name (String.length name - 3) 3 <> "err" then (
10962 pr "/* Test normal return. */\n";
10963 generate_prototype ~extern:false ~semicolon:false ~newline:true
10964 ~handle:"g" ~prefix:"guestfs__" name style;
10966 (match fst style with
10971 pr " sscanf (val, \"%%d\", &r);\n";
10974 pr " int64_t r;\n";
10975 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10978 pr " return STREQ (val, \"true\");\n"
10980 | RConstOptString _ ->
10981 (* Can't return the input string here. Return a static
10982 * string so we ensure we get a segfault if the caller
10983 * tries to free it.
10985 pr " return \"static string\";\n"
10987 pr " return strdup (val);\n"
10989 pr " char **strs;\n";
10991 pr " sscanf (val, \"%%d\", &n);\n";
10992 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10993 pr " for (i = 0; i < n; ++i) {\n";
10994 pr " strs[i] = safe_malloc (g, 16);\n";
10995 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10997 pr " strs[n] = NULL;\n";
10998 pr " return strs;\n"
10999 | RStruct (_, typ) ->
11000 pr " struct guestfs_%s *r;\n" typ;
11001 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11003 | RStructList (_, typ) ->
11004 pr " struct guestfs_%s_list *r;\n" typ;
11005 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11006 pr " sscanf (val, \"%%d\", &r->len);\n";
11007 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11010 pr " char **strs;\n";
11012 pr " sscanf (val, \"%%d\", &n);\n";
11013 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11014 pr " for (i = 0; i < n; ++i) {\n";
11015 pr " strs[i*2] = safe_malloc (g, 16);\n";
11016 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11017 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11018 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11020 pr " strs[n*2] = NULL;\n";
11021 pr " return strs;\n"
11023 pr " return strdup (val);\n"
11028 pr "/* Test error return. */\n";
11029 generate_prototype ~extern:false ~semicolon:false ~newline:true
11030 ~handle:"g" ~prefix:"guestfs__" name style;
11032 pr " error (g, \"error\");\n";
11033 (match fst style with
11034 | RErr | RInt _ | RInt64 _ | RBool _ ->
11036 | RConstString _ | RConstOptString _
11037 | RString _ | RStringList _ | RStruct _
11041 pr " return NULL;\n"
11048 and generate_ocaml_bindtests () =
11049 generate_header OCamlStyle GPLv2plus;
11053 let g = Guestfs.create () in
11057 String.concat " " (
11060 | CallString s -> "\"" ^ s ^ "\""
11061 | CallOptString None -> "None"
11062 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11063 | CallStringList xs ->
11064 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11065 | CallInt i when i >= 0 -> string_of_int i
11066 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11067 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11068 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11069 | CallBool b -> string_of_bool b
11070 | CallBuffer s -> sprintf "%S" s
11075 generate_lang_bindtests (
11076 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11079 pr "print_endline \"EOF\"\n"
11081 and generate_perl_bindtests () =
11082 pr "#!/usr/bin/perl -w\n";
11083 generate_header HashStyle GPLv2plus;
11090 my $g = Sys::Guestfs->new ();
11094 String.concat ", " (
11097 | CallString s -> "\"" ^ s ^ "\""
11098 | CallOptString None -> "undef"
11099 | CallOptString (Some s) -> sprintf "\"%s\"" s
11100 | CallStringList xs ->
11101 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11102 | CallInt i -> string_of_int i
11103 | CallInt64 i -> Int64.to_string i
11104 | CallBool b -> if b then "1" else "0"
11105 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11110 generate_lang_bindtests (
11111 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11114 pr "print \"EOF\\n\"\n"
11116 and generate_python_bindtests () =
11117 generate_header HashStyle GPLv2plus;
11122 g = guestfs.GuestFS ()
11126 String.concat ", " (
11129 | CallString s -> "\"" ^ s ^ "\""
11130 | CallOptString None -> "None"
11131 | CallOptString (Some s) -> sprintf "\"%s\"" s
11132 | CallStringList xs ->
11133 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11134 | CallInt i -> string_of_int i
11135 | CallInt64 i -> Int64.to_string i
11136 | CallBool b -> if b then "1" else "0"
11137 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11142 generate_lang_bindtests (
11143 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11146 pr "print \"EOF\"\n"
11148 and generate_ruby_bindtests () =
11149 generate_header HashStyle GPLv2plus;
11154 g = Guestfs::create()
11158 String.concat ", " (
11161 | CallString s -> "\"" ^ s ^ "\""
11162 | CallOptString None -> "nil"
11163 | CallOptString (Some s) -> sprintf "\"%s\"" s
11164 | CallStringList xs ->
11165 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11166 | CallInt i -> string_of_int i
11167 | CallInt64 i -> Int64.to_string i
11168 | CallBool b -> string_of_bool b
11169 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11174 generate_lang_bindtests (
11175 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11178 pr "print \"EOF\\n\"\n"
11180 and generate_java_bindtests () =
11181 generate_header CStyle GPLv2plus;
11184 import com.redhat.et.libguestfs.*;
11186 public class Bindtests {
11187 public static void main (String[] argv)
11190 GuestFS g = new GuestFS ();
11194 String.concat ", " (
11197 | CallString s -> "\"" ^ s ^ "\""
11198 | CallOptString None -> "null"
11199 | CallOptString (Some s) -> sprintf "\"%s\"" s
11200 | CallStringList xs ->
11202 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11203 | CallInt i -> string_of_int i
11204 | CallInt64 i -> Int64.to_string i
11205 | CallBool b -> string_of_bool b
11207 "new byte[] { " ^ String.concat "," (
11208 map_chars (fun c -> string_of_int (Char.code c)) s
11214 generate_lang_bindtests (
11215 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11219 System.out.println (\"EOF\");
11221 catch (Exception exn) {
11222 System.err.println (exn);
11229 and generate_haskell_bindtests () =
11230 generate_header HaskellStyle GPLv2plus;
11233 module Bindtests where
11234 import qualified Guestfs
11237 g <- Guestfs.create
11241 String.concat " " (
11244 | CallString s -> "\"" ^ s ^ "\""
11245 | CallOptString None -> "Nothing"
11246 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11247 | CallStringList xs ->
11248 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11249 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11250 | CallInt i -> string_of_int i
11251 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11252 | CallInt64 i -> Int64.to_string i
11253 | CallBool true -> "True"
11254 | CallBool false -> "False"
11255 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11260 generate_lang_bindtests (
11261 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11264 pr " putStrLn \"EOF\"\n"
11266 (* Language-independent bindings tests - we do it this way to
11267 * ensure there is parity in testing bindings across all languages.
11269 and generate_lang_bindtests call =
11270 call "test0" [CallString "abc"; CallOptString (Some "def");
11271 CallStringList []; CallBool false;
11272 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11273 CallBuffer "abc\000abc"];
11274 call "test0" [CallString "abc"; CallOptString None;
11275 CallStringList []; CallBool false;
11276 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11277 CallBuffer "abc\000abc"];
11278 call "test0" [CallString ""; CallOptString (Some "def");
11279 CallStringList []; CallBool false;
11280 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11281 CallBuffer "abc\000abc"];
11282 call "test0" [CallString ""; CallOptString (Some "");
11283 CallStringList []; CallBool false;
11284 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11285 CallBuffer "abc\000abc"];
11286 call "test0" [CallString "abc"; CallOptString (Some "def");
11287 CallStringList ["1"]; CallBool false;
11288 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11289 CallBuffer "abc\000abc"];
11290 call "test0" [CallString "abc"; CallOptString (Some "def");
11291 CallStringList ["1"; "2"]; CallBool false;
11292 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11293 CallBuffer "abc\000abc"];
11294 call "test0" [CallString "abc"; CallOptString (Some "def");
11295 CallStringList ["1"]; CallBool true;
11296 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11297 CallBuffer "abc\000abc"];
11298 call "test0" [CallString "abc"; CallOptString (Some "def");
11299 CallStringList ["1"]; CallBool false;
11300 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11301 CallBuffer "abc\000abc"];
11302 call "test0" [CallString "abc"; CallOptString (Some "def");
11303 CallStringList ["1"]; CallBool false;
11304 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11305 CallBuffer "abc\000abc"];
11306 call "test0" [CallString "abc"; CallOptString (Some "def");
11307 CallStringList ["1"]; CallBool false;
11308 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11309 CallBuffer "abc\000abc"];
11310 call "test0" [CallString "abc"; CallOptString (Some "def");
11311 CallStringList ["1"]; CallBool false;
11312 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11313 CallBuffer "abc\000abc"];
11314 call "test0" [CallString "abc"; CallOptString (Some "def");
11315 CallStringList ["1"]; CallBool false;
11316 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11317 CallBuffer "abc\000abc"];
11318 call "test0" [CallString "abc"; CallOptString (Some "def");
11319 CallStringList ["1"]; CallBool false;
11320 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11321 CallBuffer "abc\000abc"]
11323 (* XXX Add here tests of the return and error functions. *)
11325 (* Code to generator bindings for virt-inspector. Currently only
11326 * implemented for OCaml code (for virt-p2v 2.0).
11328 let rng_input = "inspector/virt-inspector.rng"
11330 (* Read the input file and parse it into internal structures. This is
11331 * by no means a complete RELAX NG parser, but is just enough to be
11332 * able to parse the specific input file.
11335 | Element of string * rng list (* <element name=name/> *)
11336 | Attribute of string * rng list (* <attribute name=name/> *)
11337 | Interleave of rng list (* <interleave/> *)
11338 | ZeroOrMore of rng (* <zeroOrMore/> *)
11339 | OneOrMore of rng (* <oneOrMore/> *)
11340 | Optional of rng (* <optional/> *)
11341 | Choice of string list (* <choice><value/>*</choice> *)
11342 | Value of string (* <value>str</value> *)
11343 | Text (* <text/> *)
11345 let rec string_of_rng = function
11346 | Element (name, xs) ->
11347 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11348 | Attribute (name, xs) ->
11349 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11350 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11351 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11352 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11353 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11354 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11355 | Value value -> "Value \"" ^ value ^ "\""
11358 and string_of_rng_list xs =
11359 String.concat ", " (List.map string_of_rng xs)
11361 let rec parse_rng ?defines context = function
11363 | Xml.Element ("element", ["name", name], children) :: rest ->
11364 Element (name, parse_rng ?defines context children)
11365 :: parse_rng ?defines context rest
11366 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11367 Attribute (name, parse_rng ?defines context children)
11368 :: parse_rng ?defines context rest
11369 | Xml.Element ("interleave", [], children) :: rest ->
11370 Interleave (parse_rng ?defines context children)
11371 :: parse_rng ?defines context rest
11372 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11373 let rng = parse_rng ?defines context [child] in
11375 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11377 failwithf "%s: <zeroOrMore> contains more than one child element"
11380 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11381 let rng = parse_rng ?defines context [child] in
11383 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11385 failwithf "%s: <oneOrMore> contains more than one child element"
11388 | Xml.Element ("optional", [], [child]) :: rest ->
11389 let rng = parse_rng ?defines context [child] in
11391 | [child] -> Optional child :: parse_rng ?defines context rest
11393 failwithf "%s: <optional> contains more than one child element"
11396 | Xml.Element ("choice", [], children) :: rest ->
11397 let values = List.map (
11398 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11400 failwithf "%s: can't handle anything except <value> in <choice>"
11404 :: parse_rng ?defines context rest
11405 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11406 Value value :: parse_rng ?defines context rest
11407 | Xml.Element ("text", [], []) :: rest ->
11408 Text :: parse_rng ?defines context rest
11409 | Xml.Element ("ref", ["name", name], []) :: rest ->
11410 (* Look up the reference. Because of limitations in this parser,
11411 * we can't handle arbitrarily nested <ref> yet. You can only
11412 * use <ref> from inside <start>.
11414 (match defines with
11416 failwithf "%s: contains <ref>, but no refs are defined yet" context
11418 let rng = StringMap.find name map in
11419 rng @ parse_rng ?defines context rest
11422 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11425 let xml = Xml.parse_file rng_input in
11427 | Xml.Element ("grammar", _,
11428 Xml.Element ("start", _, gram) :: defines) ->
11429 (* The <define/> elements are referenced in the <start> section,
11430 * so build a map of those first.
11432 let defines = List.fold_left (
11434 function Xml.Element ("define", ["name", name], defn) ->
11435 StringMap.add name defn map
11437 failwithf "%s: expected <define name=name/>" rng_input
11438 ) StringMap.empty defines in
11439 let defines = StringMap.mapi parse_rng defines in
11441 (* Parse the <start> clause, passing the defines. *)
11442 parse_rng ~defines "<start>" gram
11444 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11447 let name_of_field = function
11448 | Element (name, _) | Attribute (name, _)
11449 | ZeroOrMore (Element (name, _))
11450 | OneOrMore (Element (name, _))
11451 | Optional (Element (name, _)) -> name
11452 | Optional (Attribute (name, _)) -> name
11453 | Text -> (* an unnamed field in an element *)
11456 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11458 (* At the moment this function only generates OCaml types. However we
11459 * should parameterize it later so it can generate types/structs in a
11460 * variety of languages.
11462 let generate_types xs =
11463 (* A simple type is one that can be printed out directly, eg.
11464 * "string option". A complex type is one which has a name and has
11465 * to be defined via another toplevel definition, eg. a struct.
11467 * generate_type generates code for either simple or complex types.
11468 * In the simple case, it returns the string ("string option"). In
11469 * the complex case, it returns the name ("mountpoint"). In the
11470 * complex case it has to print out the definition before returning,
11471 * so it should only be called when we are at the beginning of a
11472 * new line (BOL context).
11474 let rec generate_type = function
11475 | Text -> (* string *)
11477 | Choice values -> (* [`val1|`val2|...] *)
11478 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11479 | ZeroOrMore rng -> (* <rng> list *)
11480 let t, is_simple = generate_type rng in
11481 t ^ " list (* 0 or more *)", is_simple
11482 | OneOrMore rng -> (* <rng> list *)
11483 let t, is_simple = generate_type rng in
11484 t ^ " list (* 1 or more *)", is_simple
11485 (* virt-inspector hack: bool *)
11486 | Optional (Attribute (name, [Value "1"])) ->
11488 | Optional rng -> (* <rng> list *)
11489 let t, is_simple = generate_type rng in
11490 t ^ " option", is_simple
11491 (* type name = { fields ... } *)
11492 | Element (name, fields) when is_attrs_interleave fields ->
11493 generate_type_struct name (get_attrs_interleave fields)
11494 | Element (name, [field]) (* type name = field *)
11495 | Attribute (name, [field]) ->
11496 let t, is_simple = generate_type field in
11497 if is_simple then (t, true)
11499 pr "type %s = %s\n" name t;
11502 | Element (name, fields) -> (* type name = { fields ... } *)
11503 generate_type_struct name fields
11505 failwithf "generate_type failed at: %s" (string_of_rng rng)
11507 and is_attrs_interleave = function
11508 | [Interleave _] -> true
11509 | Attribute _ :: fields -> is_attrs_interleave fields
11510 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11513 and get_attrs_interleave = function
11514 | [Interleave fields] -> fields
11515 | ((Attribute _) as field) :: fields
11516 | ((Optional (Attribute _)) as field) :: fields ->
11517 field :: get_attrs_interleave fields
11518 | _ -> assert false
11520 and generate_types xs =
11521 List.iter (fun x -> ignore (generate_type x)) xs
11523 and generate_type_struct name fields =
11524 (* Calculate the types of the fields first. We have to do this
11525 * before printing anything so we are still in BOL context.
11527 let types = List.map fst (List.map generate_type fields) in
11529 (* Special case of a struct containing just a string and another
11530 * field. Turn it into an assoc list.
11533 | ["string"; other] ->
11534 let fname1, fname2 =
11536 | [f1; f2] -> name_of_field f1, name_of_field f2
11537 | _ -> assert false in
11538 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11542 pr "type %s = {\n" name;
11544 fun (field, ftype) ->
11545 let fname = name_of_field field in
11546 pr " %s_%s : %s;\n" name fname ftype
11547 ) (List.combine fields types);
11549 (* Return the name of this type, and
11550 * false because it's not a simple type.
11557 let generate_parsers xs =
11558 (* As for generate_type above, generate_parser makes a parser for
11559 * some type, and returns the name of the parser it has generated.
11560 * Because it (may) need to print something, it should always be
11561 * called in BOL context.
11563 let rec generate_parser = function
11564 | Text -> (* string *)
11565 "string_child_or_empty"
11566 | Choice values -> (* [`val1|`val2|...] *)
11567 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11569 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11570 | ZeroOrMore rng -> (* <rng> list *)
11571 let pa = generate_parser rng in
11572 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11573 | OneOrMore rng -> (* <rng> list *)
11574 let pa = generate_parser rng in
11575 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11576 (* virt-inspector hack: bool *)
11577 | Optional (Attribute (name, [Value "1"])) ->
11578 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11579 | Optional rng -> (* <rng> list *)
11580 let pa = generate_parser rng in
11581 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11582 (* type name = { fields ... } *)
11583 | Element (name, fields) when is_attrs_interleave fields ->
11584 generate_parser_struct name (get_attrs_interleave fields)
11585 | Element (name, [field]) -> (* type name = field *)
11586 let pa = generate_parser field in
11587 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11588 pr "let %s =\n" parser_name;
11590 pr "let parse_%s = %s\n" name parser_name;
11592 | Attribute (name, [field]) ->
11593 let pa = generate_parser field in
11594 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11595 pr "let %s =\n" parser_name;
11597 pr "let parse_%s = %s\n" name parser_name;
11599 | Element (name, fields) -> (* type name = { fields ... } *)
11600 generate_parser_struct name ([], fields)
11602 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11604 and is_attrs_interleave = function
11605 | [Interleave _] -> true
11606 | Attribute _ :: fields -> is_attrs_interleave fields
11607 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11610 and get_attrs_interleave = function
11611 | [Interleave fields] -> [], fields
11612 | ((Attribute _) as field) :: fields
11613 | ((Optional (Attribute _)) as field) :: fields ->
11614 let attrs, interleaves = get_attrs_interleave fields in
11615 (field :: attrs), interleaves
11616 | _ -> assert false
11618 and generate_parsers xs =
11619 List.iter (fun x -> ignore (generate_parser x)) xs
11621 and generate_parser_struct name (attrs, interleaves) =
11622 (* Generate parsers for the fields first. We have to do this
11623 * before printing anything so we are still in BOL context.
11625 let fields = attrs @ interleaves in
11626 let pas = List.map generate_parser fields in
11628 (* Generate an intermediate tuple from all the fields first.
11629 * If the type is just a string + another field, then we will
11630 * return this directly, otherwise it is turned into a record.
11632 * RELAX NG note: This code treats <interleave> and plain lists of
11633 * fields the same. In other words, it doesn't bother enforcing
11634 * any ordering of fields in the XML.
11636 pr "let parse_%s x =\n" name;
11637 pr " let t = (\n ";
11638 let comma = ref false in
11641 if !comma then pr ",\n ";
11644 | Optional (Attribute (fname, [field])), pa ->
11646 | Optional (Element (fname, [field])), pa ->
11647 pr "%s (optional_child %S x)" pa fname
11648 | Attribute (fname, [Text]), _ ->
11649 pr "attribute %S x" fname
11650 | (ZeroOrMore _ | OneOrMore _), pa ->
11655 let fname = name_of_field field in
11656 pr "%s (child %S x)" pa fname
11657 ) (List.combine fields pas);
11661 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11665 pr " (Obj.magic t : %s)\n" name
11669 | (Optional (Attribute (fname, [field])), pa) ->
11670 pr " %s_%s =\n" name fname;
11672 | (Optional (Element (fname, [field])), pa) ->
11673 pr " %s_%s =\n" name fname;
11674 pr " (let x = optional_child %S x in\n" fname;
11677 let fname = name_of_field field in
11678 pr " %s_%s =\n" name fname;
11679 pr " (let x = child %S x in\n" fname;
11681 ) (List.combine fields pas);
11685 sprintf "parse_%s" name
11688 generate_parsers xs
11690 (* Generate ocaml/guestfs_inspector.mli. *)
11691 let generate_ocaml_inspector_mli () =
11692 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11695 (** This is an OCaml language binding to the external [virt-inspector]
11698 For more information, please read the man page [virt-inspector(1)].
11703 generate_types grammar;
11704 pr "(** The nested information returned from the {!inspect} function. *)\n";
11708 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11709 (** To inspect a libvirt domain called [name], pass a singleton
11710 list: [inspect [name]]. When using libvirt only, you may
11711 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11713 To inspect a disk image or images, pass a list of the filenames
11714 of the disk images: [inspect filenames]
11716 This function inspects the given guest or disk images and
11717 returns a list of operating system(s) found and a large amount
11718 of information about them. In the vast majority of cases,
11719 a virtual machine only contains a single operating system.
11721 If the optional [~xml] parameter is given, then this function
11722 skips running the external virt-inspector program and just
11723 parses the given XML directly (which is expected to be XML
11724 produced from a previous run of virt-inspector). The list of
11725 names and connect URI are ignored in this case.
11727 This function can throw a wide variety of exceptions, for example
11728 if the external virt-inspector program cannot be found, or if
11729 it doesn't generate valid XML.
11733 (* Generate ocaml/guestfs_inspector.ml. *)
11734 let generate_ocaml_inspector_ml () =
11735 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11740 generate_types grammar;
11744 (* Misc functions which are used by the parser code below. *)
11745 let first_child = function
11746 | Xml.Element (_, _, c::_) -> c
11747 | Xml.Element (name, _, []) ->
11748 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11749 | Xml.PCData str ->
11750 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11752 let string_child_or_empty = function
11753 | Xml.Element (_, _, [Xml.PCData s]) -> s
11754 | Xml.Element (_, _, []) -> \"\"
11755 | Xml.Element (x, _, _) ->
11756 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11758 | Xml.PCData str ->
11759 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11761 let optional_child name xml =
11762 let children = Xml.children xml in
11764 Some (List.find (function
11765 | Xml.Element (n, _, _) when n = name -> true
11766 | _ -> false) children)
11770 let child name xml =
11771 match optional_child name xml with
11774 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11776 let attribute name xml =
11777 try Xml.attrib xml name
11778 with Xml.No_attribute _ ->
11779 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11783 generate_parsers grammar;
11787 (* Run external virt-inspector, then use parser to parse the XML. *)
11788 let inspect ?connect ?xml names =
11792 if names = [] then invalid_arg \"inspect: no names given\";
11793 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11794 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11796 let cmd = List.map Filename.quote cmd in
11797 let cmd = String.concat \" \" cmd in
11798 let chan = open_process_in cmd in
11799 let xml = Xml.parse_in chan in
11800 (match close_process_in chan with
11802 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11803 | WSIGNALED i | WSTOPPED i ->
11804 failwith (\"external virt-inspector command died or stopped on sig \" ^
11809 Xml.parse_string doc in
11810 parse_operatingsystems xml
11813 and generate_max_proc_nr () =
11814 pr "%d\n" max_proc_nr
11816 let output_to filename k =
11817 let filename_new = filename ^ ".new" in
11818 chan := open_out filename_new;
11821 chan := Pervasives.stdout;
11823 (* Is the new file different from the current file? *)
11824 if Sys.file_exists filename && files_equal filename filename_new then
11825 unlink filename_new (* same, so skip it *)
11827 (* different, overwrite old one *)
11828 (try chmod filename 0o644 with Unix_error _ -> ());
11829 rename filename_new filename;
11830 chmod filename 0o444;
11831 printf "written %s\n%!" filename;
11834 let perror msg = function
11835 | Unix_error (err, _, _) ->
11836 eprintf "%s: %s\n" msg (error_message err)
11838 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11840 (* Main program. *)
11843 try openfile "HACKING" [O_RDWR] 0
11845 | Unix_error (ENOENT, _, _) ->
11847 You are probably running this from the wrong directory.
11848 Run it from the top source directory using the command
11853 perror "open: HACKING" exn;
11856 (* Acquire a lock so parallel builds won't try to run the generator
11857 * twice at the same time. Subsequent builds will wait for the first
11858 * one to finish. Note the lock is released implicitly when the
11861 (try lockf lock_fd F_LOCK 1
11863 perror "lock: HACKING" exn;
11866 check_functions ();
11868 output_to "src/guestfs_protocol.x" generate_xdr;
11869 output_to "src/guestfs-structs.h" generate_structs_h;
11870 output_to "src/guestfs-actions.h" generate_actions_h;
11871 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11872 output_to "src/guestfs-actions.c" generate_client_actions;
11873 output_to "src/guestfs-bindtests.c" generate_bindtests;
11874 output_to "src/guestfs-structs.pod" generate_structs_pod;
11875 output_to "src/guestfs-actions.pod" generate_actions_pod;
11876 output_to "src/guestfs-availability.pod" generate_availability_pod;
11877 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11878 output_to "src/libguestfs.syms" generate_linker_script;
11879 output_to "daemon/actions.h" generate_daemon_actions_h;
11880 output_to "daemon/stubs.c" generate_daemon_actions;
11881 output_to "daemon/names.c" generate_daemon_names;
11882 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11883 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11884 output_to "capitests/tests.c" generate_tests;
11885 output_to "fish/cmds.c" generate_fish_cmds;
11886 output_to "fish/completion.c" generate_fish_completion;
11887 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11888 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11889 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11890 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11891 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11892 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11893 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11894 output_to "perl/Guestfs.xs" generate_perl_xs;
11895 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11896 output_to "perl/bindtests.pl" generate_perl_bindtests;
11897 output_to "python/guestfs-py.c" generate_python_c;
11898 output_to "python/guestfs.py" generate_python_py;
11899 output_to "python/bindtests.py" generate_python_bindtests;
11900 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11901 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11902 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11906 let cols = cols_of_struct typ in
11907 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11908 output_to filename (generate_java_struct jtyp cols);
11911 output_to "java/Makefile.inc" generate_java_makefile_inc;
11912 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11913 output_to "java/Bindtests.java" generate_java_bindtests;
11914 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11915 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11916 output_to "csharp/Libguestfs.cs" generate_csharp;
11918 (* Always generate this file last, and unconditionally. It's used
11919 * by the Makefile to know when we must re-run the generator.
11921 let chan = open_out "src/stamp-generator" in
11922 fprintf chan "1\n";
11925 printf "generated %d lines of code\n" !lines