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, [OptString "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, [OptString "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 dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
801 The call returns a structure with four elements. The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet. The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
810 I<Note:> Don't use this call to test for availability
811 of features. Distro backports makes this unreliable. Use
812 C<guestfs_available> instead.");
814 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815 [InitNone, Always, TestOutputTrue (
816 [["set_selinux"; "true"];
818 "set SELinux enabled or disabled at appliance boot",
820 This sets the selinux flag that is passed to the appliance
821 at boot time. The default is C<selinux=0> (disabled).
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
829 ("get_selinux", (RBool "selinux", []), -1, [],
831 "get SELinux enabled flag",
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
839 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840 [InitNone, Always, TestOutputFalse (
841 [["set_trace"; "false"];
843 "enable or disable command traces",
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish. In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859 ("get_trace", (RBool "trace", []), -1, [],
861 "get command trace enabled flag",
863 Return the command trace flag.");
865 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866 [InitNone, Always, TestOutputFalse (
867 [["set_direct"; "false"];
869 "enable or disable direct appliance mode",
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
879 You probably don't want to use this unless you know what you
882 The default is disabled.");
884 ("get_direct", (RBool "direct", []), -1, [],
886 "get direct appliance mode flag",
888 Return the direct appliance mode flag.");
890 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891 [InitNone, Always, TestOutputTrue (
892 [["set_recovery_proc"; "true"];
893 ["get_recovery_proc"]])],
894 "enable or disable the recovery process",
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process. The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself). In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
910 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912 "get recovery process enabled flag",
914 Return the recovery process enabled flag.");
916 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918 "add a drive specifying the QEMU block emulation to use",
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
923 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925 "add a drive read-only specifying the QEMU block emulation to use",
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
932 (* daemon_functions are any functions which cause some action
933 * to take place in the daemon.
936 let daemon_functions = [
937 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938 [InitEmpty, Always, TestOutput (
939 [["part_disk"; "/dev/sda"; "mbr"];
940 ["mkfs"; "ext2"; "/dev/sda1"];
941 ["mount"; "/dev/sda1"; "/"];
942 ["write"; "/new"; "new file contents"];
943 ["cat"; "/new"]], "new file contents")],
944 "mount a guest disk at a position in the filesystem",
946 Mount a guest disk at a position in the filesystem. Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest. If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
952 The rules are the same as for L<mount(2)>: A filesystem must
953 first be mounted on C</> before others can be mounted. Other
954 filesystems can only be mounted on directories which already
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly. This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability. Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
970 ("sync", (RErr, []), 2, [],
971 [ InitEmpty, Always, TestRun [["sync"]]],
972 "sync disks, writes are flushed through to the disk image",
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
980 ("touch", (RErr, [Pathname "path"]), 3, [],
981 [InitBasicFS, Always, TestOutputTrue (
983 ["exists"; "/new"]])],
984 "update file timestamps or create a new file",
986 Touch acts like the L<touch(1)> command. It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
990 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991 [InitISOFS, Always, TestOutput (
992 [["cat"; "/known-2"]], "abcdef\n")],
993 "list the contents of a file",
995 Return the contents of the file named C<path>.
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string). For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1002 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003 [], (* XXX Tricky to test because it depends on the exact format
1004 * of the 'ls -l' command, which changes between F10 and F11.
1006 "list the files in a directory (long format)",
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1011 This command is mostly useful for interactive sessions. It
1012 is I<not> intended that you try to parse the output string.");
1014 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015 [InitBasicFS, Always, TestOutputList (
1017 ["touch"; "/newer"];
1018 ["touch"; "/newest"];
1019 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020 "list the files in a directory",
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd). The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1026 This command is mostly useful for interactive sessions. Programs
1027 should probably use C<guestfs_readdir> instead.");
1029 ("list_devices", (RStringList "devices", []), 7, [],
1030 [InitEmpty, Always, TestOutputListOfDevices (
1031 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032 "list the block devices",
1034 List all the block devices.
1036 The full block device names are returned, eg. C</dev/sda>");
1038 ("list_partitions", (RStringList "partitions", []), 8, [],
1039 [InitBasicFS, Always, TestOutputListOfDevices (
1040 [["list_partitions"]], ["/dev/sda1"]);
1041 InitEmpty, Always, TestOutputListOfDevices (
1042 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044 "list the partitions",
1046 List all the partitions detected on all block devices.
1048 The full partition device names are returned, eg. C</dev/sda1>
1050 This does not return logical volumes. For that you will need to
1051 call C<guestfs_lvs>.");
1053 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055 [["pvs"]], ["/dev/sda1"]);
1056 InitEmpty, Always, TestOutputListOfDevices (
1057 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058 ["pvcreate"; "/dev/sda1"];
1059 ["pvcreate"; "/dev/sda2"];
1060 ["pvcreate"; "/dev/sda3"];
1061 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062 "list the LVM physical volumes (PVs)",
1064 List all the physical volumes detected. This is the equivalent
1065 of the L<pvs(8)> command.
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1070 See also C<guestfs_pvs_full>.");
1072 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073 [InitBasicFSonLVM, Always, TestOutputList (
1075 InitEmpty, Always, TestOutputList (
1076 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077 ["pvcreate"; "/dev/sda1"];
1078 ["pvcreate"; "/dev/sda2"];
1079 ["pvcreate"; "/dev/sda3"];
1080 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081 ["vgcreate"; "VG2"; "/dev/sda3"];
1082 ["vgs"]], ["VG1"; "VG2"])],
1083 "list the LVM volume groups (VGs)",
1085 List all the volumes groups detected. This is the equivalent
1086 of the L<vgs(8)> command.
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1091 See also C<guestfs_vgs_full>.");
1093 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094 [InitBasicFSonLVM, Always, TestOutputList (
1095 [["lvs"]], ["/dev/VG/LV"]);
1096 InitEmpty, Always, TestOutputList (
1097 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098 ["pvcreate"; "/dev/sda1"];
1099 ["pvcreate"; "/dev/sda2"];
1100 ["pvcreate"; "/dev/sda3"];
1101 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102 ["vgcreate"; "VG2"; "/dev/sda3"];
1103 ["lvcreate"; "LV1"; "VG1"; "50"];
1104 ["lvcreate"; "LV2"; "VG1"; "50"];
1105 ["lvcreate"; "LV3"; "VG2"; "50"];
1106 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107 "list the LVM logical volumes (LVs)",
1109 List all the logical volumes detected. This is the equivalent
1110 of the L<lvs(8)> command.
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1115 See also C<guestfs_lvs_full>.");
1117 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118 [], (* XXX how to test? *)
1119 "list the LVM physical volumes (PVs)",
1121 List all the physical volumes detected. This is the equivalent
1122 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1124 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125 [], (* XXX how to test? *)
1126 "list the LVM volume groups (VGs)",
1128 List all the volumes groups detected. This is the equivalent
1129 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1131 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132 [], (* XXX how to test? *)
1133 "list the LVM logical volumes (LVs)",
1135 List all the logical volumes detected. This is the equivalent
1136 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1138 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139 [InitISOFS, Always, TestOutputList (
1140 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141 InitISOFS, Always, TestOutputList (
1142 [["read_lines"; "/empty"]], [])],
1143 "read file as lines",
1145 Return the contents of the file named C<path>.
1147 The file contents are returned as a list of lines. Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line). For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1155 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156 [], (* XXX Augeas code needs tests. *)
1157 "create a new Augeas handle",
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1163 You must call this before using any other C<guestfs_aug_*>
1166 C<root> is the filesystem root. C<root> must not be NULL,
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1175 =item C<AUG_SAVE_BACKUP> = 1
1177 Keep the original file with a C<.augsave> extension.
1179 =item C<AUG_SAVE_NEWFILE> = 2
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1184 =item C<AUG_TYPE_CHECK> = 4
1186 Typecheck lenses (can be expensive).
1188 =item C<AUG_NO_STDINC> = 8
1190 Do not use standard load path for modules.
1192 =item C<AUG_SAVE_NOOP> = 16
1194 Make save a no-op, just record what would have been changed.
1196 =item C<AUG_NO_LOAD> = 32
1198 Do not load the tree in C<guestfs_aug_init>.
1202 To close the handle, you can call C<guestfs_aug_close>.
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1206 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207 [], (* XXX Augeas code needs tests. *)
1208 "close the current Augeas handle",
1210 Close the current Augeas handle and free up any resources
1211 used by it. After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1215 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216 [], (* XXX Augeas code needs tests. *)
1217 "define an Augeas variable",
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227 [], (* XXX Augeas code needs tests. *)
1228 "define an Augeas node",
1230 Defines a variable C<name> whose value is the result of
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1241 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242 [], (* XXX Augeas code needs tests. *)
1243 "look up the value of an Augeas path",
1245 Look up the value associated with C<path>. If C<path>
1246 matches exactly one node, the C<value> is returned.");
1248 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249 [], (* XXX Augeas code needs tests. *)
1250 "set Augeas path to value",
1252 Set the value associated with C<path> to C<val>.
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL. Due to an oversight in the libguestfs API
1256 you cannot do that with this call. Instead you must use the
1257 C<guestfs_aug_clear> call.");
1259 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260 [], (* XXX Augeas code needs tests. *)
1261 "insert a sibling Augeas node",
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1271 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272 [], (* XXX Augeas code needs tests. *)
1273 "remove an Augeas path",
1275 Remove C<path> and all of its children.
1277 On success this returns the number of entries which were removed.");
1279 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280 [], (* XXX Augeas code needs tests. *)
1283 Move the node C<src> to C<dest>. C<src> must match exactly
1284 one node. C<dest> is overwritten if it exists.");
1286 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287 [], (* XXX Augeas code needs tests. *)
1288 "return Augeas nodes which match augpath",
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1294 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295 [], (* XXX Augeas code needs tests. *)
1296 "write all pending Augeas changes to disk",
1298 This writes all pending changes to disk.
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1303 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304 [], (* XXX Augeas code needs tests. *)
1305 "load files into the tree",
1307 Load files into the tree.
1309 See C<aug_load> in the Augeas documentation for the full gory
1312 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313 [], (* XXX Augeas code needs tests. *)
1314 "list Augeas nodes under augpath",
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319 ("rm", (RErr, [Pathname "path"]), 29, [],
1320 [InitBasicFS, Always, TestRun
1323 InitBasicFS, Always, TestLastFail
1325 InitBasicFS, Always, TestLastFail
1330 Remove the single file C<path>.");
1332 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333 [InitBasicFS, Always, TestRun
1336 InitBasicFS, Always, TestLastFail
1337 [["rmdir"; "/new"]];
1338 InitBasicFS, Always, TestLastFail
1340 ["rmdir"; "/new"]]],
1341 "remove a directory",
1343 Remove the single directory C<path>.");
1345 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346 [InitBasicFS, Always, TestOutputFalse
1348 ["mkdir"; "/new/foo"];
1349 ["touch"; "/new/foo/bar"];
1351 ["exists"; "/new"]]],
1352 "remove a file or directory recursively",
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory. This is like the C<rm -rf> shell
1358 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359 [InitBasicFS, Always, TestOutputTrue
1361 ["is_dir"; "/new"]];
1362 InitBasicFS, Always, TestLastFail
1363 [["mkdir"; "/new/foo/bar"]]],
1364 "create a directory",
1366 Create a directory named C<path>.");
1368 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369 [InitBasicFS, Always, TestOutputTrue
1370 [["mkdir_p"; "/new/foo/bar"];
1371 ["is_dir"; "/new/foo/bar"]];
1372 InitBasicFS, Always, TestOutputTrue
1373 [["mkdir_p"; "/new/foo/bar"];
1374 ["is_dir"; "/new/foo"]];
1375 InitBasicFS, Always, TestOutputTrue
1376 [["mkdir_p"; "/new/foo/bar"];
1377 ["is_dir"; "/new"]];
1378 (* Regression tests for RHBZ#503133: *)
1379 InitBasicFS, Always, TestRun
1381 ["mkdir_p"; "/new"]];
1382 InitBasicFS, Always, TestLastFail
1384 ["mkdir_p"; "/new"]]],
1385 "create a directory and parents",
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary. This is like the C<mkdir -p> shell command.");
1390 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391 [], (* XXX Need stat command to test *)
1394 Change the mode (permissions) of C<path> to C<mode>. Only
1395 numeric modes are supported.
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1401 The mode actually set is affected by the umask.");
1403 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404 [], (* XXX Need stat command to test *)
1405 "change file owner and group",
1407 Change the file owner to C<owner> and group to C<group>.
1409 Only numeric uid and gid are supported. If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1413 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414 [InitISOFS, Always, TestOutputTrue (
1415 [["exists"; "/empty"]]);
1416 InitISOFS, Always, TestOutputTrue (
1417 [["exists"; "/directory"]])],
1418 "test if file or directory exists",
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426 [InitISOFS, Always, TestOutputTrue (
1427 [["is_file"; "/known-1"]]);
1428 InitISOFS, Always, TestOutputFalse (
1429 [["is_file"; "/directory"]])],
1430 "test if file exists",
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name. Note that it returns false for
1434 other objects like directories.
1436 See also C<guestfs_stat>.");
1438 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439 [InitISOFS, Always, TestOutputFalse (
1440 [["is_dir"; "/known-3"]]);
1441 InitISOFS, Always, TestOutputTrue (
1442 [["is_dir"; "/directory"]])],
1443 "test if file exists",
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name. Note that it returns false for
1447 other objects like files.
1449 See also C<guestfs_stat>.");
1451 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452 [InitEmpty, Always, TestOutputListOfDevices (
1453 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454 ["pvcreate"; "/dev/sda1"];
1455 ["pvcreate"; "/dev/sda2"];
1456 ["pvcreate"; "/dev/sda3"];
1457 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458 "create an LVM physical volume",
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1464 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465 [InitEmpty, Always, TestOutputList (
1466 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467 ["pvcreate"; "/dev/sda1"];
1468 ["pvcreate"; "/dev/sda2"];
1469 ["pvcreate"; "/dev/sda3"];
1470 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471 ["vgcreate"; "VG2"; "/dev/sda3"];
1472 ["vgs"]], ["VG1"; "VG2"])],
1473 "create an LVM volume group",
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1478 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479 [InitEmpty, Always, TestOutputList (
1480 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481 ["pvcreate"; "/dev/sda1"];
1482 ["pvcreate"; "/dev/sda2"];
1483 ["pvcreate"; "/dev/sda3"];
1484 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485 ["vgcreate"; "VG2"; "/dev/sda3"];
1486 ["lvcreate"; "LV1"; "VG1"; "50"];
1487 ["lvcreate"; "LV2"; "VG1"; "50"];
1488 ["lvcreate"; "LV3"; "VG2"; "50"];
1489 ["lvcreate"; "LV4"; "VG2"; "50"];
1490 ["lvcreate"; "LV5"; "VG2"; "50"];
1492 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494 "create an LVM logical volume",
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1499 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500 [InitEmpty, Always, TestOutput (
1501 [["part_disk"; "/dev/sda"; "mbr"];
1502 ["mkfs"; "ext2"; "/dev/sda1"];
1503 ["mount_options"; ""; "/dev/sda1"; "/"];
1504 ["write"; "/new"; "new file contents"];
1505 ["cat"; "/new"]], "new file contents")],
1506 "make a filesystem",
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume). The filesystem type is C<fstype>, for
1512 ("sfdisk", (RErr, [Device "device";
1513 Int "cyls"; Int "heads"; Int "sectors";
1514 StringList "lines"]), 43, [DangerWillRobinson],
1516 "create partitions on a block device",
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1521 C<device> should be a block device, for example C</dev/sda>.
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted. Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1531 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1532 information refer to the L<sfdisk(8)> manpage.
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1541 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1545 This call creates a file called C<path>. The contents of the
1546 file is the string C<content> (which can contain any 8 bit data),
1547 with length C<size>.
1549 As a special case, if C<size> is C<0>
1550 then the length is calculated using C<strlen> (so in this case
1551 the content cannot contain embedded ASCII NULs).
1553 I<NB.> Owing to a bug, writing content containing ASCII NUL
1554 characters does I<not> work, even if the length is specified.");
1556 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557 [InitEmpty, Always, TestOutputListOfDevices (
1558 [["part_disk"; "/dev/sda"; "mbr"];
1559 ["mkfs"; "ext2"; "/dev/sda1"];
1560 ["mount_options"; ""; "/dev/sda1"; "/"];
1561 ["mounts"]], ["/dev/sda1"]);
1562 InitEmpty, Always, TestOutputList (
1563 [["part_disk"; "/dev/sda"; "mbr"];
1564 ["mkfs"; "ext2"; "/dev/sda1"];
1565 ["mount_options"; ""; "/dev/sda1"; "/"];
1568 "unmount a filesystem",
1570 This unmounts the given filesystem. The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1574 ("mounts", (RStringList "devices", []), 46, [],
1575 [InitBasicFS, Always, TestOutputListOfDevices (
1576 [["mounts"]], ["/dev/sda1"])],
1577 "show mounted filesystems",
1579 This returns the list of currently mounted filesystems. It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582 Some internal mounts are not shown.
1584 See also: C<guestfs_mountpoints>");
1586 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587 [InitBasicFS, Always, TestOutputList (
1590 (* check that umount_all can unmount nested mounts correctly: *)
1591 InitEmpty, Always, TestOutputList (
1592 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593 ["mkfs"; "ext2"; "/dev/sda1"];
1594 ["mkfs"; "ext2"; "/dev/sda2"];
1595 ["mkfs"; "ext2"; "/dev/sda3"];
1596 ["mount_options"; ""; "/dev/sda1"; "/"];
1598 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599 ["mkdir"; "/mp1/mp2"];
1600 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601 ["mkdir"; "/mp1/mp2/mp3"];
1604 "unmount all filesystems",
1606 This unmounts all mounted filesystems.
1608 Some internal mounts are not unmounted by this call.");
1610 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612 "remove all LVM LVs, VGs and PVs",
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1617 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618 [InitISOFS, Always, TestOutput (
1619 [["file"; "/empty"]], "empty");
1620 InitISOFS, Always, TestOutput (
1621 [["file"; "/known-1"]], "ASCII text");
1622 InitISOFS, Always, TestLastFail (
1623 [["file"; "/notexists"]])],
1624 "determine file type",
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file. This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1630 This call will also transparently look inside various types
1633 The exact command which runs is C<file -zbsL path>. Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1637 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638 [InitBasicFS, Always, TestOutput (
1639 [["upload"; "test-command"; "/test-command"];
1640 ["chmod"; "0o755"; "/test-command"];
1641 ["command"; "/test-command 1"]], "Result1");
1642 InitBasicFS, Always, TestOutput (
1643 [["upload"; "test-command"; "/test-command"];
1644 ["chmod"; "0o755"; "/test-command"];
1645 ["command"; "/test-command 2"]], "Result2\n");
1646 InitBasicFS, Always, TestOutput (
1647 [["upload"; "test-command"; "/test-command"];
1648 ["chmod"; "0o755"; "/test-command"];
1649 ["command"; "/test-command 3"]], "\nResult3");
1650 InitBasicFS, Always, TestOutput (
1651 [["upload"; "test-command"; "/test-command"];
1652 ["chmod"; "0o755"; "/test-command"];
1653 ["command"; "/test-command 4"]], "\nResult4\n");
1654 InitBasicFS, Always, TestOutput (
1655 [["upload"; "test-command"; "/test-command"];
1656 ["chmod"; "0o755"; "/test-command"];
1657 ["command"; "/test-command 5"]], "\nResult5\n\n");
1658 InitBasicFS, Always, TestOutput (
1659 [["upload"; "test-command"; "/test-command"];
1660 ["chmod"; "0o755"; "/test-command"];
1661 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662 InitBasicFS, Always, TestOutput (
1663 [["upload"; "test-command"; "/test-command"];
1664 ["chmod"; "0o755"; "/test-command"];
1665 ["command"; "/test-command 7"]], "");
1666 InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 8"]], "\n");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 9"]], "\n\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682 InitBasicFS, Always, TestLastFail (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command"]])],
1686 "run a command from the guest filesystem",
1688 This call runs a command from the guest filesystem. The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters. The list must be
1696 non-empty (ie. must contain a program name). Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1700 The return value is anything printed to I<stdout> by
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message. The error message
1705 string is the content of I<stderr> from the command.
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>. If you require a program from
1709 another location, you should provide the full path in the
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places. It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1718 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719 [InitBasicFS, Always, TestOutputList (
1720 [["upload"; "test-command"; "/test-command"];
1721 ["chmod"; "0o755"; "/test-command"];
1722 ["command_lines"; "/test-command 1"]], ["Result1"]);
1723 InitBasicFS, Always, TestOutputList (
1724 [["upload"; "test-command"; "/test-command"];
1725 ["chmod"; "0o755"; "/test-command"];
1726 ["command_lines"; "/test-command 2"]], ["Result2"]);
1727 InitBasicFS, Always, TestOutputList (
1728 [["upload"; "test-command"; "/test-command"];
1729 ["chmod"; "0o755"; "/test-command"];
1730 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731 InitBasicFS, Always, TestOutputList (
1732 [["upload"; "test-command"; "/test-command"];
1733 ["chmod"; "0o755"; "/test-command"];
1734 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735 InitBasicFS, Always, TestOutputList (
1736 [["upload"; "test-command"; "/test-command"];
1737 ["chmod"; "0o755"; "/test-command"];
1738 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739 InitBasicFS, Always, TestOutputList (
1740 [["upload"; "test-command"; "/test-command"];
1741 ["chmod"; "0o755"; "/test-command"];
1742 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743 InitBasicFS, Always, TestOutputList (
1744 [["upload"; "test-command"; "/test-command"];
1745 ["chmod"; "0o755"; "/test-command"];
1746 ["command_lines"; "/test-command 7"]], []);
1747 InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 8"]], [""]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 9"]], ["";""]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763 "run a command, returning lines",
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1768 See also: C<guestfs_sh_lines>");
1770 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771 [InitISOFS, Always, TestOutputStruct (
1772 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773 "get file information",
1775 Returns file information for the given C<path>.
1777 This is the same as the C<stat(2)> system call.");
1779 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780 [InitISOFS, Always, TestOutputStruct (
1781 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782 "get file information for a symbolic link",
1784 Returns file information for the given C<path>.
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1790 This is the same as the C<lstat(2)> system call.");
1792 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795 "get file system statistics",
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1801 This is the same as the C<statvfs(2)> system call.");
1803 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805 "get ext2/ext3/ext4 superblock details",
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1810 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1811 manpage for more details. The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1815 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816 [InitEmpty, Always, TestOutputTrue (
1817 [["blockdev_setro"; "/dev/sda"];
1818 ["blockdev_getro"; "/dev/sda"]])],
1819 "set block device to read-only",
1821 Sets the block device named C<device> to read-only.
1823 This uses the L<blockdev(8)> command.");
1825 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826 [InitEmpty, Always, TestOutputFalse (
1827 [["blockdev_setrw"; "/dev/sda"];
1828 ["blockdev_getro"; "/dev/sda"]])],
1829 "set block device to read-write",
1831 Sets the block device named C<device> to read-write.
1833 This uses the L<blockdev(8)> command.");
1835 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836 [InitEmpty, Always, TestOutputTrue (
1837 [["blockdev_setro"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "is block device set to read-only",
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1844 This uses the L<blockdev(8)> command.");
1846 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847 [InitEmpty, Always, TestOutputInt (
1848 [["blockdev_getss"; "/dev/sda"]], 512)],
1849 "get sectorsize of block device",
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862 "get blocksize of block device",
1864 This returns the block size of a device.
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1869 This uses the L<blockdev(8)> command.");
1871 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873 "set blocksize of block device",
1875 This sets the block size of a device.
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883 [InitEmpty, Always, TestOutputInt (
1884 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885 "get total size of device in 512-byte sectors",
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1894 This uses the L<blockdev(8)> command.");
1896 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897 [InitEmpty, Always, TestOutputInt (
1898 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899 "get total size of device in bytes",
1901 This returns the size of the device in bytes.
1903 See also C<guestfs_blockdev_getsz>.
1905 This uses the L<blockdev(8)> command.");
1907 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908 [InitEmpty, Always, TestRun
1909 [["blockdev_flushbufs"; "/dev/sda"]]],
1910 "flush device buffers",
1912 This tells the kernel to flush internal buffers associated
1915 This uses the L<blockdev(8)> command.");
1917 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918 [InitEmpty, Always, TestRun
1919 [["blockdev_rereadpt"; "/dev/sda"]]],
1920 "reread partition table",
1922 Reread the partition table on C<device>.
1924 This uses the L<blockdev(8)> command.");
1926 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927 [InitBasicFS, Always, TestOutput (
1928 (* Pick a file from cwd which isn't likely to change. *)
1929 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930 ["checksum"; "md5"; "/COPYING.LIB"]],
1931 Digest.to_hex (Digest.file "COPYING.LIB"))],
1932 "upload a file from the local machine",
1934 Upload local file C<filename> to C<remotefilename> on the
1937 C<filename> can also be a named pipe.
1939 See also C<guestfs_download>.");
1941 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942 [InitBasicFS, Always, TestOutput (
1943 (* Pick a file from cwd which isn't likely to change. *)
1944 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946 ["upload"; "testdownload.tmp"; "/upload"];
1947 ["checksum"; "md5"; "/upload"]],
1948 Digest.to_hex (Digest.file "COPYING.LIB"))],
1949 "download a file to the local machine",
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1954 C<filename> can also be a named pipe.
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1958 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959 [InitISOFS, Always, TestOutput (
1960 [["checksum"; "crc"; "/known-3"]], "2891671662");
1961 InitISOFS, Always, TestLastFail (
1962 [["checksum"; "crc"; "/notexists"]]);
1963 InitISOFS, Always, TestOutput (
1964 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965 InitISOFS, Always, TestOutput (
1966 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967 InitISOFS, Always, TestOutput (
1968 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969 InitISOFS, Always, TestOutput (
1970 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971 InitISOFS, Always, TestOutput (
1972 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973 InitISOFS, Always, TestOutput (
1974 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1975 (* Test for RHBZ#579608, absolute symbolic links. *)
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1978 "compute MD5, SHAx or CRC checksum of file",
1980 This call computes the MD5, SHAx or CRC checksum of the
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1995 Compute the MD5 hash (using the C<md5sum> program).
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2019 The checksum is returned as a printable string.
2021 To get the checksum for a device, use C<guestfs_checksum_device>.
2023 To get the checksums for many files, use C<guestfs_checksums_out>.");
2025 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2026 [InitBasicFS, Always, TestOutput (
2027 [["tar_in"; "../images/helloworld.tar"; "/"];
2028 ["cat"; "/hello"]], "hello\n")],
2029 "unpack tarfile to directory",
2031 This command uploads and unpacks local file C<tarfile> (an
2032 I<uncompressed> tar file) into C<directory>.
2034 To upload a compressed tarball, use C<guestfs_tgz_in>
2035 or C<guestfs_txz_in>.");
2037 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2039 "pack directory into tarfile",
2041 This command packs the contents of C<directory> and downloads
2042 it to local file C<tarfile>.
2044 To download a compressed tarball, use C<guestfs_tgz_out>
2045 or C<guestfs_txz_out>.");
2047 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2048 [InitBasicFS, Always, TestOutput (
2049 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2050 ["cat"; "/hello"]], "hello\n")],
2051 "unpack compressed tarball to directory",
2053 This command uploads and unpacks local file C<tarball> (a
2054 I<gzip compressed> tar file) into C<directory>.
2056 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2058 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2060 "pack directory into compressed tarball",
2062 This command packs the contents of C<directory> and downloads
2063 it to local file C<tarball>.
2065 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2067 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2068 [InitBasicFS, Always, TestLastFail (
2070 ["mount_ro"; "/dev/sda1"; "/"];
2071 ["touch"; "/new"]]);
2072 InitBasicFS, Always, TestOutput (
2073 [["write"; "/new"; "data"];
2075 ["mount_ro"; "/dev/sda1"; "/"];
2076 ["cat"; "/new"]], "data")],
2077 "mount a guest disk, read-only",
2079 This is the same as the C<guestfs_mount> command, but it
2080 mounts the filesystem with the read-only (I<-o ro>) flag.");
2082 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2084 "mount a guest disk with mount options",
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set the mount options as for the
2088 L<mount(8)> I<-o> flag.
2090 If the C<options> parameter is an empty string, then
2091 no options are passed (all options default to whatever
2092 the filesystem uses).");
2094 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2096 "mount a guest disk with mount options and vfstype",
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2102 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2104 "debugging and internals",
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2110 There is no comprehensive help for this command. You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2114 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115 [InitEmpty, Always, TestOutputList (
2116 [["part_disk"; "/dev/sda"; "mbr"];
2117 ["pvcreate"; "/dev/sda1"];
2118 ["vgcreate"; "VG"; "/dev/sda1"];
2119 ["lvcreate"; "LV1"; "VG"; "50"];
2120 ["lvcreate"; "LV2"; "VG"; "50"];
2121 ["lvremove"; "/dev/VG/LV1"];
2122 ["lvs"]], ["/dev/VG/LV2"]);
2123 InitEmpty, Always, TestOutputList (
2124 [["part_disk"; "/dev/sda"; "mbr"];
2125 ["pvcreate"; "/dev/sda1"];
2126 ["vgcreate"; "VG"; "/dev/sda1"];
2127 ["lvcreate"; "LV1"; "VG"; "50"];
2128 ["lvcreate"; "LV2"; "VG"; "50"];
2129 ["lvremove"; "/dev/VG"];
2131 InitEmpty, Always, TestOutputList (
2132 [["part_disk"; "/dev/sda"; "mbr"];
2133 ["pvcreate"; "/dev/sda1"];
2134 ["vgcreate"; "VG"; "/dev/sda1"];
2135 ["lvcreate"; "LV1"; "VG"; "50"];
2136 ["lvcreate"; "LV2"; "VG"; "50"];
2137 ["lvremove"; "/dev/VG"];
2139 "remove an LVM logical volume",
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2147 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148 [InitEmpty, Always, TestOutputList (
2149 [["part_disk"; "/dev/sda"; "mbr"];
2150 ["pvcreate"; "/dev/sda1"];
2151 ["vgcreate"; "VG"; "/dev/sda1"];
2152 ["lvcreate"; "LV1"; "VG"; "50"];
2153 ["lvcreate"; "LV2"; "VG"; "50"];
2156 InitEmpty, Always, TestOutputList (
2157 [["part_disk"; "/dev/sda"; "mbr"];
2158 ["pvcreate"; "/dev/sda1"];
2159 ["vgcreate"; "VG"; "/dev/sda1"];
2160 ["lvcreate"; "LV1"; "VG"; "50"];
2161 ["lvcreate"; "LV2"; "VG"; "50"];
2164 "remove an LVM volume group",
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2168 This also forcibly removes all logical volumes in the volume
2171 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172 [InitEmpty, Always, TestOutputListOfDevices (
2173 [["part_disk"; "/dev/sda"; "mbr"];
2174 ["pvcreate"; "/dev/sda1"];
2175 ["vgcreate"; "VG"; "/dev/sda1"];
2176 ["lvcreate"; "LV1"; "VG"; "50"];
2177 ["lvcreate"; "LV2"; "VG"; "50"];
2179 ["pvremove"; "/dev/sda1"];
2181 InitEmpty, Always, TestOutputListOfDevices (
2182 [["part_disk"; "/dev/sda"; "mbr"];
2183 ["pvcreate"; "/dev/sda1"];
2184 ["vgcreate"; "VG"; "/dev/sda1"];
2185 ["lvcreate"; "LV1"; "VG"; "50"];
2186 ["lvcreate"; "LV2"; "VG"; "50"];
2188 ["pvremove"; "/dev/sda1"];
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 "remove an LVM physical volume",
2201 This wipes a physical volume C<device> so that LVM will no longer
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2208 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209 [InitBasicFS, Always, TestOutput (
2210 [["set_e2label"; "/dev/sda1"; "testlabel"];
2211 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212 "set the ext2/3/4 filesystem label",
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>. Filesystem labels are limited to
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2221 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2223 "get the ext2/3/4 filesystem label",
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2228 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229 (let uuid = uuidgen () in
2230 [InitBasicFS, Always, TestOutput (
2231 [["set_e2uuid"; "/dev/sda1"; uuid];
2232 ["get_e2uuid"; "/dev/sda1"]], uuid);
2233 InitBasicFS, Always, TestOutput (
2234 [["set_e2uuid"; "/dev/sda1"; "clear"];
2235 ["get_e2uuid"; "/dev/sda1"]], "");
2236 (* We can't predict what UUIDs will be, so just check the commands run. *)
2237 InitBasicFS, Always, TestRun (
2238 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239 InitBasicFS, Always, TestRun (
2240 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241 "set the ext2/3/4 filesystem UUID",
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>. The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2251 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2253 "get the ext2/3/4 filesystem UUID",
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259 [InitBasicFS, Always, TestOutputInt (
2260 [["umount"; "/dev/sda1"];
2261 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262 InitBasicFS, Always, TestOutputInt (
2263 [["umount"; "/dev/sda1"];
2264 ["zero"; "/dev/sda1"];
2265 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266 "run the filesystem checker",
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2271 The returned integer is the status. See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2280 Multiple status codes can be summed together.
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2289 Checking or repairing NTFS volumes is not supported
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2296 ("zero", (RErr, [Device "device"]), 85, [],
2297 [InitBasicFS, Always, TestOutput (
2298 [["umount"; "/dev/sda1"];
2299 ["zero"; "/dev/sda1"];
2300 ["file"; "/dev/sda1"]], "data")],
2301 "write zeroes to the device",
2303 This command writes zeroes over the first few blocks of C<device>.
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device). It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2311 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312 (* Test disabled because grub-install incompatible with virtio-blk driver.
2313 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2315 [InitBasicFS, Disabled, TestOutputTrue (
2316 [["grub_install"; "/"; "/dev/sda1"];
2317 ["is_dir"; "/boot"]])],
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2323 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324 [InitBasicFS, Always, TestOutput (
2325 [["write"; "/old"; "file content"];
2326 ["cp"; "/old"; "/new"];
2327 ["cat"; "/new"]], "file content");
2328 InitBasicFS, Always, TestOutputTrue (
2329 [["write"; "/old"; "file content"];
2330 ["cp"; "/old"; "/new"];
2331 ["is_file"; "/old"]]);
2332 InitBasicFS, Always, TestOutput (
2333 [["write"; "/old"; "file content"];
2335 ["cp"; "/old"; "/dir/new"];
2336 ["cat"; "/dir/new"]], "file content")],
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2342 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343 [InitBasicFS, Always, TestOutput (
2344 [["mkdir"; "/olddir"];
2345 ["mkdir"; "/newdir"];
2346 ["write"; "/olddir/file"; "file content"];
2347 ["cp_a"; "/olddir"; "/newdir"];
2348 ["cat"; "/newdir/olddir/file"]], "file content")],
2349 "copy a file or directory recursively",
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2354 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355 [InitBasicFS, Always, TestOutput (
2356 [["write"; "/old"; "file content"];
2357 ["mv"; "/old"; "/new"];
2358 ["cat"; "/new"]], "file content");
2359 InitBasicFS, Always, TestOutputFalse (
2360 [["write"; "/old"; "file content"];
2361 ["mv"; "/old"; "/new"];
2362 ["is_file"; "/old"]])],
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2368 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369 [InitEmpty, Always, TestRun (
2370 [["drop_caches"; "3"]])],
2371 "drop kernel page cache, dentries and inodes",
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches. The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2378 Setting C<whattodrop> to 3 should drop everything.
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2383 ("dmesg", (RString "kmsgs", []), 91, [],
2384 [InitEmpty, Always, TestRun (
2386 "return kernel messages",
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel. This is sometimes useful for extended
2390 debugging of problems.
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2397 ("ping_daemon", (RErr, []), 92, [],
2398 [InitEmpty, Always, TestRun (
2399 [["ping_daemon"]])],
2400 "ping the guest daemon",
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess. Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2407 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408 [InitBasicFS, Always, TestOutputTrue (
2409 [["write"; "/file1"; "contents of a file"];
2410 ["cp"; "/file1"; "/file2"];
2411 ["equal"; "/file1"; "/file2"]]);
2412 InitBasicFS, Always, TestOutputFalse (
2413 [["write"; "/file1"; "contents of a file"];
2414 ["write"; "/file2"; "contents of another file"];
2415 ["equal"; "/file1"; "/file2"]]);
2416 InitBasicFS, Always, TestLastFail (
2417 [["equal"; "/file1"; "/file2"]])],
2418 "test if two files have equal contents",
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2423 The external L<cmp(1)> program is used for the comparison.");
2425 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426 [InitISOFS, Always, TestOutputList (
2427 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428 InitISOFS, Always, TestOutputList (
2429 [["strings"; "/empty"]], []);
2430 (* Test for RHBZ#579608, absolute symbolic links. *)
2431 InitISOFS, Always, TestRun (
2432 [["strings"; "/abssymlink"]])],
2433 "print the printable strings in a file",
2435 This runs the L<strings(1)> command on a file and returns
2436 the list of printable strings found.");
2438 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2439 [InitISOFS, Always, TestOutputList (
2440 [["strings_e"; "b"; "/known-5"]], []);
2441 InitBasicFS, Always, TestOutputList (
2442 [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2443 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2444 "print the printable strings in a file",
2446 This is like the C<guestfs_strings> command, but allows you to
2447 specify the encoding of strings that are looked for in
2448 the source file C<path>.
2450 Allowed encodings are:
2456 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2457 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2461 Single 8-bit-byte characters.
2465 16-bit big endian strings such as those encoded in
2466 UTF-16BE or UCS-2BE.
2468 =item l (lower case letter L)
2470 16-bit little endian such as UTF-16LE and UCS-2LE.
2471 This is useful for examining binaries in Windows guests.
2475 32-bit big endian such as UCS-4BE.
2479 32-bit little endian such as UCS-4LE.
2483 The returned strings are transcoded to UTF-8.");
2485 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2486 [InitISOFS, Always, TestOutput (
2487 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2488 (* Test for RHBZ#501888c2 regression which caused large hexdump
2489 * commands to segfault.
2491 InitISOFS, Always, TestRun (
2492 [["hexdump"; "/100krandom"]]);
2493 (* Test for RHBZ#579608, absolute symbolic links. *)
2494 InitISOFS, Always, TestRun (
2495 [["hexdump"; "/abssymlink"]])],
2496 "dump a file in hexadecimal",
2498 This runs C<hexdump -C> on the given C<path>. The result is
2499 the human-readable, canonical hex dump of the file.");
2501 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502 [InitNone, Always, TestOutput (
2503 [["part_disk"; "/dev/sda"; "mbr"];
2504 ["mkfs"; "ext3"; "/dev/sda1"];
2505 ["mount_options"; ""; "/dev/sda1"; "/"];
2506 ["write"; "/new"; "test file"];
2507 ["umount"; "/dev/sda1"];
2508 ["zerofree"; "/dev/sda1"];
2509 ["mount_options"; ""; "/dev/sda1"; "/"];
2510 ["cat"; "/new"]], "test file")],
2511 "zero unused inodes and disk blocks on ext2/3 filesystem",
2513 This runs the I<zerofree> program on C<device>. This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2518 You should B<not> run this program if the filesystem is
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2524 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2526 "resize an LVM physical volume",
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2531 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532 Int "cyls"; Int "heads"; Int "sectors";
2533 String "line"]), 99, [DangerWillRobinson],
2535 "modify a single partition on a block device",
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2540 For other parameters, see C<guestfs_sfdisk>. You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2543 See also: C<guestfs_part_add>");
2545 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2547 "display the partition table",
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command. It is
2551 not intended to be parsed.
2553 See also: C<guestfs_part_list>");
2555 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2557 "display the kernel geometry",
2559 This displays the kernel's idea of the geometry of C<device>.
2561 The result is in human-readable format, and not designed to
2564 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2566 "display the disk geometry from the partition table",
2568 This displays the disk geometry of C<device> read from the
2569 partition table. Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2573 The result is in human-readable format, and not designed to
2576 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2578 "activate or deactivate all volume groups",
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2584 then those devices disappear.
2586 This command is the same as running C<vgchange -a y|n>");
2588 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2590 "activate or deactivate some volume groups",
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2596 then those devices disappear.
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2603 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604 [InitNone, Always, TestOutput (
2605 [["part_disk"; "/dev/sda"; "mbr"];
2606 ["pvcreate"; "/dev/sda1"];
2607 ["vgcreate"; "VG"; "/dev/sda1"];
2608 ["lvcreate"; "LV"; "VG"; "10"];
2609 ["mkfs"; "ext2"; "/dev/VG/LV"];
2610 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611 ["write"; "/new"; "test content"];
2613 ["lvresize"; "/dev/VG/LV"; "20"];
2614 ["e2fsck_f"; "/dev/VG/LV"];
2615 ["resize2fs"; "/dev/VG/LV"];
2616 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617 ["cat"; "/new"]], "test content");
2618 InitNone, Always, TestRun (
2619 (* Make an LV smaller to test RHBZ#587484. *)
2620 [["part_disk"; "/dev/sda"; "mbr"];
2621 ["pvcreate"; "/dev/sda1"];
2622 ["vgcreate"; "VG"; "/dev/sda1"];
2623 ["lvcreate"; "LV"; "VG"; "20"];
2624 ["lvresize"; "/dev/VG/LV"; "10"]])],
2625 "resize an LVM logical volume",
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>. When reducing, data in the reduced part
2631 ("resize2fs", (RErr, [Device "device"]), 106, [],
2632 [], (* lvresize tests this *)
2633 "resize an ext2/ext3 filesystem",
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command. For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2644 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645 [InitBasicFS, Always, TestOutputList (
2646 [["find"; "/"]], ["lost+found"]);
2647 InitBasicFS, Always, TestOutputList (
2651 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652 InitBasicFS, Always, TestOutputList (
2653 [["mkdir_p"; "/a/b/c"];
2654 ["touch"; "/a/b/c/d"];
2655 ["find"; "/a/b/"]], ["c"; "c/d"])],
2656 "find all files and directories",
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>. It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2663 This returns a list of strings I<without any prefix>. Thus
2664 if the directory structure was:
2670 then the returned list from C<guestfs_find> C</tmp> would be
2678 If C<directory> is not a directory, then this command returns
2681 The returned list is sorted.
2683 See also C<guestfs_find0>.");
2685 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686 [], (* lvresize tests this *)
2687 "check an ext2/ext3 filesystem",
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.). Normally you should use C<guestfs_fsck>.");
2696 ("sleep", (RErr, [Int "secs"]), 109, [],
2697 [InitNone, Always, TestRun (
2699 "sleep for some seconds",
2701 Sleep for C<secs> seconds.");
2703 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704 [InitNone, Always, TestOutputInt (
2705 [["part_disk"; "/dev/sda"; "mbr"];
2706 ["mkfs"; "ntfs"; "/dev/sda1"];
2707 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708 InitNone, Always, TestOutputInt (
2709 [["part_disk"; "/dev/sda"; "mbr"];
2710 ["mkfs"; "ext2"; "/dev/sda1"];
2711 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712 "probe NTFS volume",
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability. (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2718 C<rw> is a boolean flag. Set it to true if you want to test
2719 if the volume can be mounted read-write. Set it to false if
2720 you want to test if the volume can be mounted read-only.
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2726 ("sh", (RString "output", [String "command"]), 111, [],
2727 [], (* XXX needs tests *)
2728 "run a command via the shell",
2730 This call runs a command from the guest filesystem via the
2733 This is like C<guestfs_command>, but passes the command to:
2735 /bin/sh -c \"command\"
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2741 All the provisos about C<guestfs_command> apply to this call.");
2743 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744 [], (* XXX needs tests *)
2745 "run a command via the shell returning lines",
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2750 See also: C<guestfs_command_lines>");
2752 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754 * code in stubs.c, since all valid glob patterns must start with "/".
2755 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2757 [InitBasicFS, Always, TestOutputList (
2758 [["mkdir_p"; "/a/b/c"];
2759 ["touch"; "/a/b/c/d"];
2760 ["touch"; "/a/b/c/e"];
2761 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762 InitBasicFS, Always, TestOutputList (
2763 [["mkdir_p"; "/a/b/c"];
2764 ["touch"; "/a/b/c/d"];
2765 ["touch"; "/a/b/c/e"];
2766 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767 InitBasicFS, Always, TestOutputList (
2768 [["mkdir_p"; "/a/b/c"];
2769 ["touch"; "/a/b/c/d"];
2770 ["touch"; "/a/b/c/e"];
2771 ["glob_expand"; "/a/*/x/*"]], [])],
2772 "expand a wildcard path",
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2785 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787 [["scrub_device"; "/dev/sdc"]])],
2788 "scrub (securely wipe) a device",
2790 This command writes patterns over C<device> to make data retrieval
2793 It is an interface to the L<scrub(1)> program. See that
2794 manual page for more details.");
2796 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797 [InitBasicFS, Always, TestRun (
2798 [["write"; "/file"; "content"];
2799 ["scrub_file"; "/file"]])],
2800 "scrub (securely wipe) a file",
2802 This command writes patterns over a file to make data retrieval
2805 The file is I<removed> after scrubbing.
2807 It is an interface to the L<scrub(1)> program. See that
2808 manual page for more details.");
2810 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811 [], (* XXX needs testing *)
2812 "scrub (securely wipe) free space",
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2820 It is an interface to the L<scrub(1)> program. See that
2821 manual page for more details.");
2823 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824 [InitBasicFS, Always, TestRun (
2826 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827 "create a temporary directory",
2829 This command creates a temporary directory. The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2837 The name of the temporary directory that was created
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2846 See also: L<mkdtemp(3)>");
2848 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849 [InitISOFS, Always, TestOutputInt (
2850 [["wc_l"; "/10klines"]], 10000);
2851 (* Test for RHBZ#579608, absolute symbolic links. *)
2852 InitISOFS, Always, TestOutputInt (
2853 [["wc_l"; "/abssymlink"]], 10000)],
2854 "count lines in a file",
2856 This command counts the lines in a file, using the
2857 C<wc -l> external command.");
2859 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2860 [InitISOFS, Always, TestOutputInt (
2861 [["wc_w"; "/10klines"]], 10000)],
2862 "count words in a file",
2864 This command counts the words in a file, using the
2865 C<wc -w> external command.");
2867 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2868 [InitISOFS, Always, TestOutputInt (
2869 [["wc_c"; "/100kallspaces"]], 102400)],
2870 "count characters in a file",
2872 This command counts the characters in a file, using the
2873 C<wc -c> external command.");
2875 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2876 [InitISOFS, Always, TestOutputList (
2877 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2878 (* Test for RHBZ#579608, absolute symbolic links. *)
2879 InitISOFS, Always, TestOutputList (
2880 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2881 "return first 10 lines of a file",
2883 This command returns up to the first 10 lines of a file as
2884 a list of strings.");
2886 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2887 [InitISOFS, Always, TestOutputList (
2888 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2889 InitISOFS, Always, TestOutputList (
2890 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891 InitISOFS, Always, TestOutputList (
2892 [["head_n"; "0"; "/10klines"]], [])],
2893 "return first N lines of a file",
2895 If the parameter C<nrlines> is a positive number, this returns the first
2896 C<nrlines> lines of the file C<path>.
2898 If the parameter C<nrlines> is a negative number, this returns lines
2899 from the file C<path>, excluding the last C<nrlines> lines.
2901 If the parameter C<nrlines> is zero, this returns an empty list.");
2903 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2904 [InitISOFS, Always, TestOutputList (
2905 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2906 "return last 10 lines of a file",
2908 This command returns up to the last 10 lines of a file as
2909 a list of strings.");
2911 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2912 [InitISOFS, Always, TestOutputList (
2913 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2914 InitISOFS, Always, TestOutputList (
2915 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916 InitISOFS, Always, TestOutputList (
2917 [["tail_n"; "0"; "/10klines"]], [])],
2918 "return last N lines of a file",
2920 If the parameter C<nrlines> is a positive number, this returns the last
2921 C<nrlines> lines of the file C<path>.
2923 If the parameter C<nrlines> is a negative number, this returns lines
2924 from the file C<path>, starting with the C<-nrlines>th line.
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2928 ("df", (RString "output", []), 125, [],
2929 [], (* XXX Tricky to test because it depends on the exact format
2930 * of the 'df' command and other imponderables.
2932 "report file system disk space usage",
2934 This command runs the C<df> command to report disk space used.
2936 This command is mostly useful for interactive sessions. It
2937 is I<not> intended that you try to parse the output string.
2938 Use C<statvfs> from programs.");
2940 ("df_h", (RString "output", []), 126, [],
2941 [], (* XXX Tricky to test because it depends on the exact format
2942 * of the 'df' command and other imponderables.
2944 "report file system disk space usage (human readable)",
2946 This command runs the C<df -h> command to report disk space used
2947 in human-readable format.
2949 This command is mostly useful for interactive sessions. It
2950 is I<not> intended that you try to parse the output string.
2951 Use C<statvfs> from programs.");
2953 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2954 [InitISOFS, Always, TestOutputInt (
2955 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2956 "estimate file space usage",
2958 This command runs the C<du -s> command to estimate file space
2961 C<path> can be a file or a directory. If C<path> is a directory
2962 then the estimate includes the contents of the directory and all
2963 subdirectories (recursively).
2965 The result is the estimated size in I<kilobytes>
2966 (ie. units of 1024 bytes).");
2968 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2969 [InitISOFS, Always, TestOutputList (
2970 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2971 "list files in an initrd",
2973 This command lists out files contained in an initrd.
2975 The files are listed without any initial C</> character. The
2976 files are listed in the order they appear (not necessarily
2977 alphabetical). Directory names are listed as separate items.
2979 Old Linux kernels (2.4 and earlier) used a compressed ext2
2980 filesystem as initrd. We I<only> support the newer initramfs
2981 format (compressed cpio files).");
2983 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2985 "mount a file using the loop device",
2987 This command lets you mount C<file> (a filesystem image
2988 in a file) on a mount point. It is entirely equivalent to
2989 the command C<mount -o loop file mountpoint>.");
2991 ("mkswap", (RErr, [Device "device"]), 130, [],
2992 [InitEmpty, Always, TestRun (
2993 [["part_disk"; "/dev/sda"; "mbr"];
2994 ["mkswap"; "/dev/sda1"]])],
2995 "create a swap partition",
2997 Create a swap partition on C<device>.");
2999 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3000 [InitEmpty, Always, TestRun (
3001 [["part_disk"; "/dev/sda"; "mbr"];
3002 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3003 "create a swap partition with a label",
3005 Create a swap partition on C<device> with label C<label>.
3007 Note that you cannot attach a swap label to a block device
3008 (eg. C</dev/sda>), just to a partition. This appears to be
3009 a limitation of the kernel or swap tools.");
3011 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3012 (let uuid = uuidgen () in
3013 [InitEmpty, Always, TestRun (
3014 [["part_disk"; "/dev/sda"; "mbr"];
3015 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3016 "create a swap partition with an explicit UUID",
3018 Create a swap partition on C<device> with UUID C<uuid>.");
3020 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3021 [InitBasicFS, Always, TestOutputStruct (
3022 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3023 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3024 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3025 InitBasicFS, Always, TestOutputStruct (
3026 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3027 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3028 "make block, character or FIFO devices",
3030 This call creates block or character special devices, or
3031 named pipes (FIFOs).
3033 The C<mode> parameter should be the mode, using the standard
3034 constants. C<devmajor> and C<devminor> are the
3035 device major and minor numbers, only used when creating block
3036 and character special devices.
3038 Note that, just like L<mknod(2)>, the mode must be bitwise
3039 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3040 just creates a regular file). These constants are
3041 available in the standard Linux header files, or you can use
3042 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3043 which are wrappers around this command which bitwise OR
3044 in the appropriate constant for you.
3046 The mode actually set is affected by the umask.");
3048 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3049 [InitBasicFS, Always, TestOutputStruct (
3050 [["mkfifo"; "0o777"; "/node"];
3051 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3052 "make FIFO (named pipe)",
3054 This call creates a FIFO (named pipe) called C<path> with
3055 mode C<mode>. It is just a convenient wrapper around
3058 The mode actually set is affected by the umask.");
3060 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3061 [InitBasicFS, Always, TestOutputStruct (
3062 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3063 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3064 "make block device node",
3066 This call creates a block device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3070 The mode actually set is affected by the umask.");
3072 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3073 [InitBasicFS, Always, TestOutputStruct (
3074 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3075 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3076 "make char device node",
3078 This call creates a char device node called C<path> with
3079 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3080 It is just a convenient wrapper around C<guestfs_mknod>.
3082 The mode actually set is affected by the umask.");
3084 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3085 [InitEmpty, Always, TestOutputInt (
3086 [["umask"; "0o22"]], 0o22)],
3087 "set file mode creation mask (umask)",
3089 This function sets the mask used for creating new files and
3090 device nodes to C<mask & 0777>.
3092 Typical umask values would be C<022> which creates new files
3093 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3094 C<002> which creates new files with permissions like
3095 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3097 The default umask is C<022>. This is important because it
3098 means that directories and device nodes will be created with
3099 C<0644> or C<0755> mode even if you specify C<0777>.
3101 See also C<guestfs_get_umask>,
3102 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3104 This call returns the previous umask.");
3106 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3108 "read directories entries",
3110 This returns the list of directory entries in directory C<dir>.
3112 All entries in the directory are returned, including C<.> and
3113 C<..>. The entries are I<not> sorted, but returned in the same
3114 order as the underlying filesystem.
3116 Also this call returns basic file type information about each
3117 file. The C<ftyp> field will contain one of the following characters:
3155 The L<readdir(3)> returned a C<d_type> field with an
3160 This function is primarily intended for use by programs. To
3161 get a simple list of names, use C<guestfs_ls>. To get a printable
3162 directory for human consumption, use C<guestfs_ll>.");
3164 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3166 "create partitions on a block device",
3168 This is a simplified interface to the C<guestfs_sfdisk>
3169 command, where partition sizes are specified in megabytes
3170 only (rounded to the nearest cylinder) and you don't need
3171 to specify the cyls, heads and sectors parameters which
3172 were rarely if ever used anyway.
3174 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3175 and C<guestfs_part_disk>");
3177 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3179 "determine file type inside a compressed file",
3181 This command runs C<file> after first decompressing C<path>
3184 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3186 Since 1.0.63, use C<guestfs_file> instead which can now
3187 process compressed files.");
3189 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3191 "list extended attributes of a file or directory",
3193 This call lists the extended attributes of the file or directory
3196 At the system call level, this is a combination of the
3197 L<listxattr(2)> and L<getxattr(2)> calls.
3199 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3201 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3203 "list extended attributes of a file or directory",
3205 This is the same as C<guestfs_getxattrs>, but if C<path>
3206 is a symbolic link, then it returns the extended attributes
3207 of the link itself.");
3209 ("setxattr", (RErr, [String "xattr";
3210 String "val"; Int "vallen"; (* will be BufferIn *)
3211 Pathname "path"]), 143, [Optional "linuxxattrs"],
3213 "set extended attribute of a file or directory",
3215 This call sets the extended attribute named C<xattr>
3216 of the file C<path> to the value C<val> (of length C<vallen>).
3217 The value is arbitrary 8 bit data.
3219 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3221 ("lsetxattr", (RErr, [String "xattr";
3222 String "val"; Int "vallen"; (* will be BufferIn *)
3223 Pathname "path"]), 144, [Optional "linuxxattrs"],
3225 "set extended attribute of a file or directory",
3227 This is the same as C<guestfs_setxattr>, but if C<path>
3228 is a symbolic link, then it sets an extended attribute
3229 of the link itself.");
3231 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3233 "remove extended attribute of a file or directory",
3235 This call removes the extended attribute named C<xattr>
3236 of the file C<path>.
3238 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3240 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3242 "remove extended attribute of a file or directory",
3244 This is the same as C<guestfs_removexattr>, but if C<path>
3245 is a symbolic link, then it removes an extended attribute
3246 of the link itself.");
3248 ("mountpoints", (RHashtable "mps", []), 147, [],
3252 This call is similar to C<guestfs_mounts>. That call returns
3253 a list of devices. This one returns a hash table (map) of
3254 device name to directory where the device is mounted.");
3256 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3257 (* This is a special case: while you would expect a parameter
3258 * of type "Pathname", that doesn't work, because it implies
3259 * NEED_ROOT in the generated calling code in stubs.c, and
3260 * this function cannot use NEED_ROOT.
3263 "create a mountpoint",
3265 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3266 specialized calls that can be used to create extra mountpoints
3267 before mounting the first filesystem.
3269 These calls are I<only> necessary in some very limited circumstances,
3270 mainly the case where you want to mount a mix of unrelated and/or
3271 read-only filesystems together.
3273 For example, live CDs often contain a \"Russian doll\" nest of
3274 filesystems, an ISO outer layer, with a squashfs image inside, with
3275 an ext2/3 image inside that. You can unpack this as follows
3278 add-ro Fedora-11-i686-Live.iso
3281 mkmountpoint /squash
3284 mount-loop /cd/LiveOS/squashfs.img /squash
3285 mount-loop /squash/LiveOS/ext3fs.img /ext3
3287 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3289 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3291 "remove a mountpoint",
3293 This calls removes a mountpoint that was previously created
3294 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3295 for full details.");
3297 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3298 [InitISOFS, Always, TestOutputBuffer (
3299 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3300 (* Test various near large, large and too large files (RHBZ#589039). *)
3301 InitBasicFS, Always, TestLastFail (
3303 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3304 ["read_file"; "/a"]]);
3305 InitBasicFS, Always, TestLastFail (
3307 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3308 ["read_file"; "/a"]]);
3309 InitBasicFS, Always, TestLastFail (
3311 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3312 ["read_file"; "/a"]])],
3315 This calls returns the contents of the file C<path> as a
3318 Unlike C<guestfs_cat>, this function can correctly
3319 handle files that contain embedded ASCII NUL characters.
3320 However unlike C<guestfs_download>, this function is limited
3321 in the total size of file that can be handled.");
3323 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3324 [InitISOFS, Always, TestOutputList (
3325 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3326 InitISOFS, Always, TestOutputList (
3327 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3328 (* Test for RHBZ#579608, absolute symbolic links. *)
3329 InitISOFS, Always, TestOutputList (
3330 [["grep"; "nomatch"; "/abssymlink"]], [])],
3331 "return lines matching a pattern",
3333 This calls the external C<grep> program and returns the
3336 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3337 [InitISOFS, Always, TestOutputList (
3338 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3339 "return lines matching a pattern",
3341 This calls the external C<egrep> program and returns the
3344 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3345 [InitISOFS, Always, TestOutputList (
3346 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3347 "return lines matching a pattern",
3349 This calls the external C<fgrep> program and returns the
3352 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3353 [InitISOFS, Always, TestOutputList (
3354 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3355 "return lines matching a pattern",
3357 This calls the external C<grep -i> program and returns the
3360 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3361 [InitISOFS, Always, TestOutputList (
3362 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3363 "return lines matching a pattern",
3365 This calls the external C<egrep -i> program and returns the
3368 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3369 [InitISOFS, Always, TestOutputList (
3370 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3371 "return lines matching a pattern",
3373 This calls the external C<fgrep -i> program and returns the
3376 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3377 [InitISOFS, Always, TestOutputList (
3378 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3379 "return lines matching a pattern",
3381 This calls the external C<zgrep> program and returns the
3384 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3385 [InitISOFS, Always, TestOutputList (
3386 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3387 "return lines matching a pattern",
3389 This calls the external C<zegrep> program and returns the
3392 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3393 [InitISOFS, Always, TestOutputList (
3394 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3395 "return lines matching a pattern",
3397 This calls the external C<zfgrep> program and returns the
3400 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3401 [InitISOFS, Always, TestOutputList (
3402 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3403 "return lines matching a pattern",
3405 This calls the external C<zgrep -i> program and returns the
3408 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3409 [InitISOFS, Always, TestOutputList (
3410 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3411 "return lines matching a pattern",
3413 This calls the external C<zegrep -i> program and returns the
3416 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3417 [InitISOFS, Always, TestOutputList (
3418 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3419 "return lines matching a pattern",
3421 This calls the external C<zfgrep -i> program and returns the
3424 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3425 [InitISOFS, Always, TestOutput (
3426 [["realpath"; "/../directory"]], "/directory")],
3427 "canonicalized absolute pathname",
3429 Return the canonicalized absolute pathname of C<path>. The
3430 returned path has no C<.>, C<..> or symbolic link path elements.");
3432 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3433 [InitBasicFS, Always, TestOutputStruct (
3436 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437 "create a hard link",
3439 This command creates a hard link using the C<ln> command.");
3441 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3442 [InitBasicFS, Always, TestOutputStruct (
3445 ["ln_f"; "/a"; "/b"];
3446 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3447 "create a hard link",
3449 This command creates a hard link using the C<ln -f> command.
3450 The C<-f> option removes the link (C<linkname>) if it exists already.");
3452 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3453 [InitBasicFS, Always, TestOutputStruct (
3455 ["ln_s"; "a"; "/b"];
3456 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3457 "create a symbolic link",
3459 This command creates a symbolic link using the C<ln -s> command.");
3461 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3462 [InitBasicFS, Always, TestOutput (
3463 [["mkdir_p"; "/a/b"];
3464 ["touch"; "/a/b/c"];
3465 ["ln_sf"; "../d"; "/a/b/c"];
3466 ["readlink"; "/a/b/c"]], "../d")],
3467 "create a symbolic link",
3469 This command creates a symbolic link using the C<ln -sf> command,
3470 The C<-f> option removes the link (C<linkname>) if it exists already.");
3472 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3473 [] (* XXX tested above *),
3474 "read the target of a symbolic link",
3476 This command reads the target of a symbolic link.");
3478 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3479 [InitBasicFS, Always, TestOutputStruct (
3480 [["fallocate"; "/a"; "1000000"];
3481 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3482 "preallocate a file in the guest filesystem",
3484 This command preallocates a file (containing zero bytes) named
3485 C<path> of size C<len> bytes. If the file exists already, it
3488 Do not confuse this with the guestfish-specific
3489 C<alloc> command which allocates a file in the host and
3490 attaches it as a device.");
3492 ("swapon_device", (RErr, [Device "device"]), 170, [],
3493 [InitPartition, Always, TestRun (
3494 [["mkswap"; "/dev/sda1"];
3495 ["swapon_device"; "/dev/sda1"];
3496 ["swapoff_device"; "/dev/sda1"]])],
3497 "enable swap on device",
3499 This command enables the libguestfs appliance to use the
3500 swap device or partition named C<device>. The increased
3501 memory is made available for all commands, for example
3502 those run using C<guestfs_command> or C<guestfs_sh>.
3504 Note that you should not swap to existing guest swap
3505 partitions unless you know what you are doing. They may
3506 contain hibernation information, or other information that
3507 the guest doesn't want you to trash. You also risk leaking
3508 information about the host to the guest this way. Instead,
3509 attach a new host device to the guest and swap on that.");
3511 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3512 [], (* XXX tested by swapon_device *)
3513 "disable swap on device",
3515 This command disables the libguestfs appliance swap
3516 device or partition named C<device>.
3517 See C<guestfs_swapon_device>.");
3519 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3520 [InitBasicFS, Always, TestRun (
3521 [["fallocate"; "/swap"; "8388608"];
3522 ["mkswap_file"; "/swap"];
3523 ["swapon_file"; "/swap"];
3524 ["swapoff_file"; "/swap"]])],
3525 "enable swap on file",
3527 This command enables swap to a file.
3528 See C<guestfs_swapon_device> for other notes.");
3530 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3531 [], (* XXX tested by swapon_file *)
3532 "disable swap on file",
3534 This command disables the libguestfs appliance swap on file.");
3536 ("swapon_label", (RErr, [String "label"]), 174, [],
3537 [InitEmpty, Always, TestRun (
3538 [["part_disk"; "/dev/sdb"; "mbr"];
3539 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3540 ["swapon_label"; "swapit"];
3541 ["swapoff_label"; "swapit"];
3542 ["zero"; "/dev/sdb"];
3543 ["blockdev_rereadpt"; "/dev/sdb"]])],
3544 "enable swap on labeled swap partition",
3546 This command enables swap to a labeled swap partition.
3547 See C<guestfs_swapon_device> for other notes.");
3549 ("swapoff_label", (RErr, [String "label"]), 175, [],
3550 [], (* XXX tested by swapon_label *)
3551 "disable swap on labeled swap partition",
3553 This command disables the libguestfs appliance swap on
3554 labeled swap partition.");
3556 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3557 (let uuid = uuidgen () in
3558 [InitEmpty, Always, TestRun (
3559 [["mkswap_U"; uuid; "/dev/sdb"];
3560 ["swapon_uuid"; uuid];
3561 ["swapoff_uuid"; uuid]])]),
3562 "enable swap on swap partition by UUID",
3564 This command enables swap to a swap partition with the given UUID.
3565 See C<guestfs_swapon_device> for other notes.");
3567 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3568 [], (* XXX tested by swapon_uuid *)
3569 "disable swap on swap partition by UUID",
3571 This command disables the libguestfs appliance swap partition
3572 with the given UUID.");
3574 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3575 [InitBasicFS, Always, TestRun (
3576 [["fallocate"; "/swap"; "8388608"];
3577 ["mkswap_file"; "/swap"]])],
3578 "create a swap file",
3582 This command just writes a swap file signature to an existing
3583 file. To create the file itself, use something like C<guestfs_fallocate>.");
3585 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3586 [InitISOFS, Always, TestRun (
3587 [["inotify_init"; "0"]])],
3588 "create an inotify handle",
3590 This command creates a new inotify handle.
3591 The inotify subsystem can be used to notify events which happen to
3592 objects in the guest filesystem.
3594 C<maxevents> is the maximum number of events which will be
3595 queued up between calls to C<guestfs_inotify_read> or
3596 C<guestfs_inotify_files>.
3597 If this is passed as C<0>, then the kernel (or previously set)
3598 default is used. For Linux 2.6.29 the default was 16384 events.
3599 Beyond this limit, the kernel throws away events, but records
3600 the fact that it threw them away by setting a flag
3601 C<IN_Q_OVERFLOW> in the returned structure list (see
3602 C<guestfs_inotify_read>).
3604 Before any events are generated, you have to add some
3605 watches to the internal watch list. See:
3606 C<guestfs_inotify_add_watch>,
3607 C<guestfs_inotify_rm_watch> and
3608 C<guestfs_inotify_watch_all>.
3610 Queued up events should be read periodically by calling
3611 C<guestfs_inotify_read>
3612 (or C<guestfs_inotify_files> which is just a helpful
3613 wrapper around C<guestfs_inotify_read>). If you don't
3614 read the events out often enough then you risk the internal
3617 The handle should be closed after use by calling
3618 C<guestfs_inotify_close>. This also removes any
3619 watches automatically.
3621 See also L<inotify(7)> for an overview of the inotify interface
3622 as exposed by the Linux kernel, which is roughly what we expose
3623 via libguestfs. Note that there is one global inotify handle
3624 per libguestfs instance.");
3626 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3627 [InitBasicFS, Always, TestOutputList (
3628 [["inotify_init"; "0"];
3629 ["inotify_add_watch"; "/"; "1073741823"];
3632 ["inotify_files"]], ["a"; "b"])],
3633 "add an inotify watch",
3635 Watch C<path> for the events listed in C<mask>.
3637 Note that if C<path> is a directory then events within that
3638 directory are watched, but this does I<not> happen recursively
3639 (in subdirectories).
3641 Note for non-C or non-Linux callers: the inotify events are
3642 defined by the Linux kernel ABI and are listed in
3643 C</usr/include/sys/inotify.h>.");
3645 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3647 "remove an inotify watch",
3649 Remove a previously defined inotify watch.
3650 See C<guestfs_inotify_add_watch>.");
3652 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3654 "return list of inotify events",
3656 Return the complete queue of events that have happened
3657 since the previous read call.
3659 If no events have happened, this returns an empty list.
3661 I<Note>: In order to make sure that all events have been
3662 read, you must call this function repeatedly until it
3663 returns an empty list. The reason is that the call will
3664 read events up to the maximum appliance-to-host message
3665 size and leave remaining events in the queue.");
3667 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3669 "return list of watched files that had events",
3671 This function is a helpful wrapper around C<guestfs_inotify_read>
3672 which just returns a list of pathnames of objects that were
3673 touched. The returned pathnames are sorted and deduplicated.");
3675 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3677 "close the inotify handle",
3679 This closes the inotify handle which was previously
3680 opened by inotify_init. It removes all watches, throws
3681 away any pending events, and deallocates all resources.");
3683 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3685 "set SELinux security context",
3687 This sets the SELinux security context of the daemon
3688 to the string C<context>.
3690 See the documentation about SELINUX in L<guestfs(3)>.");
3692 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3694 "get SELinux security context",
3696 This gets the SELinux security context of the daemon.
3698 See the documentation about SELINUX in L<guestfs(3)>,
3699 and C<guestfs_setcon>");
3701 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3702 [InitEmpty, Always, TestOutput (
3703 [["part_disk"; "/dev/sda"; "mbr"];
3704 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3705 ["mount_options"; ""; "/dev/sda1"; "/"];
3706 ["write"; "/new"; "new file contents"];
3707 ["cat"; "/new"]], "new file contents")],
3708 "make a filesystem with block size",
3710 This call is similar to C<guestfs_mkfs>, but it allows you to
3711 control the block size of the resulting filesystem. Supported
3712 block sizes depend on the filesystem type, but typically they
3713 are C<1024>, C<2048> or C<4096> only.");
3715 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3716 [InitEmpty, Always, TestOutput (
3717 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718 ["mke2journal"; "4096"; "/dev/sda1"];
3719 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3720 ["mount_options"; ""; "/dev/sda2"; "/"];
3721 ["write"; "/new"; "new file contents"];
3722 ["cat"; "/new"]], "new file contents")],
3723 "make ext2/3/4 external journal",
3725 This creates an ext2 external journal on C<device>. It is equivalent
3728 mke2fs -O journal_dev -b blocksize device");
3730 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3731 [InitEmpty, Always, TestOutput (
3732 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3733 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3734 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3735 ["mount_options"; ""; "/dev/sda2"; "/"];
3736 ["write"; "/new"; "new file contents"];
3737 ["cat"; "/new"]], "new file contents")],
3738 "make ext2/3/4 external journal with label",
3740 This creates an ext2 external journal on C<device> with label C<label>.");
3742 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3743 (let uuid = uuidgen () in
3744 [InitEmpty, Always, TestOutput (
3745 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3746 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3747 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3748 ["mount_options"; ""; "/dev/sda2"; "/"];
3749 ["write"; "/new"; "new file contents"];
3750 ["cat"; "/new"]], "new file contents")]),
3751 "make ext2/3/4 external journal with UUID",
3753 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3755 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3757 "make ext2/3/4 filesystem with external journal",
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on C<journal>. It is equivalent
3763 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3765 See also C<guestfs_mke2journal>.");
3767 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3769 "make ext2/3/4 filesystem with external journal",
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal labeled C<label>.
3774 See also C<guestfs_mke2journal_L>.");
3776 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3778 "make ext2/3/4 filesystem with external journal",
3780 This creates an ext2/3/4 filesystem on C<device> with
3781 an external journal on the journal with UUID C<uuid>.
3783 See also C<guestfs_mke2journal_U>.");
3785 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3786 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3787 "load a kernel module",
3789 This loads a kernel module in the appliance.
3791 The kernel module must have been whitelisted when libguestfs
3792 was built (see C<appliance/kmod.whitelist.in> in the source).");
3794 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3795 [InitNone, Always, TestOutput (
3796 [["echo_daemon"; "This is a test"]], "This is a test"
3798 "echo arguments back to the client",
3800 This command concatenate the list of C<words> passed with single spaces between
3801 them and returns the resulting string.
3803 You can use this command to test the connection through to the daemon.
3805 See also C<guestfs_ping_daemon>.");
3807 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3808 [], (* There is a regression test for this. *)
3809 "find all files and directories, returning NUL-separated list",
3811 This command lists out all files and directories, recursively,
3812 starting at C<directory>, placing the resulting list in the
3813 external file called C<files>.
3815 This command works the same way as C<guestfs_find> with the
3816 following exceptions:
3822 The resulting list is written to an external file.
3826 Items (filenames) in the result are separated
3827 by C<\\0> characters. See L<find(1)> option I<-print0>.
3831 This command is not limited in the number of names that it
3836 The result list is not sorted.
3840 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3841 [InitISOFS, Always, TestOutput (
3842 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3843 InitISOFS, Always, TestOutput (
3844 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3845 InitISOFS, Always, TestOutput (
3846 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3847 InitISOFS, Always, TestLastFail (
3848 [["case_sensitive_path"; "/Known-1/"]]);
3849 InitBasicFS, Always, TestOutput (
3851 ["mkdir"; "/a/bbb"];
3852 ["touch"; "/a/bbb/c"];
3853 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3854 InitBasicFS, Always, TestOutput (
3856 ["mkdir"; "/a/bbb"];
3857 ["touch"; "/a/bbb/c"];
3858 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3859 InitBasicFS, Always, TestLastFail (
3861 ["mkdir"; "/a/bbb"];
3862 ["touch"; "/a/bbb/c"];
3863 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3864 "return true path on case-insensitive filesystem",
3866 This can be used to resolve case insensitive paths on
3867 a filesystem which is case sensitive. The use case is
3868 to resolve paths which you have read from Windows configuration
3869 files or the Windows Registry, to the true path.
3871 The command handles a peculiarity of the Linux ntfs-3g
3872 filesystem driver (and probably others), which is that although
3873 the underlying filesystem is case-insensitive, the driver
3874 exports the filesystem to Linux as case-sensitive.
3876 One consequence of this is that special directories such
3877 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3878 (or other things) depending on the precise details of how
3879 they were created. In Windows itself this would not be
3882 Bug or feature? You decide:
3883 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3885 This function resolves the true case of each element in the
3886 path and returns the case-sensitive path.
3888 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3889 might return C<\"/WINDOWS/system32\"> (the exact return value
3890 would depend on details of how the directories were originally
3891 created under Windows).
3894 This function does not handle drive names, backslashes etc.
3896 See also C<guestfs_realpath>.");
3898 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3899 [InitBasicFS, Always, TestOutput (
3900 [["vfs_type"; "/dev/sda1"]], "ext2")],
3901 "get the Linux VFS type corresponding to a mounted device",
3903 This command gets the block device type corresponding to
3904 a mounted device called C<device>.
3906 Usually the result is the name of the Linux VFS module that
3907 is used to mount this device (probably determined automatically
3908 if you used the C<guestfs_mount> call).");
3910 ("truncate", (RErr, [Pathname "path"]), 199, [],
3911 [InitBasicFS, Always, TestOutputStruct (
3912 [["write"; "/test"; "some stuff so size is not zero"];
3913 ["truncate"; "/test"];
3914 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3915 "truncate a file to zero size",
3917 This command truncates C<path> to a zero-length file. The
3918 file must exist already.");
3920 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3921 [InitBasicFS, Always, TestOutputStruct (
3922 [["touch"; "/test"];
3923 ["truncate_size"; "/test"; "1000"];
3924 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3925 "truncate a file to a particular size",
3927 This command truncates C<path> to size C<size> bytes. The file
3928 must exist already. If the file is smaller than C<size> then
3929 the file is extended to the required size with null bytes.");
3931 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3932 [InitBasicFS, Always, TestOutputStruct (
3933 [["touch"; "/test"];
3934 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3935 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3936 "set timestamp of a file with nanosecond precision",
3938 This command sets the timestamps of a file with nanosecond
3941 C<atsecs, atnsecs> are the last access time (atime) in secs and
3942 nanoseconds from the epoch.
3944 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3945 secs and nanoseconds from the epoch.
3947 If the C<*nsecs> field contains the special value C<-1> then
3948 the corresponding timestamp is set to the current time. (The
3949 C<*secs> field is ignored in this case).
3951 If the C<*nsecs> field contains the special value C<-2> then
3952 the corresponding timestamp is left unchanged. (The
3953 C<*secs> field is ignored in this case).");
3955 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3956 [InitBasicFS, Always, TestOutputStruct (
3957 [["mkdir_mode"; "/test"; "0o111"];
3958 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3959 "create a directory with a particular mode",
3961 This command creates a directory, setting the initial permissions
3962 of the directory to C<mode>.
3964 For common Linux filesystems, the actual mode which is set will
3965 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3966 interpret the mode in other ways.
3968 See also C<guestfs_mkdir>, C<guestfs_umask>");
3970 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3972 "change file owner and group",
3974 Change the file owner to C<owner> and group to C<group>.
3975 This is like C<guestfs_chown> but if C<path> is a symlink then
3976 the link itself is changed, not the target.
3978 Only numeric uid and gid are supported. If you want to use
3979 names, you will need to locate and parse the password file
3980 yourself (Augeas support makes this relatively easy).");
3982 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3984 "lstat on multiple files",
3986 This call allows you to perform the C<guestfs_lstat> operation
3987 on multiple files, where all files are in the directory C<path>.
3988 C<names> is the list of files from this directory.
3990 On return you get a list of stat structs, with a one-to-one
3991 correspondence to the C<names> list. If any name did not exist
3992 or could not be lstat'd, then the C<ino> field of that structure
3995 This call is intended for programs that want to efficiently
3996 list a directory contents without making many round-trips.
3997 See also C<guestfs_lxattrlist> for a similarly efficient call
3998 for getting extended attributes. Very long directory listings
3999 might cause the protocol message size to be exceeded, causing
4000 this call to fail. The caller must split up such requests
4001 into smaller groups of names.");
4003 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4005 "lgetxattr on multiple files",
4007 This call allows you to get the extended attributes
4008 of multiple files, where all files are in the directory C<path>.
4009 C<names> is the list of files from this directory.
4011 On return you get a flat list of xattr structs which must be
4012 interpreted sequentially. The first xattr struct always has a zero-length
4013 C<attrname>. C<attrval> in this struct is zero-length
4014 to indicate there was an error doing C<lgetxattr> for this
4015 file, I<or> is a C string which is a decimal number
4016 (the number of following attributes for this file, which could
4017 be C<\"0\">). Then after the first xattr struct are the
4018 zero or more attributes for the first named file.
4019 This repeats for the second and subsequent files.
4021 This call is intended for programs that want to efficiently
4022 list a directory contents without making many round-trips.
4023 See also C<guestfs_lstatlist> for a similarly efficient call
4024 for getting standard stats. Very long directory listings
4025 might cause the protocol message size to be exceeded, causing
4026 this call to fail. The caller must split up such requests
4027 into smaller groups of names.");
4029 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4031 "readlink on multiple files",
4033 This call allows you to do a C<readlink> operation
4034 on multiple files, where all files are in the directory C<path>.
4035 C<names> is the list of files from this directory.
4037 On return you get a list of strings, with a one-to-one
4038 correspondence to the C<names> list. Each string is the
4039 value of the symbol link.
4041 If the C<readlink(2)> operation fails on any name, then
4042 the corresponding result string is the empty string C<\"\">.
4043 However the whole operation is completed even if there
4044 were C<readlink(2)> errors, and so you can call this
4045 function with names where you don't know if they are
4046 symbolic links already (albeit slightly less efficient).
4048 This call is intended for programs that want to efficiently
4049 list a directory contents without making many round-trips.
4050 Very long directory listings might cause the protocol
4051 message size to be exceeded, causing
4052 this call to fail. The caller must split up such requests
4053 into smaller groups of names.");
4055 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4056 [InitISOFS, Always, TestOutputBuffer (
4057 [["pread"; "/known-4"; "1"; "3"]], "\n");
4058 InitISOFS, Always, TestOutputBuffer (
4059 [["pread"; "/empty"; "0"; "100"]], "")],
4060 "read part of a file",
4062 This command lets you read part of a file. It reads C<count>
4063 bytes of the file, starting at C<offset>, from file C<path>.
4065 This may read fewer bytes than requested. For further details
4066 see the L<pread(2)> system call.
4068 See also C<guestfs_pwrite>.");
4070 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4071 [InitEmpty, Always, TestRun (
4072 [["part_init"; "/dev/sda"; "gpt"]])],
4073 "create an empty partition table",
4075 This creates an empty partition table on C<device> of one of the
4076 partition types listed below. Usually C<parttype> should be
4077 either C<msdos> or C<gpt> (for large disks).
4079 Initially there are no partitions. Following this, you should
4080 call C<guestfs_part_add> for each partition required.
4082 Possible values for C<parttype> are:
4086 =item B<efi> | B<gpt>
4088 Intel EFI / GPT partition table.
4090 This is recommended for >= 2 TB partitions that will be accessed
4091 from Linux and Intel-based Mac OS X. It also has limited backwards
4092 compatibility with the C<mbr> format.
4094 =item B<mbr> | B<msdos>
4096 The standard PC \"Master Boot Record\" (MBR) format used
4097 by MS-DOS and Windows. This partition type will B<only> work
4098 for device sizes up to 2 TB. For large disks we recommend
4103 Other partition table types that may work but are not
4112 =item B<amiga> | B<rdb>
4114 Amiga \"Rigid Disk Block\" format.
4122 DASD, used on IBM mainframes.
4130 Old Mac partition format. Modern Macs use C<gpt>.
4134 NEC PC-98 format, common in Japan apparently.
4142 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4143 [InitEmpty, Always, TestRun (
4144 [["part_init"; "/dev/sda"; "mbr"];
4145 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4146 InitEmpty, Always, TestRun (
4147 [["part_init"; "/dev/sda"; "gpt"];
4148 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4149 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4150 InitEmpty, Always, TestRun (
4151 [["part_init"; "/dev/sda"; "mbr"];
4152 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4153 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4154 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4155 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4156 "add a partition to the device",
4158 This command adds a partition to C<device>. If there is no partition
4159 table on the device, call C<guestfs_part_init> first.
4161 The C<prlogex> parameter is the type of partition. Normally you
4162 should pass C<p> or C<primary> here, but MBR partition tables also
4163 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4166 C<startsect> and C<endsect> are the start and end of the partition
4167 in I<sectors>. C<endsect> may be negative, which means it counts
4168 backwards from the end of the disk (C<-1> is the last sector).
4170 Creating a partition which covers the whole disk is not so easy.
4171 Use C<guestfs_part_disk> to do that.");
4173 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4174 [InitEmpty, Always, TestRun (
4175 [["part_disk"; "/dev/sda"; "mbr"]]);
4176 InitEmpty, Always, TestRun (
4177 [["part_disk"; "/dev/sda"; "gpt"]])],
4178 "partition whole disk with a single primary partition",
4180 This command is simply a combination of C<guestfs_part_init>
4181 followed by C<guestfs_part_add> to create a single primary partition
4182 covering the whole disk.
4184 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4185 but other possible values are described in C<guestfs_part_init>.");
4187 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4188 [InitEmpty, Always, TestRun (
4189 [["part_disk"; "/dev/sda"; "mbr"];
4190 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4191 "make a partition bootable",
4193 This sets the bootable flag on partition numbered C<partnum> on
4194 device C<device>. Note that partitions are numbered from 1.
4196 The bootable flag is used by some operating systems (notably
4197 Windows) to determine which partition to boot from. It is by
4198 no means universally recognized.");
4200 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4201 [InitEmpty, Always, TestRun (
4202 [["part_disk"; "/dev/sda"; "gpt"];
4203 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4204 "set partition name",
4206 This sets the partition name on partition numbered C<partnum> on
4207 device C<device>. Note that partitions are numbered from 1.
4209 The partition name can only be set on certain types of partition
4210 table. This works on C<gpt> but not on C<mbr> partitions.");
4212 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4213 [], (* XXX Add a regression test for this. *)
4214 "list partitions on a device",
4216 This command parses the partition table on C<device> and
4217 returns the list of partitions found.
4219 The fields in the returned structure are:
4225 Partition number, counting from 1.
4229 Start of the partition I<in bytes>. To get sectors you have to
4230 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4234 End of the partition in bytes.
4238 Size of the partition in bytes.
4242 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4243 [InitEmpty, Always, TestOutput (
4244 [["part_disk"; "/dev/sda"; "gpt"];
4245 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4246 "get the partition table type",
4248 This command examines the partition table on C<device> and
4249 returns the partition table type (format) being used.
4251 Common return values include: C<msdos> (a DOS/Windows style MBR
4252 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4253 values are possible, although unusual. See C<guestfs_part_init>
4256 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4257 [InitBasicFS, Always, TestOutputBuffer (
4258 [["fill"; "0x63"; "10"; "/test"];
4259 ["read_file"; "/test"]], "cccccccccc")],
4260 "fill a file with octets",
4262 This command creates a new file called C<path>. The initial
4263 content of the file is C<len> octets of C<c>, where C<c>
4264 must be a number in the range C<[0..255]>.
4266 To fill a file with zero bytes (sparsely), it is
4267 much more efficient to use C<guestfs_truncate_size>.
4268 To create a file with a pattern of repeating bytes
4269 use C<guestfs_fill_pattern>.");
4271 ("available", (RErr, [StringList "groups"]), 216, [],
4272 [InitNone, Always, TestRun [["available"; ""]]],
4273 "test availability of some parts of the API",
4275 This command is used to check the availability of some
4276 groups of functionality in the appliance, which not all builds of
4277 the libguestfs appliance will be able to provide.
4279 The libguestfs groups, and the functions that those
4280 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4281 You can also fetch this list at runtime by calling
4282 C<guestfs_available_all_groups>.
4284 The argument C<groups> is a list of group names, eg:
4285 C<[\"inotify\", \"augeas\"]> would check for the availability of
4286 the Linux inotify functions and Augeas (configuration file
4289 The command returns no error if I<all> requested groups are available.
4291 It fails with an error if one or more of the requested
4292 groups is unavailable in the appliance.
4294 If an unknown group name is included in the
4295 list of groups then an error is always returned.
4303 You must call C<guestfs_launch> before calling this function.
4305 The reason is because we don't know what groups are
4306 supported by the appliance/daemon until it is running and can
4311 If a group of functions is available, this does not necessarily
4312 mean that they will work. You still have to check for errors
4313 when calling individual API functions even if they are
4318 It is usually the job of distro packagers to build
4319 complete functionality into the libguestfs appliance.
4320 Upstream libguestfs, if built from source with all
4321 requirements satisfied, will support everything.
4325 This call was added in version C<1.0.80>. In previous
4326 versions of libguestfs all you could do would be to speculatively
4327 execute a command to find out if the daemon implemented it.
4328 See also C<guestfs_version>.
4332 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4333 [InitBasicFS, Always, TestOutputBuffer (
4334 [["write"; "/src"; "hello, world"];
4335 ["dd"; "/src"; "/dest"];
4336 ["read_file"; "/dest"]], "hello, world")],
4337 "copy from source to destination using dd",
4339 This command copies from one source device or file C<src>
4340 to another destination device or file C<dest>. Normally you
4341 would use this to copy to or from a device or partition, for
4342 example to duplicate a filesystem.
4344 If the destination is a device, it must be as large or larger
4345 than the source file or device, otherwise the copy will fail.
4346 This command cannot do partial copies (see C<guestfs_copy_size>).");
4348 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4349 [InitBasicFS, Always, TestOutputInt (
4350 [["write"; "/file"; "hello, world"];
4351 ["filesize"; "/file"]], 12)],
4352 "return the size of the file in bytes",
4354 This command returns the size of C<file> in bytes.
4356 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4357 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4358 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4360 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4361 [InitBasicFSonLVM, Always, TestOutputList (
4362 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4363 ["lvs"]], ["/dev/VG/LV2"])],
4364 "rename an LVM logical volume",
4366 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4368 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4369 [InitBasicFSonLVM, Always, TestOutputList (
4371 ["vg_activate"; "false"; "VG"];
4372 ["vgrename"; "VG"; "VG2"];
4373 ["vg_activate"; "true"; "VG2"];
4374 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4375 ["vgs"]], ["VG2"])],
4376 "rename an LVM volume group",
4378 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4380 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4381 [InitISOFS, Always, TestOutputBuffer (
4382 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4383 "list the contents of a single file in an initrd",
4385 This command unpacks the file C<filename> from the initrd file
4386 called C<initrdpath>. The filename must be given I<without> the
4387 initial C</> character.
4389 For example, in guestfish you could use the following command
4390 to examine the boot script (usually called C</init>)
4391 contained in a Linux initrd or initramfs image:
4393 initrd-cat /boot/initrd-<version>.img init
4395 See also C<guestfs_initrd_list>.");
4397 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4399 "get the UUID of a physical volume",
4401 This command returns the UUID of the LVM PV C<device>.");
4403 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4405 "get the UUID of a volume group",
4407 This command returns the UUID of the LVM VG named C<vgname>.");
4409 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4411 "get the UUID of a logical volume",
4413 This command returns the UUID of the LVM LV C<device>.");
4415 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4417 "get the PV UUIDs containing the volume group",
4419 Given a VG called C<vgname>, this returns the UUIDs of all
4420 the physical volumes that this volume group resides on.
4422 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4423 calls to associate physical volumes and volume groups.
4425 See also C<guestfs_vglvuuids>.");
4427 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4429 "get the LV UUIDs of all LVs in the volume group",
4431 Given a VG called C<vgname>, this returns the UUIDs of all
4432 the logical volumes created in this volume group.
4434 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4435 calls to associate logical volumes and volume groups.
4437 See also C<guestfs_vgpvuuids>.");
4439 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4440 [InitBasicFS, Always, TestOutputBuffer (
4441 [["write"; "/src"; "hello, world"];
4442 ["copy_size"; "/src"; "/dest"; "5"];
4443 ["read_file"; "/dest"]], "hello")],
4444 "copy size bytes from source to destination using dd",
4446 This command copies exactly C<size> bytes from one source device
4447 or file C<src> to another destination device or file C<dest>.
4449 Note this will fail if the source is too short or if the destination
4450 is not large enough.");
4452 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4453 [InitBasicFSonLVM, Always, TestRun (
4454 [["zero_device"; "/dev/VG/LV"]])],
4455 "write zeroes to an entire device",
4457 This command writes zeroes over the entire C<device>. Compare
4458 with C<guestfs_zero> which just zeroes the first few blocks of
4461 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4462 [InitBasicFS, Always, TestOutput (
4463 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4464 ["cat"; "/hello"]], "hello\n")],
4465 "unpack compressed tarball to directory",
4467 This command uploads and unpacks local file C<tarball> (an
4468 I<xz compressed> tar file) into C<directory>.");
4470 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4472 "pack directory into compressed tarball",
4474 This command packs the contents of C<directory> and downloads
4475 it to local file C<tarball> (as an xz compressed tar archive).");
4477 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4479 "resize an NTFS filesystem",
4481 This command resizes an NTFS filesystem, expanding or
4482 shrinking it to the size of the underlying device.
4483 See also L<ntfsresize(8)>.");
4485 ("vgscan", (RErr, []), 232, [],
4486 [InitEmpty, Always, TestRun (
4488 "rescan for LVM physical volumes, volume groups and logical volumes",
4490 This rescans all block devices and rebuilds the list of LVM
4491 physical volumes, volume groups and logical volumes.");
4493 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4494 [InitEmpty, Always, TestRun (
4495 [["part_init"; "/dev/sda"; "mbr"];
4496 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4497 ["part_del"; "/dev/sda"; "1"]])],
4498 "delete a partition",
4500 This command deletes the partition numbered C<partnum> on C<device>.
4502 Note that in the case of MBR partitioning, deleting an
4503 extended partition also deletes any logical partitions
4506 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4507 [InitEmpty, Always, TestOutputTrue (
4508 [["part_init"; "/dev/sda"; "mbr"];
4509 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4510 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4511 ["part_get_bootable"; "/dev/sda"; "1"]])],
4512 "return true if a partition is bootable",
4514 This command returns true if the partition C<partnum> on
4515 C<device> has the bootable flag set.
4517 See also C<guestfs_part_set_bootable>.");
4519 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4520 [InitEmpty, Always, TestOutputInt (
4521 [["part_init"; "/dev/sda"; "mbr"];
4522 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4523 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4524 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4525 "get the MBR type byte (ID byte) from a partition",
4527 Returns the MBR type byte (also known as the ID byte) from
4528 the numbered partition C<partnum>.
4530 Note that only MBR (old DOS-style) partitions have type bytes.
4531 You will get undefined results for other partition table
4532 types (see C<guestfs_part_get_parttype>).");
4534 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4535 [], (* tested by part_get_mbr_id *)
4536 "set the MBR type byte (ID byte) of a partition",
4538 Sets the MBR type byte (also known as the ID byte) of
4539 the numbered partition C<partnum> to C<idbyte>. Note
4540 that the type bytes quoted in most documentation are
4541 in fact hexadecimal numbers, but usually documented
4542 without any leading \"0x\" which might be confusing.
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 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4549 [InitISOFS, Always, TestOutput (
4550 [["checksum_device"; "md5"; "/dev/sdd"]],
4551 (Digest.to_hex (Digest.file "images/test.iso")))],
4552 "compute MD5, SHAx or CRC checksum of the contents of a device",
4554 This call computes the MD5, SHAx or CRC checksum of the
4555 contents of the device named C<device>. For the types of
4556 checksums supported see the C<guestfs_checksum> command.");
4558 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4559 [InitNone, Always, TestRun (
4560 [["part_disk"; "/dev/sda"; "mbr"];
4561 ["pvcreate"; "/dev/sda1"];
4562 ["vgcreate"; "VG"; "/dev/sda1"];
4563 ["lvcreate"; "LV"; "VG"; "10"];
4564 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4565 "expand an LV to fill free space",
4567 This expands an existing logical volume C<lv> so that it fills
4568 C<pc>% of the remaining free space in the volume group. Commonly
4569 you would call this with pc = 100 which expands the logical volume
4570 as much as possible, using all remaining free space in the volume
4573 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4574 [], (* XXX Augeas code needs tests. *)
4575 "clear Augeas path",
4577 Set the value associated with C<path> to C<NULL>. This
4578 is the same as the L<augtool(1)> C<clear> command.");
4580 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4581 [InitEmpty, Always, TestOutputInt (
4582 [["get_umask"]], 0o22)],
4583 "get the current umask",
4585 Return the current umask. By default the umask is C<022>
4586 unless it has been set by calling C<guestfs_umask>.");
4588 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4590 "upload a file to the appliance (internal use only)",
4592 The C<guestfs_debug_upload> command uploads a file to
4593 the libguestfs appliance.
4595 There is no comprehensive help for this command. You have
4596 to look at the file C<daemon/debug.c> in the libguestfs source
4597 to find out what it is for.");
4599 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4600 [InitBasicFS, Always, TestOutput (
4601 [["base64_in"; "../images/hello.b64"; "/hello"];
4602 ["cat"; "/hello"]], "hello\n")],
4603 "upload base64-encoded data to file",
4605 This command uploads base64-encoded data from C<base64file>
4608 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4610 "download file and encode as base64",
4612 This command downloads the contents of C<filename>, writing
4613 it out to local file C<base64file> encoded as base64.");
4615 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4617 "compute MD5, SHAx or CRC checksum of files in a directory",
4619 This command computes the checksums of all regular files in
4620 C<directory> and then emits a list of those checksums to
4621 the local output file C<sumsfile>.
4623 This can be used for verifying the integrity of a virtual
4624 machine. However to be properly secure you should pay
4625 attention to the output of the checksum command (it uses
4626 the ones from GNU coreutils). In particular when the
4627 filename is not printable, coreutils uses a special
4628 backslash syntax. For more information, see the GNU
4629 coreutils info file.");
4631 ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4632 [InitBasicFS, Always, TestOutputBuffer (
4633 [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4634 ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4635 "fill a file with a repeating pattern of bytes",
4637 This function is like C<guestfs_fill> except that it creates
4638 a new file of length C<len> containing the repeating pattern
4639 of bytes in C<pattern>. The pattern is truncated if necessary
4640 to ensure the length of the file is exactly C<len> bytes.");
4642 ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4643 [InitBasicFS, Always, TestOutput (
4644 [["write"; "/new"; "new file contents"];
4645 ["cat"; "/new"]], "new file contents");
4646 InitBasicFS, Always, TestOutput (
4647 [["write"; "/new"; "\nnew file contents\n"];
4648 ["cat"; "/new"]], "\nnew file contents\n");
4649 InitBasicFS, Always, TestOutput (
4650 [["write"; "/new"; "\n\n"];
4651 ["cat"; "/new"]], "\n\n");
4652 InitBasicFS, Always, TestOutput (
4653 [["write"; "/new"; ""];
4654 ["cat"; "/new"]], "");
4655 InitBasicFS, Always, TestOutput (
4656 [["write"; "/new"; "\n\n\n"];
4657 ["cat"; "/new"]], "\n\n\n");
4658 InitBasicFS, Always, TestOutput (
4659 [["write"; "/new"; "\n"];
4660 ["cat"; "/new"]], "\n")],
4661 "create a new file",
4663 This call creates a file called C<path>. The content of the
4664 file is the string C<content> (which can contain any 8 bit data).");
4666 ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4667 [InitBasicFS, Always, TestOutput (
4668 [["write"; "/new"; "new file contents"];
4669 ["pwrite"; "/new"; "data"; "4"];
4670 ["cat"; "/new"]], "new data contents");
4671 InitBasicFS, Always, TestOutput (
4672 [["write"; "/new"; "new file contents"];
4673 ["pwrite"; "/new"; "is extended"; "9"];
4674 ["cat"; "/new"]], "new file is extended");
4675 InitBasicFS, Always, TestOutput (
4676 [["write"; "/new"; "new file contents"];
4677 ["pwrite"; "/new"; ""; "4"];
4678 ["cat"; "/new"]], "new file contents")],
4679 "write to part of a file",
4681 This command writes to part of a file. It writes the data
4682 buffer C<content> to the file C<path> starting at offset C<offset>.
4684 This command implements the L<pwrite(2)> system call, and like
4685 that system call it may not write the full data requested. The
4686 return value is the number of bytes that were actually written
4687 to the file. This could even be 0, although short writes are
4688 unlikely for regular files in ordinary circumstances.
4690 See also C<guestfs_pread>.");
4692 ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4694 "resize an ext2/ext3 filesystem (with size)",
4696 This command is the same as C<guestfs_resize2fs> except that it
4697 allows you to specify the new size (in bytes) explicitly.");
4699 ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4701 "resize an LVM physical volume (with size)",
4703 This command is the same as C<guestfs_pvresize> except that it
4704 allows you to specify the new size (in bytes) explicitly.");
4706 ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4708 "resize an NTFS filesystem (with size)",
4710 This command is the same as C<guestfs_ntfsresize> except that it
4711 allows you to specify the new size (in bytes) explicitly.");
4713 ("available_all_groups", (RStringList "groups", []), 251, [],
4715 "return a list of all optional groups",
4717 This command returns a list of all optional groups that this
4718 daemon knows about. Note this returns both supported and unsupported
4719 groups. To find out which ones the daemon can actually support
4720 you have to call C<guestfs_available> on each member of the
4723 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4727 let all_functions = non_daemon_functions @ daemon_functions
4729 (* In some places we want the functions to be displayed sorted
4730 * alphabetically, so this is useful:
4732 let all_functions_sorted =
4733 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4734 compare n1 n2) all_functions
4736 (* This is used to generate the src/MAX_PROC_NR file which
4737 * contains the maximum procedure number, a surrogate for the
4738 * ABI version number. See src/Makefile.am for the details.
4741 let proc_nrs = List.map (
4742 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4743 ) daemon_functions in
4744 List.fold_left max 0 proc_nrs
4746 (* Field types for structures. *)
4748 | FChar (* C 'char' (really, a 7 bit byte). *)
4749 | FString (* nul-terminated ASCII string, NOT NULL. *)
4750 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4755 | FBytes (* Any int measure that counts bytes. *)
4756 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4757 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4759 (* Because we generate extra parsing code for LVM command line tools,
4760 * we have to pull out the LVM columns separately here.
4770 "pv_attr", FString (* XXX *);
4771 "pv_pe_count", FInt64;
4772 "pv_pe_alloc_count", FInt64;
4775 "pv_mda_count", FInt64;
4776 "pv_mda_free", FBytes;
4777 (* Not in Fedora 10:
4778 "pv_mda_size", FBytes;
4785 "vg_attr", FString (* XXX *);
4788 "vg_sysid", FString;
4789 "vg_extent_size", FBytes;
4790 "vg_extent_count", FInt64;
4791 "vg_free_count", FInt64;
4796 "snap_count", FInt64;
4799 "vg_mda_count", FInt64;
4800 "vg_mda_free", FBytes;
4801 (* Not in Fedora 10:
4802 "vg_mda_size", FBytes;
4808 "lv_attr", FString (* XXX *);
4811 "lv_kernel_major", FInt64;
4812 "lv_kernel_minor", FInt64;
4814 "seg_count", FInt64;
4816 "snap_percent", FOptPercent;
4817 "copy_percent", FOptPercent;
4820 "mirror_log", FString;
4824 (* Names and fields in all structures (in RStruct and RStructList)
4828 (* The old RIntBool return type, only ever used for aug_defnode. Do
4829 * not use this struct in any new code.
4832 "i", FInt32; (* for historical compatibility *)
4833 "b", FInt32; (* for historical compatibility *)
4836 (* LVM PVs, VGs, LVs. *)
4837 "lvm_pv", lvm_pv_cols;
4838 "lvm_vg", lvm_vg_cols;
4839 "lvm_lv", lvm_lv_cols;
4841 (* Column names and types from stat structures.
4842 * NB. Can't use things like 'st_atime' because glibc header files
4843 * define some of these as macros. Ugh.
4874 (* Column names in dirent structure. *)
4877 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4882 (* Version numbers. *)
4890 (* Extended attribute. *)
4892 "attrname", FString;
4896 (* Inotify events. *)
4900 "in_cookie", FUInt32;
4904 (* Partition table entry. *)
4907 "part_start", FBytes;
4909 "part_size", FBytes;
4911 ] (* end of structs *)
4913 (* Ugh, Java has to be different ..
4914 * These names are also used by the Haskell bindings.
4916 let java_structs = [
4917 "int_bool", "IntBool";
4922 "statvfs", "StatVFS";
4924 "version", "Version";
4926 "inotify_event", "INotifyEvent";
4927 "partition", "Partition";
4930 (* What structs are actually returned. *)
4931 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4933 (* Returns a list of RStruct/RStructList structs that are returned
4934 * by any function. Each element of returned list is a pair:
4936 * (structname, RStructOnly)
4937 * == there exists function which returns RStruct (_, structname)
4938 * (structname, RStructListOnly)
4939 * == there exists function which returns RStructList (_, structname)
4940 * (structname, RStructAndList)
4941 * == there are functions returning both RStruct (_, structname)
4942 * and RStructList (_, structname)
4944 let rstructs_used_by functions =
4945 (* ||| is a "logical OR" for rstructs_used_t *)
4949 | _, RStructAndList -> RStructAndList
4950 | RStructOnly, RStructListOnly
4951 | RStructListOnly, RStructOnly -> RStructAndList
4952 | RStructOnly, RStructOnly -> RStructOnly
4953 | RStructListOnly, RStructListOnly -> RStructListOnly
4956 let h = Hashtbl.create 13 in
4958 (* if elem->oldv exists, update entry using ||| operator,
4959 * else just add elem->newv to the hash
4961 let update elem newv =
4962 try let oldv = Hashtbl.find h elem in
4963 Hashtbl.replace h elem (newv ||| oldv)
4964 with Not_found -> Hashtbl.add h elem newv
4968 fun (_, style, _, _, _, _, _) ->
4969 match fst style with
4970 | RStruct (_, structname) -> update structname RStructOnly
4971 | RStructList (_, structname) -> update structname RStructListOnly
4975 (* return key->values as a list of (key,value) *)
4976 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4978 (* Used for testing language bindings. *)
4980 | CallString of string
4981 | CallOptString of string option
4982 | CallStringList of string list
4984 | CallInt64 of int64
4986 | CallBuffer of string
4988 (* Used to memoize the result of pod2text. *)
4989 let pod2text_memo_filename = "src/.pod2text.data"
4990 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4992 let chan = open_in pod2text_memo_filename in
4993 let v = input_value chan in
4997 _ -> Hashtbl.create 13
4998 let pod2text_memo_updated () =
4999 let chan = open_out pod2text_memo_filename in
5000 output_value chan pod2text_memo;
5003 (* Useful functions.
5004 * Note we don't want to use any external OCaml libraries which
5005 * makes this a bit harder than it should be.
5007 module StringMap = Map.Make (String)
5009 let failwithf fs = ksprintf failwith fs
5011 let unique = let i = ref 0 in fun () -> incr i; !i
5013 let replace_char s c1 c2 =
5014 let s2 = String.copy s in
5015 let r = ref false in
5016 for i = 0 to String.length s2 - 1 do
5017 if String.unsafe_get s2 i = c1 then (
5018 String.unsafe_set s2 i c2;
5022 if not !r then s else s2
5026 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5028 let triml ?(test = isspace) str =
5030 let n = ref (String.length str) in
5031 while !n > 0 && test str.[!i]; do
5036 else String.sub str !i !n
5038 let trimr ?(test = isspace) str =
5039 let n = ref (String.length str) in
5040 while !n > 0 && test str.[!n-1]; do
5043 if !n = String.length str then str
5044 else String.sub str 0 !n
5046 let trim ?(test = isspace) str =
5047 trimr ~test (triml ~test str)
5049 let rec find s sub =
5050 let len = String.length s in
5051 let sublen = String.length sub in
5053 if i <= len-sublen then (
5055 if j < sublen then (
5056 if s.[i+j] = sub.[j] then loop2 (j+1)
5062 if r = -1 then loop (i+1) else r
5068 let rec replace_str s s1 s2 =
5069 let len = String.length s in
5070 let sublen = String.length s1 in
5071 let i = find s s1 in
5074 let s' = String.sub s 0 i in
5075 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5076 s' ^ s2 ^ replace_str s'' s1 s2
5079 let rec string_split sep str =
5080 let len = String.length str in
5081 let seplen = String.length sep in
5082 let i = find str sep in
5083 if i = -1 then [str]
5085 let s' = String.sub str 0 i in
5086 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5087 s' :: string_split sep s''
5090 let files_equal n1 n2 =
5091 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5092 match Sys.command cmd with
5095 | i -> failwithf "%s: failed with error code %d" cmd i
5097 let rec filter_map f = function
5101 | Some y -> y :: filter_map f xs
5102 | None -> filter_map f xs
5104 let rec find_map f = function
5105 | [] -> raise Not_found
5109 | None -> find_map f xs
5112 let rec loop i = function
5114 | x :: xs -> f i x; loop (i+1) xs
5119 let rec loop i = function
5121 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5125 let count_chars c str =
5126 let count = ref 0 in
5127 for i = 0 to String.length str - 1 do
5128 if c = String.unsafe_get str i then incr count
5134 for i = 0 to String.length str - 1 do
5135 let c = String.unsafe_get str i in
5140 let map_chars f str =
5141 List.map f (explode str)
5143 let name_of_argt = function
5144 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5145 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5146 | FileIn n | FileOut n | BufferIn n -> n
5148 let java_name_of_struct typ =
5149 try List.assoc typ java_structs
5152 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5154 let cols_of_struct typ =
5155 try List.assoc typ structs
5157 failwithf "cols_of_struct: unknown struct %s" typ
5159 let seq_of_test = function
5160 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5161 | TestOutputListOfDevices (s, _)
5162 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5163 | TestOutputTrue s | TestOutputFalse s
5164 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5165 | TestOutputStruct (s, _)
5166 | TestLastFail s -> s
5168 (* Handling for function flags. *)
5169 let protocol_limit_warning =
5170 "Because of the message protocol, there is a transfer limit
5171 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5173 let danger_will_robinson =
5174 "B<This command is dangerous. Without careful use you
5175 can easily destroy all your data>."
5177 let deprecation_notice flags =
5180 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5182 sprintf "This function is deprecated.
5183 In new code, use the C<%s> call instead.
5185 Deprecated functions will not be removed from the API, but the
5186 fact that they are deprecated indicates that there are problems
5187 with correct use of these functions." alt in
5192 (* Create list of optional groups. *)
5194 let h = Hashtbl.create 13 in
5196 fun (name, _, _, flags, _, _, _) ->
5200 let names = try Hashtbl.find h group with Not_found -> [] in
5201 Hashtbl.replace h group (name :: names)
5205 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5208 fun group -> group, List.sort compare (Hashtbl.find h group)
5210 List.sort (fun x y -> compare (fst x) (fst y)) groups
5212 (* Check function names etc. for consistency. *)
5213 let check_functions () =
5214 let contains_uppercase str =
5215 let len = String.length str in
5217 if i >= len then false
5220 if c >= 'A' && c <= 'Z' then true
5227 (* Check function names. *)
5229 fun (name, _, _, _, _, _, _) ->
5230 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5231 failwithf "function name %s does not need 'guestfs' prefix" name;
5233 failwithf "function name is empty";
5234 if name.[0] < 'a' || name.[0] > 'z' then
5235 failwithf "function name %s must start with lowercase a-z" name;
5236 if String.contains name '-' then
5237 failwithf "function name %s should not contain '-', use '_' instead."
5241 (* Check function parameter/return names. *)
5243 fun (name, style, _, _, _, _, _) ->
5244 let check_arg_ret_name n =
5245 if contains_uppercase n then
5246 failwithf "%s param/ret %s should not contain uppercase chars"
5248 if String.contains n '-' || String.contains n '_' then
5249 failwithf "%s param/ret %s should not contain '-' or '_'"
5252 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;
5253 if n = "int" || n = "char" || n = "short" || n = "long" then
5254 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5255 if n = "i" || n = "n" then
5256 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5257 if n = "argv" || n = "args" then
5258 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5260 (* List Haskell, OCaml and C keywords here.
5261 * http://www.haskell.org/haskellwiki/Keywords
5262 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5263 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5264 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5265 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5266 * Omitting _-containing words, since they're handled above.
5267 * Omitting the OCaml reserved word, "val", is ok,
5268 * and saves us from renaming several parameters.
5271 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5272 "char"; "class"; "const"; "constraint"; "continue"; "data";
5273 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5274 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5275 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5276 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5277 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5279 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5280 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5281 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5282 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5283 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5284 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5285 "volatile"; "when"; "where"; "while";
5287 if List.mem n reserved then
5288 failwithf "%s has param/ret using reserved word %s" name n;
5291 (match fst style with
5293 | RInt n | RInt64 n | RBool n
5294 | RConstString n | RConstOptString n | RString n
5295 | RStringList n | RStruct (n, _) | RStructList (n, _)
5296 | RHashtable n | RBufferOut n ->
5297 check_arg_ret_name n
5299 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5302 (* Check short descriptions. *)
5304 fun (name, _, _, _, _, shortdesc, _) ->
5305 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5306 failwithf "short description of %s should begin with lowercase." name;
5307 let c = shortdesc.[String.length shortdesc-1] in
5308 if c = '\n' || c = '.' then
5309 failwithf "short description of %s should not end with . or \\n." name
5312 (* Check long descriptions. *)
5314 fun (name, _, _, _, _, _, longdesc) ->
5315 if longdesc.[String.length longdesc-1] = '\n' then
5316 failwithf "long description of %s should not end with \\n." name
5319 (* Check proc_nrs. *)
5321 fun (name, _, proc_nr, _, _, _, _) ->
5322 if proc_nr <= 0 then
5323 failwithf "daemon function %s should have proc_nr > 0" name
5327 fun (name, _, proc_nr, _, _, _, _) ->
5328 if proc_nr <> -1 then
5329 failwithf "non-daemon function %s should have proc_nr -1" name
5330 ) non_daemon_functions;
5333 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5336 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5337 let rec loop = function
5340 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5342 | (name1,nr1) :: (name2,nr2) :: _ ->
5343 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5351 (* Ignore functions that have no tests. We generate a
5352 * warning when the user does 'make check' instead.
5354 | name, _, _, _, [], _, _ -> ()
5355 | name, _, _, _, tests, _, _ ->
5359 match seq_of_test test with
5361 failwithf "%s has a test containing an empty sequence" name
5362 | cmds -> List.map List.hd cmds
5364 let funcs = List.flatten funcs in
5366 let tested = List.mem name funcs in
5369 failwithf "function %s has tests but does not test itself" name
5372 (* 'pr' prints to the current output file. *)
5373 let chan = ref Pervasives.stdout
5378 let i = count_chars '\n' str in
5379 lines := !lines + i;
5380 output_string !chan str
5383 let copyright_years =
5384 let this_year = 1900 + (localtime (time ())).tm_year in
5385 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5387 (* Generate a header block in a number of standard styles. *)
5388 type comment_style =
5389 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5390 type license = GPLv2plus | LGPLv2plus
5392 let generate_header ?(extra_inputs = []) comment license =
5393 let inputs = "src/generator.ml" :: extra_inputs in
5394 let c = match comment with
5395 | CStyle -> pr "/* "; " *"
5396 | CPlusPlusStyle -> pr "// "; "//"
5397 | HashStyle -> pr "# "; "#"
5398 | OCamlStyle -> pr "(* "; " *"
5399 | HaskellStyle -> pr "{- "; " " in
5400 pr "libguestfs generated file\n";
5401 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5402 List.iter (pr "%s %s\n" c) inputs;
5403 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5405 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5409 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5410 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5411 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5412 pr "%s (at your option) any later version.\n" c;
5414 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5415 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5416 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5417 pr "%s GNU General Public License for more details.\n" c;
5419 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5420 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5421 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5424 pr "%s This library is free software; you can redistribute it and/or\n" c;
5425 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5426 pr "%s License as published by the Free Software Foundation; either\n" c;
5427 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5429 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5430 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5431 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5432 pr "%s Lesser General Public License for more details.\n" c;
5434 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5435 pr "%s License along with this library; if not, write to the Free Software\n" c;
5436 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5439 | CStyle -> pr " */\n"
5442 | OCamlStyle -> pr " *)\n"
5443 | HaskellStyle -> pr "-}\n"
5447 (* Start of main code generation functions below this line. *)
5449 (* Generate the pod documentation for the C API. *)
5450 let rec generate_actions_pod () =
5452 fun (shortname, style, _, flags, _, _, longdesc) ->
5453 if not (List.mem NotInDocs flags) then (
5454 let name = "guestfs_" ^ shortname in
5455 pr "=head2 %s\n\n" name;
5457 generate_prototype ~extern:false ~handle:"g" name style;
5459 pr "%s\n\n" longdesc;
5460 (match fst style with
5462 pr "This function returns 0 on success or -1 on error.\n\n"
5464 pr "On error this function returns -1.\n\n"
5466 pr "On error this function returns -1.\n\n"
5468 pr "This function returns a C truth value on success or -1 on error.\n\n"
5470 pr "This function returns a string, or NULL on error.
5471 The string is owned by the guest handle and must I<not> be freed.\n\n"
5472 | RConstOptString _ ->
5473 pr "This function returns a string which may be NULL.
5474 There is way to return an error from this function.
5475 The string is owned by the guest handle and must I<not> be freed.\n\n"
5477 pr "This function returns a string, or NULL on error.
5478 I<The caller must free the returned string after use>.\n\n"
5480 pr "This function returns a NULL-terminated array of strings
5481 (like L<environ(3)>), or NULL if there was an error.
5482 I<The caller must free the strings and the array after use>.\n\n"
5483 | RStruct (_, typ) ->
5484 pr "This function returns a C<struct guestfs_%s *>,
5485 or NULL if there was an error.
5486 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5487 | RStructList (_, typ) ->
5488 pr "This function returns a C<struct guestfs_%s_list *>
5489 (see E<lt>guestfs-structs.hE<gt>),
5490 or NULL if there was an error.
5491 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5493 pr "This function returns a NULL-terminated array of
5494 strings, or NULL if there was an error.
5495 The array of strings will always have length C<2n+1>, where
5496 C<n> keys and values alternate, followed by the trailing NULL entry.
5497 I<The caller must free the strings and the array after use>.\n\n"
5499 pr "This function returns a buffer, or NULL on error.
5500 The size of the returned buffer is written to C<*size_r>.
5501 I<The caller must free the returned buffer after use>.\n\n"
5503 if List.mem ProtocolLimitWarning flags then
5504 pr "%s\n\n" protocol_limit_warning;
5505 if List.mem DangerWillRobinson flags then
5506 pr "%s\n\n" danger_will_robinson;
5507 match deprecation_notice flags with
5509 | Some txt -> pr "%s\n\n" txt
5511 ) all_functions_sorted
5513 and generate_structs_pod () =
5514 (* Structs documentation. *)
5517 pr "=head2 guestfs_%s\n" typ;
5519 pr " struct guestfs_%s {\n" typ;
5522 | name, FChar -> pr " char %s;\n" name
5523 | name, FUInt32 -> pr " uint32_t %s;\n" name
5524 | name, FInt32 -> pr " int32_t %s;\n" name
5525 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5526 | name, FInt64 -> pr " int64_t %s;\n" name
5527 | name, FString -> pr " char *%s;\n" name
5529 pr " /* The next two fields describe a byte array. */\n";
5530 pr " uint32_t %s_len;\n" name;
5531 pr " char *%s;\n" name
5533 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5534 pr " char %s[32];\n" name
5535 | name, FOptPercent ->
5536 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5537 pr " float %s;\n" name
5541 pr " struct guestfs_%s_list {\n" typ;
5542 pr " uint32_t len; /* Number of elements in list. */\n";
5543 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5546 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5547 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5552 and generate_availability_pod () =
5553 (* Availability documentation. *)
5557 fun (group, functions) ->
5558 pr "=item B<%s>\n" group;
5560 pr "The following functions:\n";
5561 List.iter (pr "L</guestfs_%s>\n") functions;
5567 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5568 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5570 * We have to use an underscore instead of a dash because otherwise
5571 * rpcgen generates incorrect code.
5573 * This header is NOT exported to clients, but see also generate_structs_h.
5575 and generate_xdr () =
5576 generate_header CStyle LGPLv2plus;
5578 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5579 pr "typedef string str<>;\n";
5582 (* Internal structures. *)
5586 pr "struct guestfs_int_%s {\n" typ;
5588 | name, FChar -> pr " char %s;\n" name
5589 | name, FString -> pr " string %s<>;\n" name
5590 | name, FBuffer -> pr " opaque %s<>;\n" name
5591 | name, FUUID -> pr " opaque %s[32];\n" name
5592 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5593 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5594 | name, FOptPercent -> pr " float %s;\n" name
5598 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5603 fun (shortname, style, _, _, _, _, _) ->
5604 let name = "guestfs_" ^ shortname in
5606 (match snd style with
5609 pr "struct %s_args {\n" name;
5612 | Pathname n | Device n | Dev_or_Path n | String n ->
5613 pr " string %s<>;\n" n
5614 | OptString n -> pr " str *%s;\n" n
5615 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5616 | Bool n -> pr " bool %s;\n" n
5617 | Int n -> pr " int %s;\n" n
5618 | Int64 n -> pr " hyper %s;\n" n
5620 pr " opaque %s<>;\n" n
5621 | FileIn _ | FileOut _ -> ()
5625 (match fst style with
5628 pr "struct %s_ret {\n" name;
5632 pr "struct %s_ret {\n" name;
5633 pr " hyper %s;\n" n;
5636 pr "struct %s_ret {\n" name;
5639 | RConstString _ | RConstOptString _ ->
5640 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5642 pr "struct %s_ret {\n" name;
5643 pr " string %s<>;\n" n;
5646 pr "struct %s_ret {\n" name;
5647 pr " str %s<>;\n" n;
5649 | RStruct (n, typ) ->
5650 pr "struct %s_ret {\n" name;
5651 pr " guestfs_int_%s %s;\n" typ n;
5653 | RStructList (n, typ) ->
5654 pr "struct %s_ret {\n" name;
5655 pr " guestfs_int_%s_list %s;\n" typ n;
5658 pr "struct %s_ret {\n" name;
5659 pr " str %s<>;\n" n;
5662 pr "struct %s_ret {\n" name;
5663 pr " opaque %s<>;\n" n;
5668 (* Table of procedure numbers. *)
5669 pr "enum guestfs_procedure {\n";
5671 fun (shortname, _, proc_nr, _, _, _, _) ->
5672 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5674 pr " GUESTFS_PROC_NR_PROCS\n";
5678 (* Having to choose a maximum message size is annoying for several
5679 * reasons (it limits what we can do in the API), but it (a) makes
5680 * the protocol a lot simpler, and (b) provides a bound on the size
5681 * of the daemon which operates in limited memory space.
5683 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5686 (* Message header, etc. *)
5688 /* The communication protocol is now documented in the guestfs(3)
5692 const GUESTFS_PROGRAM = 0x2000F5F5;
5693 const GUESTFS_PROTOCOL_VERSION = 1;
5695 /* These constants must be larger than any possible message length. */
5696 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5697 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5699 enum guestfs_message_direction {
5700 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5701 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5704 enum guestfs_message_status {
5705 GUESTFS_STATUS_OK = 0,
5706 GUESTFS_STATUS_ERROR = 1
5709 const GUESTFS_ERROR_LEN = 256;
5711 struct guestfs_message_error {
5712 string error_message<GUESTFS_ERROR_LEN>;
5715 struct guestfs_message_header {
5716 unsigned prog; /* GUESTFS_PROGRAM */
5717 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5718 guestfs_procedure proc; /* GUESTFS_PROC_x */
5719 guestfs_message_direction direction;
5720 unsigned serial; /* message serial number */
5721 guestfs_message_status status;
5724 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5726 struct guestfs_chunk {
5727 int cancel; /* if non-zero, transfer is cancelled */
5728 /* data size is 0 bytes if the transfer has finished successfully */
5729 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5733 (* Generate the guestfs-structs.h file. *)
5734 and generate_structs_h () =
5735 generate_header CStyle LGPLv2plus;
5737 (* This is a public exported header file containing various
5738 * structures. The structures are carefully written to have
5739 * exactly the same in-memory format as the XDR structures that
5740 * we use on the wire to the daemon. The reason for creating
5741 * copies of these structures here is just so we don't have to
5742 * export the whole of guestfs_protocol.h (which includes much
5743 * unrelated and XDR-dependent stuff that we don't want to be
5744 * public, or required by clients).
5746 * To reiterate, we will pass these structures to and from the
5747 * client with a simple assignment or memcpy, so the format
5748 * must be identical to what rpcgen / the RFC defines.
5751 (* Public structures. *)
5754 pr "struct guestfs_%s {\n" typ;
5757 | name, FChar -> pr " char %s;\n" name
5758 | name, FString -> pr " char *%s;\n" name
5760 pr " uint32_t %s_len;\n" name;
5761 pr " char *%s;\n" name
5762 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5763 | name, FUInt32 -> pr " uint32_t %s;\n" name
5764 | name, FInt32 -> pr " int32_t %s;\n" name
5765 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5766 | name, FInt64 -> pr " int64_t %s;\n" name
5767 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5771 pr "struct guestfs_%s_list {\n" typ;
5772 pr " uint32_t len;\n";
5773 pr " struct guestfs_%s *val;\n" typ;
5776 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5777 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5781 (* Generate the guestfs-actions.h file. *)
5782 and generate_actions_h () =
5783 generate_header CStyle LGPLv2plus;
5785 fun (shortname, style, _, _, _, _, _) ->
5786 let name = "guestfs_" ^ shortname in
5787 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5791 (* Generate the guestfs-internal-actions.h file. *)
5792 and generate_internal_actions_h () =
5793 generate_header CStyle LGPLv2plus;
5795 fun (shortname, style, _, _, _, _, _) ->
5796 let name = "guestfs__" ^ shortname in
5797 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5799 ) non_daemon_functions
5801 (* Generate the client-side dispatch stubs. *)
5802 and generate_client_actions () =
5803 generate_header CStyle LGPLv2plus;
5810 #include <inttypes.h>
5812 #include \"guestfs.h\"
5813 #include \"guestfs-internal.h\"
5814 #include \"guestfs-internal-actions.h\"
5815 #include \"guestfs_protocol.h\"
5817 #define error guestfs_error
5818 //#define perrorf guestfs_perrorf
5819 #define safe_malloc guestfs_safe_malloc
5820 #define safe_realloc guestfs_safe_realloc
5821 //#define safe_strdup guestfs_safe_strdup
5822 #define safe_memdup guestfs_safe_memdup
5824 /* Check the return message from a call for validity. */
5826 check_reply_header (guestfs_h *g,
5827 const struct guestfs_message_header *hdr,
5828 unsigned int proc_nr, unsigned int serial)
5830 if (hdr->prog != GUESTFS_PROGRAM) {
5831 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5834 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5835 error (g, \"wrong protocol version (%%d/%%d)\",
5836 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5839 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5840 error (g, \"unexpected message direction (%%d/%%d)\",
5841 hdr->direction, GUESTFS_DIRECTION_REPLY);
5844 if (hdr->proc != proc_nr) {
5845 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5848 if (hdr->serial != serial) {
5849 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5856 /* Check we are in the right state to run a high-level action. */
5858 check_state (guestfs_h *g, const char *caller)
5860 if (!guestfs__is_ready (g)) {
5861 if (guestfs__is_config (g) || guestfs__is_launching (g))
5862 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5865 error (g, \"%%s called from the wrong state, %%d != READY\",
5866 caller, guestfs__get_state (g));
5874 let error_code_of = function
5875 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5876 | RConstString _ | RConstOptString _
5877 | RString _ | RStringList _
5878 | RStruct _ | RStructList _
5879 | RHashtable _ | RBufferOut _ -> "NULL"
5882 (* Generate code to check String-like parameters are not passed in
5883 * as NULL (returning an error if they are).
5885 let check_null_strings shortname style =
5886 let pr_newline = ref false in
5889 (* parameters which should not be NULL *)
5899 pr " if (%s == NULL) {\n" n;
5900 pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5901 pr " \"%s\", \"%s\");\n" shortname n;
5902 pr " return %s;\n" (error_code_of (fst style));
5909 (* not applicable *)
5915 if !pr_newline then pr "\n";
5918 (* Generate code to generate guestfish call traces. *)
5919 let trace_call shortname style =
5920 pr " if (guestfs__get_trace (g)) {\n";
5923 List.exists (function
5924 | StringList _ | DeviceList _ -> true
5925 | _ -> false) (snd style) in
5931 pr " printf (\"%s\");\n" shortname;
5934 | String n (* strings *)
5941 (* guestfish doesn't support string escaping, so neither do we *)
5942 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5943 | OptString n -> (* string option *)
5944 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5945 pr " else printf (\" null\");\n"
5947 | DeviceList n -> (* string list *)
5948 pr " putchar (' ');\n";
5949 pr " putchar ('\"');\n";
5950 pr " for (i = 0; %s[i]; ++i) {\n" n;
5951 pr " if (i > 0) putchar (' ');\n";
5952 pr " fputs (%s[i], stdout);\n" n;
5954 pr " putchar ('\"');\n";
5955 | Bool n -> (* boolean *)
5956 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5957 | Int n -> (* int *)
5958 pr " printf (\" %%d\", %s);\n" n
5960 pr " printf (\" %%\" PRIi64, %s);\n" n
5962 pr " putchar ('\\n');\n";
5967 (* For non-daemon functions, generate a wrapper around each function. *)
5969 fun (shortname, style, _, _, _, _, _) ->
5970 let name = "guestfs_" ^ shortname in
5972 generate_prototype ~extern:false ~semicolon:false ~newline:true
5973 ~handle:"g" name style;
5975 check_null_strings shortname style;
5976 trace_call shortname style;
5977 pr " return guestfs__%s " shortname;
5978 generate_c_call_args ~handle:"g" style;
5982 ) non_daemon_functions;
5984 (* Client-side stubs for each function. *)
5986 fun (shortname, style, _, _, _, _, _) ->
5987 let name = "guestfs_" ^ shortname in
5988 let error_code = error_code_of (fst style) in
5990 (* Generate the action stub. *)
5991 generate_prototype ~extern:false ~semicolon:false ~newline:true
5992 ~handle:"g" name style;
5996 (match snd style with
5998 | _ -> pr " struct %s_args args;\n" name
6001 pr " guestfs_message_header hdr;\n";
6002 pr " guestfs_message_error err;\n";
6004 match fst style with
6006 | RConstString _ | RConstOptString _ ->
6007 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6009 | RBool _ | RString _ | RStringList _
6010 | RStruct _ | RStructList _
6011 | RHashtable _ | RBufferOut _ ->
6012 pr " struct %s_ret ret;\n" name;
6015 pr " int serial;\n";
6018 check_null_strings shortname style;
6019 trace_call shortname style;
6020 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
6021 shortname error_code;
6022 pr " guestfs___set_busy (g);\n";
6025 (* Send the main header and arguments. *)
6026 (match snd style with
6028 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6029 (String.uppercase shortname)
6033 | Pathname n | Device n | Dev_or_Path n | String n ->
6034 pr " args.%s = (char *) %s;\n" n n
6036 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
6037 | StringList n | DeviceList n ->
6038 pr " args.%s.%s_val = (char **) %s;\n" n n n;
6039 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6041 pr " args.%s = %s;\n" n n
6043 pr " args.%s = %s;\n" n n
6045 pr " args.%s = %s;\n" n n
6046 | FileIn _ | FileOut _ -> ()
6048 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6049 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6050 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6052 pr " guestfs___end_busy (g);\n";
6053 pr " return %s;\n" error_code;
6055 pr " args.%s.%s_val = (char *) %s;\n" n n n;
6056 pr " args.%s.%s_len = %s_size;\n" n n n
6058 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6059 (String.uppercase shortname);
6060 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6063 pr " if (serial == -1) {\n";
6064 pr " guestfs___end_busy (g);\n";
6065 pr " return %s;\n" error_code;
6069 (* Send any additional files (FileIn) requested. *)
6070 let need_read_reply_label = ref false in
6074 pr " r = guestfs___send_file (g, %s);\n" n;
6075 pr " if (r == -1) {\n";
6076 pr " guestfs___end_busy (g);\n";
6077 pr " return %s;\n" error_code;
6079 pr " if (r == -2) /* daemon cancelled */\n";
6080 pr " goto read_reply;\n";
6081 need_read_reply_label := true;
6086 (* Wait for the reply from the remote end. *)
6087 if !need_read_reply_label then pr " read_reply:\n";
6088 pr " memset (&hdr, 0, sizeof hdr);\n";
6089 pr " memset (&err, 0, sizeof err);\n";
6090 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
6092 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
6096 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6099 pr " if (r == -1) {\n";
6100 pr " guestfs___end_busy (g);\n";
6101 pr " return %s;\n" error_code;
6105 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6106 (String.uppercase shortname);
6107 pr " guestfs___end_busy (g);\n";
6108 pr " return %s;\n" error_code;
6112 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6113 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6114 pr " free (err.error_message);\n";
6115 pr " guestfs___end_busy (g);\n";
6116 pr " return %s;\n" error_code;
6120 (* Expecting to receive further files (FileOut)? *)
6124 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6125 pr " guestfs___end_busy (g);\n";
6126 pr " return %s;\n" error_code;
6132 pr " guestfs___end_busy (g);\n";
6134 (match fst style with
6135 | RErr -> pr " return 0;\n"
6136 | RInt n | RInt64 n | RBool n ->
6137 pr " return ret.%s;\n" n
6138 | RConstString _ | RConstOptString _ ->
6139 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6141 pr " return ret.%s; /* caller will free */\n" n
6142 | RStringList n | RHashtable n ->
6143 pr " /* caller will free this, but we need to add a NULL entry */\n";
6144 pr " ret.%s.%s_val =\n" n n;
6145 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6146 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6148 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6149 pr " return ret.%s.%s_val;\n" n n
6151 pr " /* caller will free this */\n";
6152 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6153 | RStructList (n, _) ->
6154 pr " /* caller will free this */\n";
6155 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6157 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6158 pr " * _val might be NULL here. To make the API saner for\n";
6159 pr " * callers, we turn this case into a unique pointer (using\n";
6160 pr " * malloc(1)).\n";
6162 pr " if (ret.%s.%s_len > 0) {\n" n n;
6163 pr " *size_r = ret.%s.%s_len;\n" n n;
6164 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6166 pr " free (ret.%s.%s_val);\n" n n;
6167 pr " char *p = safe_malloc (g, 1);\n";
6168 pr " *size_r = ret.%s.%s_len;\n" n n;
6176 (* Functions to free structures. *)
6177 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6178 pr " * structure format is identical to the XDR format. See note in\n";
6179 pr " * generator.ml.\n";
6186 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6188 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6194 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6196 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6203 (* Generate daemon/actions.h. *)
6204 and generate_daemon_actions_h () =
6205 generate_header CStyle GPLv2plus;
6207 pr "#include \"../src/guestfs_protocol.h\"\n";
6211 fun (name, style, _, _, _, _, _) ->
6213 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6217 (* Generate the linker script which controls the visibility of
6218 * symbols in the public ABI and ensures no other symbols get
6219 * exported accidentally.
6221 and generate_linker_script () =
6222 generate_header HashStyle GPLv2plus;
6227 "guestfs_get_error_handler";
6228 "guestfs_get_out_of_memory_handler";
6229 "guestfs_last_error";
6230 "guestfs_set_error_handler";
6231 "guestfs_set_launch_done_callback";
6232 "guestfs_set_log_message_callback";
6233 "guestfs_set_out_of_memory_handler";
6234 "guestfs_set_subprocess_quit_callback";
6236 (* Unofficial parts of the API: the bindings code use these
6237 * functions, so it is useful to export them.
6239 "guestfs_safe_calloc";
6240 "guestfs_safe_malloc";
6243 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6247 List.map (fun (typ, _) ->
6248 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6251 let globals = List.sort compare (globals @ functions @ structs) in
6255 List.iter (pr " %s;\n") globals;
6262 (* Generate the server-side stubs. *)
6263 and generate_daemon_actions () =
6264 generate_header CStyle GPLv2plus;
6266 pr "#include <config.h>\n";
6268 pr "#include <stdio.h>\n";
6269 pr "#include <stdlib.h>\n";
6270 pr "#include <string.h>\n";
6271 pr "#include <inttypes.h>\n";
6272 pr "#include <rpc/types.h>\n";
6273 pr "#include <rpc/xdr.h>\n";
6275 pr "#include \"daemon.h\"\n";
6276 pr "#include \"c-ctype.h\"\n";
6277 pr "#include \"../src/guestfs_protocol.h\"\n";
6278 pr "#include \"actions.h\"\n";
6282 fun (name, style, _, _, _, _, _) ->
6283 (* Generate server-side stubs. *)
6284 pr "static void %s_stub (XDR *xdr_in)\n" name;
6287 match fst style with
6288 | RErr | RInt _ -> pr " int r;\n"; "-1"
6289 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6290 | RBool _ -> pr " int r;\n"; "-1"
6291 | RConstString _ | RConstOptString _ ->
6292 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6293 | RString _ -> pr " char *r;\n"; "NULL"
6294 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6295 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6296 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6298 pr " size_t size = 1;\n";
6302 (match snd style with
6305 pr " struct guestfs_%s_args args;\n" name;
6308 | Device n | Dev_or_Path n
6311 | OptString n -> pr " char *%s;\n" n
6312 | StringList n | DeviceList n -> pr " char **%s;\n" n
6313 | Bool n -> pr " int %s;\n" n
6314 | Int n -> pr " int %s;\n" n
6315 | Int64 n -> pr " int64_t %s;\n" n
6316 | FileIn _ | FileOut _ -> ()
6318 pr " const char *%s;\n" n;
6319 pr " size_t %s_size;\n" n
6325 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6327 (match snd style with
6330 pr " memset (&args, 0, sizeof args);\n";
6332 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6334 pr " if (cancel_receive () != -2)\n";
6335 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6339 pr " char *%s = args.%s;\n" n n
6341 let pr_list_handling_code n =
6342 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6343 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6344 pr " if (%s == NULL) {\n" n;
6346 pr " if (cancel_receive () != -2)\n";
6347 pr " reply_with_perror (\"realloc\");\n";
6350 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6351 pr " args.%s.%s_val = %s;\n" n n n;
6357 pr " ABS_PATH (%s, %s, goto done);\n"
6358 n (if is_filein then "cancel_receive ()" else "0");
6361 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6362 n (if is_filein then "cancel_receive ()" else "0");
6365 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6366 n (if is_filein then "cancel_receive ()" else "0");
6367 | String n -> pr_args n
6368 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6370 pr_list_handling_code n;
6372 pr_list_handling_code n;
6373 pr " /* Ensure that each is a device,\n";
6374 pr " * and perform device name translation. */\n";
6375 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6376 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6377 (if is_filein then "cancel_receive ()" else "0");
6379 | Bool n -> pr " %s = args.%s;\n" n n
6380 | Int n -> pr " %s = args.%s;\n" n n
6381 | Int64 n -> pr " %s = args.%s;\n" n n
6382 | FileIn _ | FileOut _ -> ()
6384 pr " %s = args.%s.%s_val;\n" n n n;
6385 pr " %s_size = args.%s.%s_len;\n" n n n
6390 (* this is used at least for do_equal *)
6391 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6392 (* Emit NEED_ROOT just once, even when there are two or
6393 more Pathname args *)
6394 pr " NEED_ROOT (%s, goto done);\n"
6395 (if is_filein then "cancel_receive ()" else "0");
6398 (* Don't want to call the impl with any FileIn or FileOut
6399 * parameters, since these go "outside" the RPC protocol.
6402 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6404 pr " r = do_%s " name;
6405 generate_c_call_args (fst style, args');
6408 (match fst style with
6409 | RErr | RInt _ | RInt64 _ | RBool _
6410 | RConstString _ | RConstOptString _
6411 | RString _ | RStringList _ | RHashtable _
6412 | RStruct (_, _) | RStructList (_, _) ->
6413 pr " if (r == %s)\n" error_code;
6414 pr " /* do_%s has already called reply_with_error */\n" name;
6418 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6419 pr " * an ordinary zero-length buffer), so be careful ...\n";
6421 pr " if (size == 1 && r == %s)\n" error_code;
6422 pr " /* do_%s has already called reply_with_error */\n" name;
6427 (* If there are any FileOut parameters, then the impl must
6428 * send its own reply.
6431 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6433 pr " /* do_%s has already sent a reply */\n" name
6435 match fst style with
6436 | RErr -> pr " reply (NULL, NULL);\n"
6437 | RInt n | RInt64 n | RBool n ->
6438 pr " struct guestfs_%s_ret ret;\n" name;
6439 pr " ret.%s = r;\n" n;
6440 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6442 | RConstString _ | RConstOptString _ ->
6443 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6445 pr " struct guestfs_%s_ret ret;\n" name;
6446 pr " ret.%s = r;\n" n;
6447 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6450 | RStringList n | RHashtable n ->
6451 pr " struct guestfs_%s_ret ret;\n" name;
6452 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6453 pr " ret.%s.%s_val = r;\n" n n;
6454 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6456 pr " free_strings (r);\n"
6458 pr " struct guestfs_%s_ret ret;\n" name;
6459 pr " ret.%s = *r;\n" n;
6460 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6462 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6464 | RStructList (n, _) ->
6465 pr " struct guestfs_%s_ret ret;\n" name;
6466 pr " ret.%s = *r;\n" n;
6467 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6469 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6472 pr " struct guestfs_%s_ret ret;\n" name;
6473 pr " ret.%s.%s_val = r;\n" n n;
6474 pr " ret.%s.%s_len = size;\n" n n;
6475 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6480 (* Free the args. *)
6482 (match snd style with
6485 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6492 (* Dispatch function. *)
6493 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6495 pr " switch (proc_nr) {\n";
6498 fun (name, style, _, _, _, _, _) ->
6499 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6500 pr " %s_stub (xdr_in);\n" name;
6505 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";
6510 (* LVM columns and tokenization functions. *)
6511 (* XXX This generates crap code. We should rethink how we
6517 pr "static const char *lvm_%s_cols = \"%s\";\n"
6518 typ (String.concat "," (List.map fst cols));
6521 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6523 pr " char *tok, *p, *next;\n";
6527 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6530 pr " if (!str) {\n";
6531 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6534 pr " if (!*str || c_isspace (*str)) {\n";
6535 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6540 fun (name, coltype) ->
6541 pr " if (!tok) {\n";
6542 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6545 pr " p = strchrnul (tok, ',');\n";
6546 pr " if (*p) next = p+1; else next = NULL;\n";
6547 pr " *p = '\\0';\n";
6550 pr " r->%s = strdup (tok);\n" name;
6551 pr " if (r->%s == NULL) {\n" name;
6552 pr " perror (\"strdup\");\n";
6556 pr " for (i = j = 0; i < 32; ++j) {\n";
6557 pr " if (tok[j] == '\\0') {\n";
6558 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6560 pr " } else if (tok[j] != '-')\n";
6561 pr " r->%s[i++] = tok[j];\n" name;
6564 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6565 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6569 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6570 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6574 pr " if (tok[0] == '\\0')\n";
6575 pr " r->%s = -1;\n" name;
6576 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6577 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6580 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6581 assert false (* can never be an LVM column *)
6583 pr " tok = next;\n";
6586 pr " if (tok != NULL) {\n";
6587 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6594 pr "guestfs_int_lvm_%s_list *\n" typ;
6595 pr "parse_command_line_%ss (void)\n" typ;
6597 pr " char *out, *err;\n";
6598 pr " char *p, *pend;\n";
6600 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6601 pr " void *newp;\n";
6603 pr " ret = malloc (sizeof *ret);\n";
6604 pr " if (!ret) {\n";
6605 pr " reply_with_perror (\"malloc\");\n";
6606 pr " return NULL;\n";
6609 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6610 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6612 pr " r = command (&out, &err,\n";
6613 pr " \"lvm\", \"%ss\",\n" typ;
6614 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6615 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6616 pr " if (r == -1) {\n";
6617 pr " reply_with_error (\"%%s\", err);\n";
6618 pr " free (out);\n";
6619 pr " free (err);\n";
6620 pr " free (ret);\n";
6621 pr " return NULL;\n";
6624 pr " free (err);\n";
6626 pr " /* Tokenize each line of the output. */\n";
6629 pr " while (p) {\n";
6630 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6631 pr " if (pend) {\n";
6632 pr " *pend = '\\0';\n";
6636 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6639 pr " if (!*p) { /* Empty line? Skip it. */\n";
6644 pr " /* Allocate some space to store this next entry. */\n";
6645 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6646 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6647 pr " if (newp == NULL) {\n";
6648 pr " reply_with_perror (\"realloc\");\n";
6649 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6650 pr " free (ret);\n";
6651 pr " free (out);\n";
6652 pr " return NULL;\n";
6654 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6656 pr " /* Tokenize the next entry. */\n";
6657 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6658 pr " if (r == -1) {\n";
6659 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6660 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6661 pr " free (ret);\n";
6662 pr " free (out);\n";
6663 pr " return NULL;\n";
6670 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6672 pr " free (out);\n";
6673 pr " return ret;\n";
6676 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6678 (* Generate a list of function names, for debugging in the daemon.. *)
6679 and generate_daemon_names () =
6680 generate_header CStyle GPLv2plus;
6682 pr "#include <config.h>\n";
6684 pr "#include \"daemon.h\"\n";
6687 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6688 pr "const char *function_names[] = {\n";
6690 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6694 (* Generate the optional groups for the daemon to implement
6695 * guestfs_available.
6697 and generate_daemon_optgroups_c () =
6698 generate_header CStyle GPLv2plus;
6700 pr "#include <config.h>\n";
6702 pr "#include \"daemon.h\"\n";
6703 pr "#include \"optgroups.h\"\n";
6706 pr "struct optgroup optgroups[] = {\n";
6709 pr " { \"%s\", optgroup_%s_available },\n" group group
6711 pr " { NULL, NULL }\n";
6714 and generate_daemon_optgroups_h () =
6715 generate_header CStyle GPLv2plus;
6719 pr "extern int optgroup_%s_available (void);\n" group
6722 (* Generate the tests. *)
6723 and generate_tests () =
6724 generate_header CStyle GPLv2plus;
6731 #include <sys/types.h>
6734 #include \"guestfs.h\"
6735 #include \"guestfs-internal.h\"
6737 static guestfs_h *g;
6738 static int suppress_error = 0;
6740 static void print_error (guestfs_h *g, void *data, const char *msg)
6742 if (!suppress_error)
6743 fprintf (stderr, \"%%s\\n\", msg);
6746 /* FIXME: nearly identical code appears in fish.c */
6747 static void print_strings (char *const *argv)
6751 for (argc = 0; argv[argc] != NULL; ++argc)
6752 printf (\"\\t%%s\\n\", argv[argc]);
6756 static void print_table (char const *const *argv)
6760 for (i = 0; argv[i] != NULL; i += 2)
6761 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6767 (* Generate a list of commands which are not tested anywhere. *)
6768 pr "static void no_test_warnings (void)\n";
6771 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6773 fun (_, _, _, _, tests, _, _) ->
6774 let tests = filter_map (
6776 | (_, (Always|If _|Unless _), test) -> Some test
6777 | (_, Disabled, _) -> None
6779 let seq = List.concat (List.map seq_of_test tests) in
6780 let cmds_tested = List.map List.hd seq in
6781 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6785 fun (name, _, _, _, _, _, _) ->
6786 if not (Hashtbl.mem hash name) then
6787 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6793 (* Generate the actual tests. Note that we generate the tests
6794 * in reverse order, deliberately, so that (in general) the
6795 * newest tests run first. This makes it quicker and easier to
6800 fun (name, _, _, flags, tests, _, _) ->
6801 mapi (generate_one_test name flags) tests
6802 ) (List.rev all_functions) in
6803 let test_names = List.concat test_names in
6804 let nr_tests = List.length test_names in
6807 int main (int argc, char *argv[])
6810 unsigned long int n_failed = 0;
6811 const char *filename;
6813 int nr_tests, test_num = 0;
6815 setbuf (stdout, NULL);
6817 no_test_warnings ();
6819 g = guestfs_create ();
6821 printf (\"guestfs_create FAILED\\n\");
6822 exit (EXIT_FAILURE);
6825 guestfs_set_error_handler (g, print_error, NULL);
6827 guestfs_set_path (g, \"../appliance\");
6829 filename = \"test1.img\";
6830 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6833 exit (EXIT_FAILURE);
6835 if (lseek (fd, %d, SEEK_SET) == -1) {
6839 exit (EXIT_FAILURE);
6841 if (write (fd, &c, 1) == -1) {
6845 exit (EXIT_FAILURE);
6847 if (close (fd) == -1) {
6850 exit (EXIT_FAILURE);
6852 if (guestfs_add_drive (g, filename) == -1) {
6853 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6854 exit (EXIT_FAILURE);
6857 filename = \"test2.img\";
6858 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6861 exit (EXIT_FAILURE);
6863 if (lseek (fd, %d, SEEK_SET) == -1) {
6867 exit (EXIT_FAILURE);
6869 if (write (fd, &c, 1) == -1) {
6873 exit (EXIT_FAILURE);
6875 if (close (fd) == -1) {
6878 exit (EXIT_FAILURE);
6880 if (guestfs_add_drive (g, filename) == -1) {
6881 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6882 exit (EXIT_FAILURE);
6885 filename = \"test3.img\";
6886 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6889 exit (EXIT_FAILURE);
6891 if (lseek (fd, %d, SEEK_SET) == -1) {
6895 exit (EXIT_FAILURE);
6897 if (write (fd, &c, 1) == -1) {
6901 exit (EXIT_FAILURE);
6903 if (close (fd) == -1) {
6906 exit (EXIT_FAILURE);
6908 if (guestfs_add_drive (g, filename) == -1) {
6909 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6910 exit (EXIT_FAILURE);
6913 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6914 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6915 exit (EXIT_FAILURE);
6918 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6921 if (guestfs_launch (g) == -1) {
6922 printf (\"guestfs_launch FAILED\\n\");
6923 exit (EXIT_FAILURE);
6926 /* Cancel previous alarm. */
6931 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6935 pr " test_num++;\n";
6936 pr " if (guestfs_get_verbose (g))\n";
6937 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6938 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6939 pr " if (%s () == -1) {\n" test_name;
6940 pr " printf (\"%s FAILED\\n\");\n" test_name;
6941 pr " n_failed++;\n";
6946 pr " guestfs_close (g);\n";
6947 pr " unlink (\"test1.img\");\n";
6948 pr " unlink (\"test2.img\");\n";
6949 pr " unlink (\"test3.img\");\n";
6952 pr " if (n_failed > 0) {\n";
6953 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6954 pr " exit (EXIT_FAILURE);\n";
6958 pr " exit (EXIT_SUCCESS);\n";
6961 and generate_one_test name flags i (init, prereq, test) =
6962 let test_name = sprintf "test_%s_%d" name i in
6965 static int %s_skip (void)
6969 str = getenv (\"TEST_ONLY\");
6971 return strstr (str, \"%s\") == NULL;
6972 str = getenv (\"SKIP_%s\");
6973 if (str && STREQ (str, \"1\")) return 1;
6974 str = getenv (\"SKIP_TEST_%s\");
6975 if (str && STREQ (str, \"1\")) return 1;
6979 " test_name name (String.uppercase test_name) (String.uppercase name);
6982 | Disabled | Always -> ()
6983 | If code | Unless code ->
6984 pr "static int %s_prereq (void)\n" test_name;
6992 static int %s (void)
6995 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6999 " test_name test_name test_name;
7001 (* Optional functions should only be tested if the relevant
7002 * support is available in the daemon.
7008 pr " const char *groups[] = { \"%s\", NULL };\n" group;
7010 pr " suppress_error = 1;\n";
7011 pr " r = guestfs_available (g, (char **) groups);\n";
7012 pr " suppress_error = 0;\n";
7013 pr " if (r == -1) {\n";
7014 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7023 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7025 pr " if (! %s_prereq ()) {\n" test_name;
7026 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7030 generate_one_test_body name i test_name init test;
7032 pr " if (%s_prereq ()) {\n" test_name;
7033 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7037 generate_one_test_body name i test_name init test;
7039 generate_one_test_body name i test_name init test
7047 and generate_one_test_body name i test_name init test =
7049 | InitNone (* XXX at some point, InitNone and InitEmpty became
7050 * folded together as the same thing. Really we should
7051 * make InitNone do nothing at all, but the tests may
7052 * need to be checked to make sure this is OK.
7055 pr " /* InitNone|InitEmpty for %s */\n" test_name;
7056 List.iter (generate_test_command_call test_name)
7057 [["blockdev_setrw"; "/dev/sda"];
7061 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7062 List.iter (generate_test_command_call test_name)
7063 [["blockdev_setrw"; "/dev/sda"];
7066 ["part_disk"; "/dev/sda"; "mbr"]]
7068 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7069 List.iter (generate_test_command_call test_name)
7070 [["blockdev_setrw"; "/dev/sda"];
7073 ["part_disk"; "/dev/sda"; "mbr"];
7074 ["mkfs"; "ext2"; "/dev/sda1"];
7075 ["mount_options"; ""; "/dev/sda1"; "/"]]
7076 | InitBasicFSonLVM ->
7077 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7079 List.iter (generate_test_command_call test_name)
7080 [["blockdev_setrw"; "/dev/sda"];
7083 ["part_disk"; "/dev/sda"; "mbr"];
7084 ["pvcreate"; "/dev/sda1"];
7085 ["vgcreate"; "VG"; "/dev/sda1"];
7086 ["lvcreate"; "LV"; "VG"; "8"];
7087 ["mkfs"; "ext2"; "/dev/VG/LV"];
7088 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7090 pr " /* InitISOFS for %s */\n" test_name;
7091 List.iter (generate_test_command_call test_name)
7092 [["blockdev_setrw"; "/dev/sda"];
7095 ["mount_ro"; "/dev/sdd"; "/"]]
7098 let get_seq_last = function
7100 failwithf "%s: you cannot use [] (empty list) when expecting a command"
7103 let seq = List.rev seq in
7104 List.rev (List.tl seq), List.hd seq
7109 pr " /* TestRun for %s (%d) */\n" name i;
7110 List.iter (generate_test_command_call test_name) seq
7111 | TestOutput (seq, expected) ->
7112 pr " /* TestOutput for %s (%d) */\n" name i;
7113 pr " const char *expected = \"%s\";\n" (c_quote expected);
7114 let seq, last = get_seq_last seq in
7116 pr " if (STRNEQ (r, expected)) {\n";
7117 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7121 List.iter (generate_test_command_call test_name) seq;
7122 generate_test_command_call ~test test_name last
7123 | TestOutputList (seq, expected) ->
7124 pr " /* TestOutputList for %s (%d) */\n" name i;
7125 let seq, last = get_seq_last seq in
7129 pr " if (!r[%d]) {\n" i;
7130 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7131 pr " print_strings (r);\n";
7135 pr " const char *expected = \"%s\";\n" (c_quote str);
7136 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7137 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7142 pr " if (r[%d] != NULL) {\n" (List.length expected);
7143 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7145 pr " print_strings (r);\n";
7149 List.iter (generate_test_command_call test_name) seq;
7150 generate_test_command_call ~test test_name last
7151 | TestOutputListOfDevices (seq, expected) ->
7152 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7153 let seq, last = get_seq_last seq in
7157 pr " if (!r[%d]) {\n" i;
7158 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7159 pr " print_strings (r);\n";
7163 pr " const char *expected = \"%s\";\n" (c_quote str);
7164 pr " r[%d][5] = 's';\n" i;
7165 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7166 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7171 pr " if (r[%d] != NULL) {\n" (List.length expected);
7172 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7174 pr " print_strings (r);\n";
7178 List.iter (generate_test_command_call test_name) seq;
7179 generate_test_command_call ~test test_name last
7180 | TestOutputInt (seq, expected) ->
7181 pr " /* TestOutputInt for %s (%d) */\n" name i;
7182 let seq, last = get_seq_last seq in
7184 pr " if (r != %d) {\n" expected;
7185 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7191 List.iter (generate_test_command_call test_name) seq;
7192 generate_test_command_call ~test test_name last
7193 | TestOutputIntOp (seq, op, expected) ->
7194 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7195 let seq, last = get_seq_last seq in
7197 pr " if (! (r %s %d)) {\n" op expected;
7198 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7199 test_name op expected;
7204 List.iter (generate_test_command_call test_name) seq;
7205 generate_test_command_call ~test test_name last
7206 | TestOutputTrue seq ->
7207 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7208 let seq, last = get_seq_last seq in
7211 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7216 List.iter (generate_test_command_call test_name) seq;
7217 generate_test_command_call ~test test_name last
7218 | TestOutputFalse seq ->
7219 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7220 let seq, last = get_seq_last seq in
7223 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7228 List.iter (generate_test_command_call test_name) seq;
7229 generate_test_command_call ~test test_name last
7230 | TestOutputLength (seq, expected) ->
7231 pr " /* TestOutputLength for %s (%d) */\n" name i;
7232 let seq, last = get_seq_last seq in
7235 pr " for (j = 0; j < %d; ++j)\n" expected;
7236 pr " if (r[j] == NULL) {\n";
7237 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7239 pr " print_strings (r);\n";
7242 pr " if (r[j] != NULL) {\n";
7243 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7245 pr " print_strings (r);\n";
7249 List.iter (generate_test_command_call test_name) seq;
7250 generate_test_command_call ~test test_name last
7251 | TestOutputBuffer (seq, expected) ->
7252 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7253 pr " const char *expected = \"%s\";\n" (c_quote expected);
7254 let seq, last = get_seq_last seq in
7255 let len = String.length expected in
7257 pr " if (size != %d) {\n" len;
7258 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7261 pr " if (STRNEQLEN (r, expected, size)) {\n";
7262 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7266 List.iter (generate_test_command_call test_name) seq;
7267 generate_test_command_call ~test test_name last
7268 | TestOutputStruct (seq, checks) ->
7269 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7270 let seq, last = get_seq_last seq in
7274 | CompareWithInt (field, expected) ->
7275 pr " if (r->%s != %d) {\n" field expected;
7276 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7277 test_name field expected;
7278 pr " (int) r->%s);\n" field;
7281 | CompareWithIntOp (field, op, expected) ->
7282 pr " if (!(r->%s %s %d)) {\n" field op expected;
7283 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7284 test_name field op expected;
7285 pr " (int) r->%s);\n" field;
7288 | CompareWithString (field, expected) ->
7289 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7290 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7291 test_name field expected;
7292 pr " r->%s);\n" field;
7295 | CompareFieldsIntEq (field1, field2) ->
7296 pr " if (r->%s != r->%s) {\n" field1 field2;
7297 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7298 test_name field1 field2;
7299 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7302 | CompareFieldsStrEq (field1, field2) ->
7303 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7304 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7305 test_name field1 field2;
7306 pr " r->%s, r->%s);\n" field1 field2;
7311 List.iter (generate_test_command_call test_name) seq;
7312 generate_test_command_call ~test test_name last
7313 | TestLastFail seq ->
7314 pr " /* TestLastFail for %s (%d) */\n" name i;
7315 let seq, last = get_seq_last seq in
7316 List.iter (generate_test_command_call test_name) seq;
7317 generate_test_command_call test_name ~expect_error:true last
7319 (* Generate the code to run a command, leaving the result in 'r'.
7320 * If you expect to get an error then you should set expect_error:true.
7322 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7324 | [] -> assert false
7326 (* Look up the command to find out what args/ret it has. *)
7329 let _, style, _, _, _, _, _ =
7330 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7333 failwithf "%s: in test, command %s was not found" test_name name in
7335 if List.length (snd style) <> List.length args then
7336 failwithf "%s: in test, wrong number of args given to %s"
7343 | OptString n, "NULL" -> ()
7346 | Dev_or_Path n, arg
7348 | OptString n, arg ->
7349 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7350 | BufferIn n, arg ->
7351 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7352 pr " size_t %s_size = %d;\n" n (String.length arg)
7356 | FileIn _, _ | FileOut _, _ -> ()
7357 | StringList n, "" | DeviceList n, "" ->
7358 pr " const char *const %s[1] = { NULL };\n" n
7359 | StringList n, arg | DeviceList n, arg ->
7360 let strs = string_split " " arg in
7363 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7365 pr " const char *const %s[] = {\n" n;
7367 fun i _ -> pr " %s_%d,\n" n i
7371 ) (List.combine (snd style) args);
7374 match fst style with
7375 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7376 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7377 | RConstString _ | RConstOptString _ ->
7378 pr " const char *r;\n"; "NULL"
7379 | RString _ -> pr " char *r;\n"; "NULL"
7380 | RStringList _ | RHashtable _ ->
7384 | RStruct (_, typ) ->
7385 pr " struct guestfs_%s *r;\n" typ; "NULL"
7386 | RStructList (_, typ) ->
7387 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7390 pr " size_t size;\n";
7393 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7394 pr " r = guestfs_%s (g" name;
7396 (* Generate the parameters. *)
7399 | OptString _, "NULL" -> pr ", NULL"
7401 | Device n, _ | Dev_or_Path n, _
7406 pr ", %s, %s_size" n n
7407 | FileIn _, arg | FileOut _, arg ->
7408 pr ", \"%s\"" (c_quote arg)
7409 | StringList n, _ | DeviceList n, _ ->
7410 pr ", (char **) %s" n
7413 try int_of_string arg
7414 with Failure "int_of_string" ->
7415 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7419 try Int64.of_string arg
7420 with Failure "int_of_string" ->
7421 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7424 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7425 ) (List.combine (snd style) args);
7427 (match fst style with
7428 | RBufferOut _ -> pr ", &size"
7434 if not expect_error then
7435 pr " if (r == %s)\n" error_code
7437 pr " if (r != %s)\n" error_code;
7440 (* Insert the test code. *)
7446 (match fst style with
7447 | RErr | RInt _ | RInt64 _ | RBool _
7448 | RConstString _ | RConstOptString _ -> ()
7449 | RString _ | RBufferOut _ -> pr " free (r);\n"
7450 | RStringList _ | RHashtable _ ->
7451 pr " for (i = 0; r[i] != NULL; ++i)\n";
7452 pr " free (r[i]);\n";
7454 | RStruct (_, typ) ->
7455 pr " guestfs_free_%s (r);\n" typ
7456 | RStructList (_, typ) ->
7457 pr " guestfs_free_%s_list (r);\n" typ
7463 let str = replace_str str "\r" "\\r" in
7464 let str = replace_str str "\n" "\\n" in
7465 let str = replace_str str "\t" "\\t" in
7466 let str = replace_str str "\000" "\\0" in
7469 (* Generate a lot of different functions for guestfish. *)
7470 and generate_fish_cmds () =
7471 generate_header CStyle GPLv2plus;
7475 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7477 let all_functions_sorted =
7479 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7480 ) all_functions_sorted in
7482 pr "#include <config.h>\n";
7484 pr "#include <stdio.h>\n";
7485 pr "#include <stdlib.h>\n";
7486 pr "#include <string.h>\n";
7487 pr "#include <inttypes.h>\n";
7489 pr "#include <guestfs.h>\n";
7490 pr "#include \"c-ctype.h\"\n";
7491 pr "#include \"full-write.h\"\n";
7492 pr "#include \"xstrtol.h\"\n";
7493 pr "#include \"fish.h\"\n";
7495 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
7496 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7499 (* list_commands function, which implements guestfish -h *)
7500 pr "void list_commands (void)\n";
7502 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7503 pr " list_builtin_commands ();\n";
7505 fun (name, _, _, flags, _, shortdesc, _) ->
7506 let name = replace_char name '_' '-' in
7507 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7509 ) all_functions_sorted;
7510 pr " printf (\" %%s\\n\",";
7511 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7515 (* display_command function, which implements guestfish -h cmd *)
7516 pr "void display_command (const char *cmd)\n";
7519 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7520 let name2 = replace_char name '_' '-' in
7522 try find_map (function FishAlias n -> Some n | _ -> None) flags
7523 with Not_found -> name in
7524 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7526 match snd style with
7530 name2 (String.concat " " (List.map name_of_argt args)) in
7533 if List.mem ProtocolLimitWarning flags then
7534 ("\n\n" ^ protocol_limit_warning)
7537 (* For DangerWillRobinson commands, we should probably have
7538 * guestfish prompt before allowing you to use them (especially
7539 * in interactive mode). XXX
7543 if List.mem DangerWillRobinson flags then
7544 ("\n\n" ^ danger_will_robinson)
7549 match deprecation_notice flags with
7551 | Some txt -> "\n\n" ^ txt in
7553 let describe_alias =
7554 if name <> alias then
7555 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7559 pr "STRCASEEQ (cmd, \"%s\")" name;
7560 if name <> name2 then
7561 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7562 if name <> alias then
7563 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7565 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7567 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7568 "=head1 DESCRIPTION\n\n" ^
7569 longdesc ^ warnings ^ describe_alias);
7572 pr " display_builtin_command (cmd);\n";
7576 let emit_print_list_function typ =
7577 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7580 pr " unsigned int i;\n";
7582 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7583 pr " printf (\"[%%d] = {\\n\", i);\n";
7584 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7585 pr " printf (\"}\\n\");\n";
7591 (* print_* functions *)
7595 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7597 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7600 pr " unsigned int i;\n";
7606 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7608 pr " printf (\"%%s%s: \", indent);\n" name;
7609 pr " for (i = 0; i < 32; ++i)\n";
7610 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7611 pr " printf (\"\\n\");\n"
7613 pr " printf (\"%%s%s: \", indent);\n" name;
7614 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7615 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7616 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7618 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7619 pr " printf (\"\\n\");\n"
7620 | name, (FUInt64|FBytes) ->
7621 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7624 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7627 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7630 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7633 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7635 | name, FOptPercent ->
7636 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7637 typ name name typ name;
7638 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7644 (* Emit a print_TYPE_list function definition only if that function is used. *)
7647 | typ, (RStructListOnly | RStructAndList) ->
7648 (* generate the function for typ *)
7649 emit_print_list_function typ
7650 | typ, _ -> () (* empty *)
7651 ) (rstructs_used_by all_functions);
7653 (* Emit a print_TYPE function definition only if that function is used. *)
7656 | typ, (RStructOnly | RStructAndList) ->
7657 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7659 pr " print_%s_indent (%s, \"\");\n" typ typ;
7662 | typ, _ -> () (* empty *)
7663 ) (rstructs_used_by all_functions);
7665 (* run_<action> actions *)
7667 fun (name, style, _, flags, _, _, _) ->
7668 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7670 (match fst style with
7673 | RBool _ -> pr " int r;\n"
7674 | RInt64 _ -> pr " int64_t r;\n"
7675 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7676 | RString _ -> pr " char *r;\n"
7677 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7678 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7679 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7682 pr " size_t size;\n";
7688 | OptString n -> pr " const char *%s;\n" n
7692 | FileOut n -> pr " char *%s;\n" n
7694 pr " const char *%s;\n" n;
7695 pr " size_t %s_size;\n" n
7696 | StringList n | DeviceList n -> pr " char **%s;\n" n
7697 | Bool n -> pr " int %s;\n" n
7698 | Int n -> pr " int %s;\n" n
7699 | Int64 n -> pr " int64_t %s;\n" n
7702 (* Check and convert parameters. *)
7703 let argc_expected = List.length (snd style) in
7704 pr " if (argc != %d) {\n" argc_expected;
7705 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7707 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7711 let parse_integer fn fntyp rtyp range name i =
7713 pr " strtol_error xerr;\n";
7714 pr " %s r;\n" fntyp;
7716 pr " xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7717 pr " if (xerr != LONGINT_OK) {\n";
7718 pr " fprintf (stderr,\n";
7719 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7720 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7725 | Some (min, max, comment) ->
7726 pr " /* %s */\n" comment;
7727 pr " if (r < %s || r > %s) {\n" min max;
7728 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7732 pr " /* The check above should ensure this assignment does not overflow. */\n";
7734 pr " %s = r;\n" name;
7743 pr " %s = argv[%d];\n" name i
7745 | Dev_or_Path name ->
7746 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7747 pr " if (%s == NULL) return -1;\n" name
7749 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7752 pr " %s = argv[%d];\n" name i;
7753 pr " %s_size = strlen (argv[%d]);\n" name i
7755 pr " %s = file_in (argv[%d]);\n" name i;
7756 pr " if (%s == NULL) return -1;\n" name
7758 pr " %s = file_out (argv[%d]);\n" name i;
7759 pr " if (%s == NULL) return -1;\n" name
7760 | StringList name | DeviceList name ->
7761 pr " %s = parse_string_list (argv[%d]);\n" name i;
7762 pr " if (%s == NULL) return -1;\n" name;
7764 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7767 let min = "(-(2LL<<30))"
7768 and max = "((2LL<<30)-1)"
7770 "The Int type in the generator is a signed 31 bit int." in
7771 Some (min, max, comment) in
7772 parse_integer "xstrtoll" "long long" "int" range name i
7774 parse_integer "xstrtoll" "long long" "int64_t" None name i
7777 (* Call C API function. *)
7778 pr " r = guestfs_%s " name;
7779 generate_c_call_args ~handle:"g" style;
7784 | Device name | String name
7785 | OptString name | Bool name
7786 | Int name | Int64 name
7787 | BufferIn name -> ()
7788 | Pathname name | Dev_or_Path name | FileOut name ->
7789 pr " free (%s);\n" name
7791 pr " free_file_in (%s);\n" name
7792 | StringList name | DeviceList name ->
7793 pr " free_strings (%s);\n" name
7796 (* Any output flags? *)
7798 let flags = filter_map (
7799 function FishOutput flag -> Some flag | _ -> None
7805 failwithf "%s: more than one FishOutput flag is not allowed" name in
7807 (* Check return value for errors and display command results. *)
7808 (match fst style with
7809 | RErr -> pr " return r;\n"
7811 pr " if (r == -1) return -1;\n";
7812 (match fish_output with
7814 pr " printf (\"%%d\\n\", r);\n";
7815 | Some FishOutputOctal ->
7816 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7817 | Some FishOutputHexadecimal ->
7818 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7821 pr " if (r == -1) return -1;\n";
7822 (match fish_output with
7824 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7825 | Some FishOutputOctal ->
7826 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7827 | Some FishOutputHexadecimal ->
7828 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7831 pr " if (r == -1) return -1;\n";
7832 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7835 pr " if (r == NULL) return -1;\n";
7836 pr " printf (\"%%s\\n\", r);\n";
7838 | RConstOptString _ ->
7839 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7842 pr " if (r == NULL) return -1;\n";
7843 pr " printf (\"%%s\\n\", r);\n";
7847 pr " if (r == NULL) return -1;\n";
7848 pr " print_strings (r);\n";
7849 pr " free_strings (r);\n";
7851 | RStruct (_, typ) ->
7852 pr " if (r == NULL) return -1;\n";
7853 pr " print_%s (r);\n" typ;
7854 pr " guestfs_free_%s (r);\n" typ;
7856 | RStructList (_, typ) ->
7857 pr " if (r == NULL) return -1;\n";
7858 pr " print_%s_list (r);\n" typ;
7859 pr " guestfs_free_%s_list (r);\n" typ;
7862 pr " if (r == NULL) return -1;\n";
7863 pr " print_table (r);\n";
7864 pr " free_strings (r);\n";
7867 pr " if (r == NULL) return -1;\n";
7868 pr " if (full_write (1, r, size) != size) {\n";
7869 pr " perror (\"write\");\n";
7880 (* run_action function *)
7881 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7884 fun (name, _, _, flags, _, _, _) ->
7885 let name2 = replace_char name '_' '-' in
7887 try find_map (function FishAlias n -> Some n | _ -> None) flags
7888 with Not_found -> name in
7890 pr "STRCASEEQ (cmd, \"%s\")" name;
7891 if name <> name2 then
7892 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7893 if name <> alias then
7894 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7896 pr " return run_%s (cmd, argc, argv);\n" name;
7900 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7901 pr " if (command_num == 1)\n";
7902 pr " extended_help_message ();\n";
7909 (* Readline completion for guestfish. *)
7910 and generate_fish_completion () =
7911 generate_header CStyle GPLv2plus;
7915 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7925 #ifdef HAVE_LIBREADLINE
7926 #include <readline/readline.h>
7931 #ifdef HAVE_LIBREADLINE
7933 static const char *const commands[] = {
7934 BUILTIN_COMMANDS_FOR_COMPLETION,
7937 (* Get the commands, including the aliases. They don't need to be
7938 * sorted - the generator() function just does a dumb linear search.
7942 fun (name, _, _, flags, _, _, _) ->
7943 let name2 = replace_char name '_' '-' in
7945 try find_map (function FishAlias n -> Some n | _ -> None) flags
7946 with Not_found -> name in
7948 if name <> alias then [name2; alias] else [name2]
7950 let commands = List.flatten commands in
7952 List.iter (pr " \"%s\",\n") commands;
7958 generator (const char *text, int state)
7960 static int index, len;
7965 len = strlen (text);
7968 rl_attempted_completion_over = 1;
7970 while ((name = commands[index]) != NULL) {
7972 if (STRCASEEQLEN (name, text, len))
7973 return strdup (name);
7979 #endif /* HAVE_LIBREADLINE */
7981 #ifdef HAVE_RL_COMPLETION_MATCHES
7982 #define RL_COMPLETION_MATCHES rl_completion_matches
7984 #ifdef HAVE_COMPLETION_MATCHES
7985 #define RL_COMPLETION_MATCHES completion_matches
7987 #endif /* else just fail if we don't have either symbol */
7990 do_completion (const char *text, int start, int end)
7992 char **matches = NULL;
7994 #ifdef HAVE_LIBREADLINE
7995 rl_completion_append_character = ' ';
7998 matches = RL_COMPLETION_MATCHES (text, generator);
7999 else if (complete_dest_paths)
8000 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8007 (* Generate the POD documentation for guestfish. *)
8008 and generate_fish_actions_pod () =
8009 let all_functions_sorted =
8011 fun (_, _, _, flags, _, _, _) ->
8012 not (List.mem NotInFish flags || List.mem NotInDocs flags)
8013 ) all_functions_sorted in
8015 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8018 fun (name, style, _, flags, _, _, longdesc) ->
8020 Str.global_substitute rex (
8023 try Str.matched_group 1 s
8025 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8026 "C<" ^ replace_char sub '_' '-' ^ ">"
8028 let name = replace_char name '_' '-' in
8030 try find_map (function FishAlias n -> Some n | _ -> None) flags
8031 with Not_found -> name in
8033 pr "=head2 %s" name;
8034 if name <> alias then
8041 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8042 | OptString n -> pr " %s" n
8043 | StringList n | DeviceList n -> pr " '%s ...'" n
8044 | Bool _ -> pr " true|false"
8045 | Int n -> pr " %s" n
8046 | Int64 n -> pr " %s" n
8047 | FileIn n | FileOut n -> pr " (%s|-)" n
8048 | BufferIn n -> pr " %s" n
8052 pr "%s\n\n" longdesc;
8054 if List.exists (function FileIn _ | FileOut _ -> true
8055 | _ -> false) (snd style) then
8056 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8058 if List.mem ProtocolLimitWarning flags then
8059 pr "%s\n\n" protocol_limit_warning;
8061 if List.mem DangerWillRobinson flags then
8062 pr "%s\n\n" danger_will_robinson;
8064 match deprecation_notice flags with
8066 | Some txt -> pr "%s\n\n" txt
8067 ) all_functions_sorted
8069 (* Generate a C function prototype. *)
8070 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8071 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8073 ?handle name style =
8074 if extern then pr "extern ";
8075 if static then pr "static ";
8076 (match fst style with
8078 | RInt _ -> pr "int "
8079 | RInt64 _ -> pr "int64_t "
8080 | RBool _ -> pr "int "
8081 | RConstString _ | RConstOptString _ -> pr "const char *"
8082 | RString _ | RBufferOut _ -> pr "char *"
8083 | RStringList _ | RHashtable _ -> pr "char **"
8084 | RStruct (_, typ) ->
8085 if not in_daemon then pr "struct guestfs_%s *" typ
8086 else pr "guestfs_int_%s *" typ
8087 | RStructList (_, typ) ->
8088 if not in_daemon then pr "struct guestfs_%s_list *" typ
8089 else pr "guestfs_int_%s_list *" typ
8091 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8092 pr "%s%s (" prefix name;
8093 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8096 let comma = ref false in
8099 | Some handle -> pr "guestfs_h *%s" handle; comma := true
8103 if single_line then pr ", " else pr ",\n\t\t"
8110 | Device n | Dev_or_Path n
8114 pr "const char *%s" n
8115 | StringList n | DeviceList n ->
8117 pr "char *const *%s" n
8118 | Bool n -> next (); pr "int %s" n
8119 | Int n -> next (); pr "int %s" n
8120 | Int64 n -> next (); pr "int64_t %s" n
8123 if not in_daemon then (next (); pr "const char *%s" n)
8126 pr "const char *%s" n;
8128 pr "size_t %s_size" n
8130 if is_RBufferOut then (next (); pr "size_t *size_r");
8133 if semicolon then pr ";";
8134 if newline then pr "\n"
8136 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8137 and generate_c_call_args ?handle ?(decl = false) style =
8139 let comma = ref false in
8141 if !comma then pr ", ";
8146 | Some handle -> pr "%s" handle; comma := true
8152 pr "%s, %s_size" n n
8155 pr "%s" (name_of_argt arg)
8157 (* For RBufferOut calls, add implicit &size parameter. *)
8159 match fst style with
8167 (* Generate the OCaml bindings interface. *)
8168 and generate_ocaml_mli () =
8169 generate_header OCamlStyle LGPLv2plus;
8172 (** For API documentation you should refer to the C API
8173 in the guestfs(3) manual page. The OCaml API uses almost
8174 exactly the same calls. *)
8177 (** A [guestfs_h] handle. *)
8179 exception Error of string
8180 (** This exception is raised when there is an error. *)
8182 exception Handle_closed of string
8183 (** This exception is raised if you use a {!Guestfs.t} handle
8184 after calling {!close} on it. The string is the name of
8187 val create : unit -> t
8188 (** Create a {!Guestfs.t} handle. *)
8190 val close : t -> unit
8191 (** Close the {!Guestfs.t} handle and free up all resources used
8194 Handles are closed by the garbage collector when they become
8195 unreferenced, but callers can call this in order to provide
8196 predictable cleanup. *)
8199 generate_ocaml_structure_decls ();
8203 fun (name, style, _, _, _, shortdesc, _) ->
8204 generate_ocaml_prototype name style;
8205 pr "(** %s *)\n" shortdesc;
8207 ) all_functions_sorted
8209 (* Generate the OCaml bindings implementation. *)
8210 and generate_ocaml_ml () =
8211 generate_header OCamlStyle LGPLv2plus;
8216 exception Error of string
8217 exception Handle_closed of string
8219 external create : unit -> t = \"ocaml_guestfs_create\"
8220 external close : t -> unit = \"ocaml_guestfs_close\"
8222 (* Give the exceptions names, so they can be raised from the C code. *)
8224 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8225 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8229 generate_ocaml_structure_decls ();
8233 fun (name, style, _, _, _, shortdesc, _) ->
8234 generate_ocaml_prototype ~is_external:true name style;
8235 ) all_functions_sorted
8237 (* Generate the OCaml bindings C implementation. *)
8238 and generate_ocaml_c () =
8239 generate_header CStyle LGPLv2plus;
8246 #include <caml/config.h>
8247 #include <caml/alloc.h>
8248 #include <caml/callback.h>
8249 #include <caml/fail.h>
8250 #include <caml/memory.h>
8251 #include <caml/mlvalues.h>
8252 #include <caml/signals.h>
8254 #include <guestfs.h>
8256 #include \"guestfs_c.h\"
8258 /* Copy a hashtable of string pairs into an assoc-list. We return
8259 * the list in reverse order, but hashtables aren't supposed to be
8262 static CAMLprim value
8263 copy_table (char * const * argv)
8266 CAMLlocal5 (rv, pairv, kv, vv, cons);
8270 for (i = 0; argv[i] != NULL; i += 2) {
8271 kv = caml_copy_string (argv[i]);
8272 vv = caml_copy_string (argv[i+1]);
8273 pairv = caml_alloc (2, 0);
8274 Store_field (pairv, 0, kv);
8275 Store_field (pairv, 1, vv);
8276 cons = caml_alloc (2, 0);
8277 Store_field (cons, 1, rv);
8279 Store_field (cons, 0, pairv);
8287 (* Struct copy functions. *)
8289 let emit_ocaml_copy_list_function typ =
8290 pr "static CAMLprim value\n";
8291 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8293 pr " CAMLparam0 ();\n";
8294 pr " CAMLlocal2 (rv, v);\n";
8295 pr " unsigned int i;\n";
8297 pr " if (%ss->len == 0)\n" typ;
8298 pr " CAMLreturn (Atom (0));\n";
8300 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8301 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8302 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8303 pr " caml_modify (&Field (rv, i), v);\n";
8305 pr " CAMLreturn (rv);\n";
8313 let has_optpercent_col =
8314 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8316 pr "static CAMLprim value\n";
8317 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8319 pr " CAMLparam0 ();\n";
8320 if has_optpercent_col then
8321 pr " CAMLlocal3 (rv, v, v2);\n"
8323 pr " CAMLlocal2 (rv, v);\n";
8325 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8330 pr " v = caml_copy_string (%s->%s);\n" typ name
8332 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8333 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8336 pr " v = caml_alloc_string (32);\n";
8337 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8338 | name, (FBytes|FInt64|FUInt64) ->
8339 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8340 | name, (FInt32|FUInt32) ->
8341 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8342 | name, FOptPercent ->
8343 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8344 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8345 pr " v = caml_alloc (1, 0);\n";
8346 pr " Store_field (v, 0, v2);\n";
8347 pr " } else /* None */\n";
8348 pr " v = Val_int (0);\n";
8350 pr " v = Val_int (%s->%s);\n" typ name
8352 pr " Store_field (rv, %d, v);\n" i
8354 pr " CAMLreturn (rv);\n";
8359 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8362 | typ, (RStructListOnly | RStructAndList) ->
8363 (* generate the function for typ *)
8364 emit_ocaml_copy_list_function typ
8365 | typ, _ -> () (* empty *)
8366 ) (rstructs_used_by all_functions);
8370 fun (name, style, _, _, _, _, _) ->
8371 pr "/* Automatically generated wrapper for function\n";
8373 generate_ocaml_prototype name style;
8378 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8380 let needs_extra_vs =
8381 match fst style with RConstOptString _ -> true | _ -> false in
8383 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8384 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8385 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8388 pr "CAMLprim value\n";
8389 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8390 List.iter (pr ", value %s") (List.tl params);
8395 | [p1; p2; p3; p4; p5] ->
8396 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8397 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8398 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8399 pr " CAMLxparam%d (%s);\n"
8400 (List.length rest) (String.concat ", " rest)
8402 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8404 if not needs_extra_vs then
8405 pr " CAMLlocal1 (rv);\n"
8407 pr " CAMLlocal3 (rv, v, v2);\n";
8410 pr " guestfs_h *g = Guestfs_val (gv);\n";
8411 pr " if (g == NULL)\n";
8412 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8418 | Device n | Dev_or_Path n
8422 pr " const char *%s = String_val (%sv);\n" n n
8424 pr " const char *%s =\n" n;
8425 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8428 pr " const char *%s = String_val (%sv);\n" n n;
8429 pr " size_t %s_size = caml_string_length (%sv);\n" n n
8430 | StringList n | DeviceList n ->
8431 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8433 pr " int %s = Bool_val (%sv);\n" n n
8435 pr " int %s = Int_val (%sv);\n" n n
8437 pr " int64_t %s = Int64_val (%sv);\n" n n
8440 match fst style with
8441 | RErr -> pr " int r;\n"; "-1"
8442 | RInt _ -> pr " int r;\n"; "-1"
8443 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8444 | RBool _ -> pr " int r;\n"; "-1"
8445 | RConstString _ | RConstOptString _ ->
8446 pr " const char *r;\n"; "NULL"
8447 | RString _ -> pr " char *r;\n"; "NULL"
8452 | RStruct (_, typ) ->
8453 pr " struct guestfs_%s *r;\n" typ; "NULL"
8454 | RStructList (_, typ) ->
8455 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8462 pr " size_t size;\n";
8466 pr " caml_enter_blocking_section ();\n";
8467 pr " r = guestfs_%s " name;
8468 generate_c_call_args ~handle:"g" style;
8470 pr " caml_leave_blocking_section ();\n";
8474 | StringList n | DeviceList n ->
8475 pr " ocaml_guestfs_free_strings (%s);\n" n;
8476 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8477 | Bool _ | Int _ | Int64 _
8478 | FileIn _ | FileOut _ | BufferIn _ -> ()
8481 pr " if (r == %s)\n" error_code;
8482 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8485 (match fst style with
8486 | RErr -> pr " rv = Val_unit;\n"
8487 | RInt _ -> pr " rv = Val_int (r);\n"
8489 pr " rv = caml_copy_int64 (r);\n"
8490 | RBool _ -> pr " rv = Val_bool (r);\n"
8492 pr " rv = caml_copy_string (r);\n"
8493 | RConstOptString _ ->
8494 pr " if (r) { /* Some string */\n";
8495 pr " v = caml_alloc (1, 0);\n";
8496 pr " v2 = caml_copy_string (r);\n";
8497 pr " Store_field (v, 0, v2);\n";
8498 pr " } else /* None */\n";
8499 pr " v = Val_int (0);\n";
8501 pr " rv = caml_copy_string (r);\n";
8504 pr " rv = caml_copy_string_array ((const char **) r);\n";
8505 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8507 | RStruct (_, typ) ->
8508 pr " rv = copy_%s (r);\n" typ;
8509 pr " guestfs_free_%s (r);\n" typ;
8510 | RStructList (_, typ) ->
8511 pr " rv = copy_%s_list (r);\n" typ;
8512 pr " guestfs_free_%s_list (r);\n" typ;
8514 pr " rv = copy_table (r);\n";
8515 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8518 pr " rv = caml_alloc_string (size);\n";
8519 pr " memcpy (String_val (rv), r, size);\n";
8522 pr " CAMLreturn (rv);\n";
8526 if List.length params > 5 then (
8527 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8528 pr "CAMLprim value ";
8529 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8530 pr "CAMLprim value\n";
8531 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8533 pr " return ocaml_guestfs_%s (argv[0]" name;
8534 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8539 ) all_functions_sorted
8541 and generate_ocaml_structure_decls () =
8544 pr "type %s = {\n" typ;
8547 | name, FString -> pr " %s : string;\n" name
8548 | name, FBuffer -> pr " %s : string;\n" name
8549 | name, FUUID -> pr " %s : string;\n" name
8550 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8551 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8552 | name, FChar -> pr " %s : char;\n" name
8553 | name, FOptPercent -> pr " %s : float option;\n" name
8559 and generate_ocaml_prototype ?(is_external = false) name style =
8560 if is_external then pr "external " else pr "val ";
8561 pr "%s : t -> " name;
8564 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8565 | BufferIn _ -> pr "string -> "
8566 | OptString _ -> pr "string option -> "
8567 | StringList _ | DeviceList _ -> pr "string array -> "
8568 | Bool _ -> pr "bool -> "
8569 | Int _ -> pr "int -> "
8570 | Int64 _ -> pr "int64 -> "
8572 (match fst style with
8573 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8574 | RInt _ -> pr "int"
8575 | RInt64 _ -> pr "int64"
8576 | RBool _ -> pr "bool"
8577 | RConstString _ -> pr "string"
8578 | RConstOptString _ -> pr "string option"
8579 | RString _ | RBufferOut _ -> pr "string"
8580 | RStringList _ -> pr "string array"
8581 | RStruct (_, typ) -> pr "%s" typ
8582 | RStructList (_, typ) -> pr "%s array" typ
8583 | RHashtable _ -> pr "(string * string) list"
8585 if is_external then (
8587 if List.length (snd style) + 1 > 5 then
8588 pr "\"ocaml_guestfs_%s_byte\" " name;
8589 pr "\"ocaml_guestfs_%s\"" name
8593 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8594 and generate_perl_xs () =
8595 generate_header CStyle LGPLv2plus;
8598 #include \"EXTERN.h\"
8602 #include <guestfs.h>
8605 #define PRId64 \"lld\"
8609 my_newSVll(long long val) {
8610 #ifdef USE_64_BIT_ALL
8611 return newSViv(val);
8615 len = snprintf(buf, 100, \"%%\" PRId64, val);
8616 return newSVpv(buf, len);
8621 #define PRIu64 \"llu\"
8625 my_newSVull(unsigned long long val) {
8626 #ifdef USE_64_BIT_ALL
8627 return newSVuv(val);
8631 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8632 return newSVpv(buf, len);
8636 /* http://www.perlmonks.org/?node_id=680842 */
8638 XS_unpack_charPtrPtr (SV *arg) {
8643 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8644 croak (\"array reference expected\");
8646 av = (AV *)SvRV (arg);
8647 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8649 croak (\"malloc failed\");
8651 for (i = 0; i <= av_len (av); i++) {
8652 SV **elem = av_fetch (av, i, 0);
8654 if (!elem || !*elem)
8655 croak (\"missing element in list\");
8657 ret[i] = SvPV_nolen (*elem);
8665 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8672 RETVAL = guestfs_create ();
8674 croak (\"could not create guestfs handle\");
8675 guestfs_set_error_handler (RETVAL, NULL, NULL);
8688 fun (name, style, _, _, _, _, _) ->
8689 (match fst style with
8690 | RErr -> pr "void\n"
8691 | RInt _ -> pr "SV *\n"
8692 | RInt64 _ -> pr "SV *\n"
8693 | RBool _ -> pr "SV *\n"
8694 | RConstString _ -> pr "SV *\n"
8695 | RConstOptString _ -> pr "SV *\n"
8696 | RString _ -> pr "SV *\n"
8697 | RBufferOut _ -> pr "SV *\n"
8699 | RStruct _ | RStructList _
8701 pr "void\n" (* all lists returned implictly on the stack *)
8703 (* Call and arguments. *)
8706 fun arg -> pr ", %s" (name_of_argt arg)
8709 pr " guestfs_h *g;\n";
8713 | Pathname n | Device n | Dev_or_Path n | String n
8714 | FileIn n | FileOut n ->
8717 pr " char *%s;\n" n;
8718 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8720 (* http://www.perlmonks.org/?node_id=554277
8721 * Note that the implicit handle argument means we have
8722 * to add 1 to the ST(x) operator.
8724 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8725 | StringList n | DeviceList n -> pr " char **%s;\n" n
8726 | Bool n -> pr " int %s;\n" n
8727 | Int n -> pr " int %s;\n" n
8728 | Int64 n -> pr " int64_t %s;\n" n
8731 let do_cleanups () =
8734 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8735 | Bool _ | Int _ | Int64 _
8736 | FileIn _ | FileOut _
8738 | StringList n | DeviceList n -> pr " free (%s);\n" n
8743 (match fst style with
8748 pr " r = guestfs_%s " name;
8749 generate_c_call_args ~handle:"g" style;
8752 pr " if (r == -1)\n";
8753 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8759 pr " %s = guestfs_%s " n name;
8760 generate_c_call_args ~handle:"g" style;
8763 pr " if (%s == -1)\n" n;
8764 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8765 pr " RETVAL = newSViv (%s);\n" n;
8770 pr " int64_t %s;\n" n;
8772 pr " %s = guestfs_%s " n name;
8773 generate_c_call_args ~handle:"g" style;
8776 pr " if (%s == -1)\n" n;
8777 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8778 pr " RETVAL = my_newSVll (%s);\n" n;
8783 pr " const char *%s;\n" n;
8785 pr " %s = guestfs_%s " n name;
8786 generate_c_call_args ~handle:"g" style;
8789 pr " if (%s == NULL)\n" n;
8790 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8791 pr " RETVAL = newSVpv (%s, 0);\n" n;
8794 | RConstOptString n ->
8796 pr " const char *%s;\n" n;
8798 pr " %s = guestfs_%s " n name;
8799 generate_c_call_args ~handle:"g" style;
8802 pr " if (%s == NULL)\n" n;
8803 pr " RETVAL = &PL_sv_undef;\n";
8805 pr " RETVAL = newSVpv (%s, 0);\n" n;
8810 pr " char *%s;\n" n;
8812 pr " %s = guestfs_%s " n name;
8813 generate_c_call_args ~handle:"g" style;
8816 pr " if (%s == NULL)\n" n;
8817 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8818 pr " RETVAL = newSVpv (%s, 0);\n" n;
8819 pr " free (%s);\n" n;
8822 | RStringList n | RHashtable n ->
8824 pr " char **%s;\n" n;
8827 pr " %s = guestfs_%s " n name;
8828 generate_c_call_args ~handle:"g" style;
8831 pr " if (%s == NULL)\n" n;
8832 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8833 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8834 pr " EXTEND (SP, n);\n";
8835 pr " for (i = 0; i < n; ++i) {\n";
8836 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8837 pr " free (%s[i]);\n" n;
8839 pr " free (%s);\n" n;
8840 | RStruct (n, typ) ->
8841 let cols = cols_of_struct typ in
8842 generate_perl_struct_code typ cols name style n do_cleanups
8843 | RStructList (n, typ) ->
8844 let cols = cols_of_struct typ in
8845 generate_perl_struct_list_code typ cols name style n do_cleanups
8848 pr " char *%s;\n" n;
8849 pr " size_t size;\n";
8851 pr " %s = guestfs_%s " n name;
8852 generate_c_call_args ~handle:"g" style;
8855 pr " if (%s == NULL)\n" n;
8856 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8857 pr " RETVAL = newSVpvn (%s, size);\n" n;
8858 pr " free (%s);\n" n;
8866 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8868 pr " struct guestfs_%s_list *%s;\n" typ n;
8872 pr " %s = guestfs_%s " n name;
8873 generate_c_call_args ~handle:"g" style;
8876 pr " if (%s == NULL)\n" n;
8877 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8878 pr " EXTEND (SP, %s->len);\n" n;
8879 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8880 pr " hv = newHV ();\n";
8884 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8885 name (String.length name) n name
8887 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8888 name (String.length name) n name
8890 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8891 name (String.length name) n name n name
8892 | name, (FBytes|FUInt64) ->
8893 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8894 name (String.length name) n name
8896 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8897 name (String.length name) n name
8898 | name, (FInt32|FUInt32) ->
8899 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8900 name (String.length name) n name
8902 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8903 name (String.length name) n name
8904 | name, FOptPercent ->
8905 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8906 name (String.length name) n name
8908 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8910 pr " guestfs_free_%s_list (%s);\n" typ n
8912 and generate_perl_struct_code typ cols name style n do_cleanups =
8914 pr " struct guestfs_%s *%s;\n" typ n;
8916 pr " %s = guestfs_%s " n name;
8917 generate_c_call_args ~handle:"g" style;
8920 pr " if (%s == NULL)\n" n;
8921 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8922 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8924 fun ((name, _) as col) ->
8925 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8929 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8932 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8935 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8937 | name, (FBytes|FUInt64) ->
8938 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8941 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8943 | name, (FInt32|FUInt32) ->
8944 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8947 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8949 | name, FOptPercent ->
8950 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8953 pr " free (%s);\n" n
8955 (* Generate Sys/Guestfs.pm. *)
8956 and generate_perl_pm () =
8957 generate_header HashStyle LGPLv2plus;
8964 Sys::Guestfs - Perl bindings for libguestfs
8970 my $h = Sys::Guestfs->new ();
8971 $h->add_drive ('guest.img');
8973 $h->mount ('/dev/sda1', '/');
8974 $h->touch ('/hello');
8979 The C<Sys::Guestfs> module provides a Perl XS binding to the
8980 libguestfs API for examining and modifying virtual machine
8983 Amongst the things this is good for: making batch configuration
8984 changes to guests, getting disk used/free statistics (see also:
8985 virt-df), migrating between virtualization systems (see also:
8986 virt-p2v), performing partial backups, performing partial guest
8987 clones, cloning guests and changing registry/UUID/hostname info, and
8990 Libguestfs uses Linux kernel and qemu code, and can access any type of
8991 guest filesystem that Linux and qemu can, including but not limited
8992 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8993 schemes, qcow, qcow2, vmdk.
8995 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8996 LVs, what filesystem is in each LV, etc.). It can also run commands
8997 in the context of the guest. Also you can access filesystems over
9000 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9001 functions for using libguestfs from Perl, including integration
9006 All errors turn into calls to C<croak> (see L<Carp(3)>).
9014 package Sys::Guestfs;
9019 # This version number changes whenever a new function
9020 # is added to the libguestfs API. It is not directly
9021 # related to the libguestfs version number.
9022 use vars qw($VERSION);
9026 XSLoader::load ('Sys::Guestfs');
9028 =item $h = Sys::Guestfs->new ();
9030 Create a new guestfs handle.
9036 my $class = ref ($proto) || $proto;
9038 my $self = Sys::Guestfs::_create ();
9039 bless $self, $class;
9045 (* Actions. We only need to print documentation for these as
9046 * they are pulled in from the XS code automatically.
9049 fun (name, style, _, flags, _, _, longdesc) ->
9050 if not (List.mem NotInDocs flags) then (
9051 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9053 generate_perl_prototype name style;
9055 pr "%s\n\n" longdesc;
9056 if List.mem ProtocolLimitWarning flags then
9057 pr "%s\n\n" protocol_limit_warning;
9058 if List.mem DangerWillRobinson flags then
9059 pr "%s\n\n" danger_will_robinson;
9060 match deprecation_notice flags with
9062 | Some txt -> pr "%s\n\n" txt
9064 ) all_functions_sorted;
9076 Copyright (C) %s Red Hat Inc.
9080 Please see the file COPYING.LIB for the full license.
9086 L<http://libguestfs.org>,
9087 L<Sys::Guestfs::Lib(3)>.
9092 and generate_perl_prototype name style =
9093 (match fst style with
9101 | RBufferOut n -> pr "$%s = " n
9103 | RHashtable n -> pr "%%%s = " n
9105 | RStructList (n,_) -> pr "@%s = " n
9108 let comma = ref false in
9111 if !comma then pr ", ";
9114 | Pathname n | Device n | Dev_or_Path n | String n
9115 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9118 | StringList n | DeviceList n ->
9123 (* Generate Python C module. *)
9124 and generate_python_c () =
9125 generate_header CStyle LGPLv2plus;
9128 #define PY_SSIZE_T_CLEAN 1
9131 #if PY_VERSION_HEX < 0x02050000
9132 typedef int Py_ssize_t;
9133 #define PY_SSIZE_T_MAX INT_MAX
9134 #define PY_SSIZE_T_MIN INT_MIN
9141 #include \"guestfs.h\"
9149 get_handle (PyObject *obj)
9152 assert (obj != Py_None);
9153 return ((Pyguestfs_Object *) obj)->g;
9157 put_handle (guestfs_h *g)
9161 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9164 /* This list should be freed (but not the strings) after use. */
9166 get_string_list (PyObject *obj)
9173 if (!PyList_Check (obj)) {
9174 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9178 len = PyList_Size (obj);
9179 r = malloc (sizeof (char *) * (len+1));
9181 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9185 for (i = 0; i < len; ++i)
9186 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9193 put_string_list (char * const * const argv)
9198 for (argc = 0; argv[argc] != NULL; ++argc)
9201 list = PyList_New (argc);
9202 for (i = 0; i < argc; ++i)
9203 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9209 put_table (char * const * const argv)
9211 PyObject *list, *item;
9214 for (argc = 0; argv[argc] != NULL; ++argc)
9217 list = PyList_New (argc >> 1);
9218 for (i = 0; i < argc; i += 2) {
9219 item = PyTuple_New (2);
9220 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9221 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9222 PyList_SetItem (list, i >> 1, item);
9229 free_strings (char **argv)
9233 for (argc = 0; argv[argc] != NULL; ++argc)
9239 py_guestfs_create (PyObject *self, PyObject *args)
9243 g = guestfs_create ();
9245 PyErr_SetString (PyExc_RuntimeError,
9246 \"guestfs.create: failed to allocate handle\");
9249 guestfs_set_error_handler (g, NULL, NULL);
9250 return put_handle (g);
9254 py_guestfs_close (PyObject *self, PyObject *args)
9259 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9261 g = get_handle (py_g);
9265 Py_INCREF (Py_None);
9271 let emit_put_list_function typ =
9272 pr "static PyObject *\n";
9273 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9275 pr " PyObject *list;\n";
9278 pr " list = PyList_New (%ss->len);\n" typ;
9279 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9280 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9281 pr " return list;\n";
9286 (* Structures, turned into Python dictionaries. *)
9289 pr "static PyObject *\n";
9290 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9292 pr " PyObject *dict;\n";
9294 pr " dict = PyDict_New ();\n";
9298 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9299 pr " PyString_FromString (%s->%s));\n"
9302 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9303 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9306 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9307 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9309 | name, (FBytes|FUInt64) ->
9310 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9311 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9314 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9315 pr " PyLong_FromLongLong (%s->%s));\n"
9318 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9319 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9322 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9323 pr " PyLong_FromLong (%s->%s));\n"
9325 | name, FOptPercent ->
9326 pr " if (%s->%s >= 0)\n" typ name;
9327 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9328 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9331 pr " Py_INCREF (Py_None);\n";
9332 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9335 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9336 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9338 pr " return dict;\n";
9344 (* Emit a put_TYPE_list function definition only if that function is used. *)
9347 | typ, (RStructListOnly | RStructAndList) ->
9348 (* generate the function for typ *)
9349 emit_put_list_function typ
9350 | typ, _ -> () (* empty *)
9351 ) (rstructs_used_by all_functions);
9353 (* Python wrapper functions. *)
9355 fun (name, style, _, _, _, _, _) ->
9356 pr "static PyObject *\n";
9357 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9360 pr " PyObject *py_g;\n";
9361 pr " guestfs_h *g;\n";
9362 pr " PyObject *py_r;\n";
9365 match fst style with
9366 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9367 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9368 | RConstString _ | RConstOptString _ ->
9369 pr " const char *r;\n"; "NULL"
9370 | RString _ -> pr " char *r;\n"; "NULL"
9371 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9372 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9373 | RStructList (_, typ) ->
9374 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9377 pr " size_t size;\n";
9382 | Pathname n | Device n | Dev_or_Path n | String n
9383 | FileIn n | FileOut n ->
9384 pr " const char *%s;\n" n
9385 | OptString n -> pr " const char *%s;\n" n
9387 pr " const char *%s;\n" n;
9388 pr " Py_ssize_t %s_size;\n" n
9389 | StringList n | DeviceList n ->
9390 pr " PyObject *py_%s;\n" n;
9391 pr " char **%s;\n" n
9392 | Bool n -> pr " int %s;\n" n
9393 | Int n -> pr " int %s;\n" n
9394 | Int64 n -> pr " long long %s;\n" n
9399 (* Convert the parameters. *)
9400 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9403 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9404 | OptString _ -> pr "z"
9405 | StringList _ | DeviceList _ -> pr "O"
9406 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9408 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9409 * emulate C's int/long/long long in Python?
9411 | BufferIn _ -> pr "s#"
9413 pr ":guestfs_%s\",\n" name;
9417 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9418 | OptString n -> pr ", &%s" n
9419 | StringList n | DeviceList n -> pr ", &py_%s" n
9420 | Bool n -> pr ", &%s" n
9421 | Int n -> pr ", &%s" n
9422 | Int64 n -> pr ", &%s" n
9423 | BufferIn n -> pr ", &%s, &%s_size" n n
9427 pr " return NULL;\n";
9429 pr " g = get_handle (py_g);\n";
9432 | Pathname _ | Device _ | Dev_or_Path _ | String _
9433 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9435 | StringList n | DeviceList n ->
9436 pr " %s = get_string_list (py_%s);\n" n n;
9437 pr " if (!%s) return NULL;\n" n
9442 pr " r = guestfs_%s " name;
9443 generate_c_call_args ~handle:"g" style;
9448 | Pathname _ | Device _ | Dev_or_Path _ | String _
9449 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9451 | StringList n | DeviceList n ->
9452 pr " free (%s);\n" n
9455 pr " if (r == %s) {\n" error_code;
9456 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9457 pr " return NULL;\n";
9461 (match fst style with
9463 pr " Py_INCREF (Py_None);\n";
9464 pr " py_r = Py_None;\n"
9466 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9467 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9468 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9469 | RConstOptString _ ->
9471 pr " py_r = PyString_FromString (r);\n";
9473 pr " Py_INCREF (Py_None);\n";
9474 pr " py_r = Py_None;\n";
9477 pr " py_r = PyString_FromString (r);\n";
9480 pr " py_r = put_string_list (r);\n";
9481 pr " free_strings (r);\n"
9482 | RStruct (_, typ) ->
9483 pr " py_r = put_%s (r);\n" typ;
9484 pr " guestfs_free_%s (r);\n" typ
9485 | RStructList (_, typ) ->
9486 pr " py_r = put_%s_list (r);\n" typ;
9487 pr " guestfs_free_%s_list (r);\n" typ
9489 pr " py_r = put_table (r);\n";
9490 pr " free_strings (r);\n"
9492 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9496 pr " return py_r;\n";
9501 (* Table of functions. *)
9502 pr "static PyMethodDef methods[] = {\n";
9503 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9504 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9506 fun (name, _, _, _, _, _, _) ->
9507 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9510 pr " { NULL, NULL, 0, NULL }\n";
9514 (* Init function. *)
9517 initlibguestfsmod (void)
9519 static int initialized = 0;
9521 if (initialized) return;
9522 Py_InitModule ((char *) \"libguestfsmod\", methods);
9527 (* Generate Python module. *)
9528 and generate_python_py () =
9529 generate_header HashStyle LGPLv2plus;
9532 u\"\"\"Python bindings for libguestfs
9535 g = guestfs.GuestFS ()
9536 g.add_drive (\"guest.img\")
9538 parts = g.list_partitions ()
9540 The guestfs module provides a Python binding to the libguestfs API
9541 for examining and modifying virtual machine disk images.
9543 Amongst the things this is good for: making batch configuration
9544 changes to guests, getting disk used/free statistics (see also:
9545 virt-df), migrating between virtualization systems (see also:
9546 virt-p2v), performing partial backups, performing partial guest
9547 clones, cloning guests and changing registry/UUID/hostname info, and
9550 Libguestfs uses Linux kernel and qemu code, and can access any type of
9551 guest filesystem that Linux and qemu can, including but not limited
9552 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9553 schemes, qcow, qcow2, vmdk.
9555 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9556 LVs, what filesystem is in each LV, etc.). It can also run commands
9557 in the context of the guest. Also you can access filesystems over
9560 Errors which happen while using the API are turned into Python
9561 RuntimeError exceptions.
9563 To create a guestfs handle you usually have to perform the following
9566 # Create the handle, call add_drive at least once, and possibly
9567 # several times if the guest has multiple block devices:
9568 g = guestfs.GuestFS ()
9569 g.add_drive (\"guest.img\")
9571 # Launch the qemu subprocess and wait for it to become ready:
9574 # Now you can issue commands, for example:
9579 import libguestfsmod
9582 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9584 def __init__ (self):
9585 \"\"\"Create a new libguestfs handle.\"\"\"
9586 self._o = libguestfsmod.create ()
9589 libguestfsmod.close (self._o)
9594 fun (name, style, _, flags, _, _, longdesc) ->
9596 generate_py_call_args ~handle:"self" (snd style);
9599 if not (List.mem NotInDocs flags) then (
9600 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9602 match fst style with
9603 | RErr | RInt _ | RInt64 _ | RBool _
9604 | RConstOptString _ | RConstString _
9605 | RString _ | RBufferOut _ -> doc
9607 doc ^ "\n\nThis function returns a list of strings."
9608 | RStruct (_, typ) ->
9609 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9610 | RStructList (_, typ) ->
9611 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9613 doc ^ "\n\nThis function returns a dictionary." in
9615 if List.mem ProtocolLimitWarning flags then
9616 doc ^ "\n\n" ^ protocol_limit_warning
9619 if List.mem DangerWillRobinson flags then
9620 doc ^ "\n\n" ^ danger_will_robinson
9623 match deprecation_notice flags with
9625 | Some txt -> doc ^ "\n\n" ^ txt in
9626 let doc = pod2text ~width:60 name doc in
9627 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9628 let doc = String.concat "\n " doc in
9629 pr " u\"\"\"%s\"\"\"\n" doc;
9631 pr " return libguestfsmod.%s " name;
9632 generate_py_call_args ~handle:"self._o" (snd style);
9637 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9638 and generate_py_call_args ~handle args =
9640 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9643 (* Useful if you need the longdesc POD text as plain text. Returns a
9646 * Because this is very slow (the slowest part of autogeneration),
9647 * we memoize the results.
9649 and pod2text ~width name longdesc =
9650 let key = width, name, longdesc in
9651 try Hashtbl.find pod2text_memo key
9653 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9654 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9656 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9657 let chan = open_process_in cmd in
9658 let lines = ref [] in
9660 let line = input_line chan in
9661 if i = 1 then (* discard the first line of output *)
9664 let line = triml line in
9665 lines := line :: !lines;
9668 let lines = try loop 1 with End_of_file -> List.rev !lines in
9670 (match close_process_in chan with
9673 failwithf "pod2text: process exited with non-zero status (%d)" i
9674 | WSIGNALED i | WSTOPPED i ->
9675 failwithf "pod2text: process signalled or stopped by signal %d" i
9677 Hashtbl.add pod2text_memo key lines;
9678 pod2text_memo_updated ();
9681 (* Generate ruby bindings. *)
9682 and generate_ruby_c () =
9683 generate_header CStyle LGPLv2plus;
9691 #include \"guestfs.h\"
9693 #include \"extconf.h\"
9695 /* For Ruby < 1.9 */
9697 #define RARRAY_LEN(r) (RARRAY((r))->len)
9700 static VALUE m_guestfs; /* guestfs module */
9701 static VALUE c_guestfs; /* guestfs_h handle */
9702 static VALUE e_Error; /* used for all errors */
9704 static void ruby_guestfs_free (void *p)
9707 guestfs_close ((guestfs_h *) p);
9710 static VALUE ruby_guestfs_create (VALUE m)
9714 g = guestfs_create ();
9716 rb_raise (e_Error, \"failed to create guestfs handle\");
9718 /* Don't print error messages to stderr by default. */
9719 guestfs_set_error_handler (g, NULL, NULL);
9721 /* Wrap it, and make sure the close function is called when the
9724 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9727 static VALUE ruby_guestfs_close (VALUE gv)
9730 Data_Get_Struct (gv, guestfs_h, g);
9732 ruby_guestfs_free (g);
9733 DATA_PTR (gv) = NULL;
9741 fun (name, style, _, _, _, _, _) ->
9742 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9743 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9746 pr " guestfs_h *g;\n";
9747 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9749 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9755 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9756 pr " Check_Type (%sv, T_STRING);\n" n;
9757 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9759 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9760 pr " \"%s\", \"%s\");\n" n name
9762 pr " Check_Type (%sv, T_STRING);\n" n;
9763 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
9765 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9766 pr " \"%s\", \"%s\");\n" n name;
9767 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
9769 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9770 | StringList n | DeviceList n ->
9771 pr " char **%s;\n" n;
9772 pr " Check_Type (%sv, T_ARRAY);\n" n;
9774 pr " int i, len;\n";
9775 pr " len = RARRAY_LEN (%sv);\n" n;
9776 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9778 pr " for (i = 0; i < len; ++i) {\n";
9779 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9780 pr " %s[i] = StringValueCStr (v);\n" n;
9782 pr " %s[len] = NULL;\n" n;
9785 pr " int %s = RTEST (%sv);\n" n n
9787 pr " int %s = NUM2INT (%sv);\n" n n
9789 pr " long long %s = NUM2LL (%sv);\n" n n
9794 match fst style with
9795 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9796 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9797 | RConstString _ | RConstOptString _ ->
9798 pr " const char *r;\n"; "NULL"
9799 | RString _ -> pr " char *r;\n"; "NULL"
9800 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9801 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9802 | RStructList (_, typ) ->
9803 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9806 pr " size_t size;\n";
9810 pr " r = guestfs_%s " name;
9811 generate_c_call_args ~handle:"g" style;
9816 | Pathname _ | Device _ | Dev_or_Path _ | String _
9817 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9819 | StringList n | DeviceList n ->
9820 pr " free (%s);\n" n
9823 pr " if (r == %s)\n" error_code;
9824 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9827 (match fst style with
9829 pr " return Qnil;\n"
9830 | RInt _ | RBool _ ->
9831 pr " return INT2NUM (r);\n"
9833 pr " return ULL2NUM (r);\n"
9835 pr " return rb_str_new2 (r);\n";
9836 | RConstOptString _ ->
9838 pr " return rb_str_new2 (r);\n";
9840 pr " return Qnil;\n";
9842 pr " VALUE rv = rb_str_new2 (r);\n";
9846 pr " int i, len = 0;\n";
9847 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9848 pr " VALUE rv = rb_ary_new2 (len);\n";
9849 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9850 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9851 pr " free (r[i]);\n";
9855 | RStruct (_, typ) ->
9856 let cols = cols_of_struct typ in
9857 generate_ruby_struct_code typ cols
9858 | RStructList (_, typ) ->
9859 let cols = cols_of_struct typ in
9860 generate_ruby_struct_list_code typ cols
9862 pr " VALUE rv = rb_hash_new ();\n";
9864 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9865 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9866 pr " free (r[i]);\n";
9867 pr " free (r[i+1]);\n";
9872 pr " VALUE rv = rb_str_new (r, size);\n";
9882 /* Initialize the module. */
9883 void Init__guestfs ()
9885 m_guestfs = rb_define_module (\"Guestfs\");
9886 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9887 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9889 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9890 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9893 (* Define the rest of the methods. *)
9895 fun (name, style, _, _, _, _, _) ->
9896 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9897 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9902 (* Ruby code to return a struct. *)
9903 and generate_ruby_struct_code typ cols =
9904 pr " VALUE rv = rb_hash_new ();\n";
9908 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9910 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9912 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9913 | name, (FBytes|FUInt64) ->
9914 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9916 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9918 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9920 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9921 | name, FOptPercent ->
9922 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9923 | name, FChar -> (* XXX wrong? *)
9924 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9926 pr " guestfs_free_%s (r);\n" typ;
9929 (* Ruby code to return a struct list. *)
9930 and generate_ruby_struct_list_code typ cols =
9931 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9933 pr " for (i = 0; i < r->len; ++i) {\n";
9934 pr " VALUE hv = rb_hash_new ();\n";
9938 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9940 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
9942 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9943 | name, (FBytes|FUInt64) ->
9944 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9946 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9948 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9950 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9951 | name, FOptPercent ->
9952 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9953 | name, FChar -> (* XXX wrong? *)
9954 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9956 pr " rb_ary_push (rv, hv);\n";
9958 pr " guestfs_free_%s_list (r);\n" typ;
9961 (* Generate Java bindings GuestFS.java file. *)
9962 and generate_java_java () =
9963 generate_header CStyle LGPLv2plus;
9966 package com.redhat.et.libguestfs;
9968 import java.util.HashMap;
9969 import com.redhat.et.libguestfs.LibGuestFSException;
9970 import com.redhat.et.libguestfs.PV;
9971 import com.redhat.et.libguestfs.VG;
9972 import com.redhat.et.libguestfs.LV;
9973 import com.redhat.et.libguestfs.Stat;
9974 import com.redhat.et.libguestfs.StatVFS;
9975 import com.redhat.et.libguestfs.IntBool;
9976 import com.redhat.et.libguestfs.Dirent;
9979 * The GuestFS object is a libguestfs handle.
9983 public class GuestFS {
9984 // Load the native code.
9986 System.loadLibrary (\"guestfs_jni\");
9990 * The native guestfs_h pointer.
9995 * Create a libguestfs handle.
9997 * @throws LibGuestFSException
9999 public GuestFS () throws LibGuestFSException
10003 private native long _create () throws LibGuestFSException;
10006 * Close a libguestfs handle.
10008 * You can also leave handles to be collected by the garbage
10009 * collector, but this method ensures that the resources used
10010 * by the handle are freed up immediately. If you call any
10011 * other methods after closing the handle, you will get an
10014 * @throws LibGuestFSException
10016 public void close () throws LibGuestFSException
10022 private native void _close (long g) throws LibGuestFSException;
10024 public void finalize () throws LibGuestFSException
10032 fun (name, style, _, flags, _, shortdesc, longdesc) ->
10033 if not (List.mem NotInDocs flags); then (
10034 let doc = replace_str longdesc "C<guestfs_" "C<g." in
10036 if List.mem ProtocolLimitWarning flags then
10037 doc ^ "\n\n" ^ protocol_limit_warning
10040 if List.mem DangerWillRobinson flags then
10041 doc ^ "\n\n" ^ danger_will_robinson
10044 match deprecation_notice flags with
10046 | Some txt -> doc ^ "\n\n" ^ txt in
10047 let doc = pod2text ~width:60 name doc in
10048 let doc = List.map ( (* RHBZ#501883 *)
10051 | nonempty -> nonempty
10053 let doc = String.concat "\n * " doc in
10056 pr " * %s\n" shortdesc;
10059 pr " * @throws LibGuestFSException\n";
10063 generate_java_prototype ~public:true ~semicolon:false name style;
10066 pr " if (g == 0)\n";
10067 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
10070 if fst style <> RErr then pr "return ";
10072 generate_java_call_args ~handle:"g" (snd style);
10076 generate_java_prototype ~privat:true ~native:true name style;
10083 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10084 and generate_java_call_args ~handle args =
10086 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10089 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10090 ?(semicolon=true) name style =
10091 if privat then pr "private ";
10092 if public then pr "public ";
10093 if native then pr "native ";
10096 (match fst style with
10097 | RErr -> pr "void ";
10098 | RInt _ -> pr "int ";
10099 | RInt64 _ -> pr "long ";
10100 | RBool _ -> pr "boolean ";
10101 | RConstString _ | RConstOptString _ | RString _
10102 | RBufferOut _ -> pr "String ";
10103 | RStringList _ -> pr "String[] ";
10104 | RStruct (_, typ) ->
10105 let name = java_name_of_struct typ in
10107 | RStructList (_, typ) ->
10108 let name = java_name_of_struct typ in
10110 | RHashtable _ -> pr "HashMap<String,String> ";
10113 if native then pr "_%s " name else pr "%s " name;
10115 let needs_comma = ref false in
10118 needs_comma := true
10124 if !needs_comma then pr ", ";
10125 needs_comma := true;
10129 | Device n | Dev_or_Path n
10137 | StringList n | DeviceList n ->
10148 pr " throws LibGuestFSException";
10149 if semicolon then pr ";"
10151 and generate_java_struct jtyp cols () =
10152 generate_header CStyle LGPLv2plus;
10155 package com.redhat.et.libguestfs;
10158 * Libguestfs %s structure.
10170 | name, FBuffer -> pr " public String %s;\n" name
10171 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10172 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10173 | name, FChar -> pr " public char %s;\n" name
10174 | name, FOptPercent ->
10175 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10176 pr " public float %s;\n" name
10181 and generate_java_c () =
10182 generate_header CStyle LGPLv2plus;
10186 #include <stdlib.h>
10187 #include <string.h>
10189 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10190 #include \"guestfs.h\"
10192 /* Note that this function returns. The exception is not thrown
10193 * until after the wrapper function returns.
10196 throw_exception (JNIEnv *env, const char *msg)
10199 cl = (*env)->FindClass (env,
10200 \"com/redhat/et/libguestfs/LibGuestFSException\");
10201 (*env)->ThrowNew (env, cl, msg);
10204 JNIEXPORT jlong JNICALL
10205 Java_com_redhat_et_libguestfs_GuestFS__1create
10206 (JNIEnv *env, jobject obj)
10210 g = guestfs_create ();
10212 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10215 guestfs_set_error_handler (g, NULL, NULL);
10216 return (jlong) (long) g;
10219 JNIEXPORT void JNICALL
10220 Java_com_redhat_et_libguestfs_GuestFS__1close
10221 (JNIEnv *env, jobject obj, jlong jg)
10223 guestfs_h *g = (guestfs_h *) (long) jg;
10230 fun (name, style, _, _, _, _, _) ->
10232 (match fst style with
10233 | RErr -> pr "void ";
10234 | RInt _ -> pr "jint ";
10235 | RInt64 _ -> pr "jlong ";
10236 | RBool _ -> pr "jboolean ";
10237 | RConstString _ | RConstOptString _ | RString _
10238 | RBufferOut _ -> pr "jstring ";
10239 | RStruct _ | RHashtable _ ->
10241 | RStringList _ | RStructList _ ->
10242 pr "jobjectArray ";
10245 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10246 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10248 pr " (JNIEnv *env, jobject obj, jlong jg";
10252 | Device n | Dev_or_Path n
10257 pr ", jstring j%s" n
10259 pr ", jbyteArray j%s" n
10260 | StringList n | DeviceList n ->
10261 pr ", jobjectArray j%s" n
10263 pr ", jboolean j%s" n
10271 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10272 let error_code, no_ret =
10273 match fst style with
10274 | RErr -> pr " int r;\n"; "-1", ""
10276 | RInt _ -> pr " int r;\n"; "-1", "0"
10277 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10278 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10279 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10281 pr " jstring jr;\n";
10282 pr " char *r;\n"; "NULL", "NULL"
10284 pr " jobjectArray jr;\n";
10285 pr " int r_len;\n";
10286 pr " jclass cl;\n";
10287 pr " jstring jstr;\n";
10288 pr " char **r;\n"; "NULL", "NULL"
10289 | RStruct (_, typ) ->
10290 pr " jobject jr;\n";
10291 pr " jclass cl;\n";
10292 pr " jfieldID fl;\n";
10293 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10294 | RStructList (_, typ) ->
10295 pr " jobjectArray jr;\n";
10296 pr " jclass cl;\n";
10297 pr " jfieldID fl;\n";
10298 pr " jobject jfl;\n";
10299 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10300 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10302 pr " jstring jr;\n";
10304 pr " size_t size;\n";
10309 | Device n | Dev_or_Path n
10314 pr " const char *%s;\n" n
10316 pr " jbyte *%s;\n" n;
10317 pr " size_t %s_size;\n" n
10318 | StringList n | DeviceList n ->
10319 pr " int %s_len;\n" n;
10320 pr " const char **%s;\n" n
10325 pr " int64_t %s;\n" n
10329 (match fst style with
10330 | RStringList _ | RStructList _ -> true
10331 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10332 | RConstOptString _
10333 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10334 List.exists (function
10335 | StringList _ -> true
10336 | DeviceList _ -> true
10337 | _ -> false) (snd style) in
10343 (* Get the parameters. *)
10347 | Device n | Dev_or_Path n
10351 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10353 (* This is completely undocumented, but Java null becomes
10354 * a NULL parameter.
10356 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10358 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10359 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10360 | StringList n | DeviceList n ->
10361 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10362 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10363 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10364 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10366 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10368 pr " %s[%s_len] = NULL;\n" n n;
10372 pr " %s = j%s;\n" n n
10375 (* Make the call. *)
10376 pr " r = guestfs_%s " name;
10377 generate_c_call_args ~handle:"g" style;
10380 (* Release the parameters. *)
10384 | Device n | Dev_or_Path n
10388 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10390 pr " if (j%s)\n" n;
10391 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10393 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10394 | StringList n | DeviceList n ->
10395 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10396 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10398 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10400 pr " free (%s);\n" n
10406 (* Check for errors. *)
10407 pr " if (r == %s) {\n" error_code;
10408 pr " throw_exception (env, guestfs_last_error (g));\n";
10409 pr " return %s;\n" no_ret;
10412 (* Return value. *)
10413 (match fst style with
10415 | RInt _ -> pr " return (jint) r;\n"
10416 | RBool _ -> pr " return (jboolean) r;\n"
10417 | RInt64 _ -> pr " return (jlong) r;\n"
10418 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10419 | RConstOptString _ ->
10420 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10422 pr " jr = (*env)->NewStringUTF (env, r);\n";
10426 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10427 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10428 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10429 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10430 pr " for (i = 0; i < r_len; ++i) {\n";
10431 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10432 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10433 pr " free (r[i]);\n";
10437 | RStruct (_, typ) ->
10438 let jtyp = java_name_of_struct typ in
10439 let cols = cols_of_struct typ in
10440 generate_java_struct_return typ jtyp cols
10441 | RStructList (_, typ) ->
10442 let jtyp = java_name_of_struct typ in
10443 let cols = cols_of_struct typ in
10444 generate_java_struct_list_return typ jtyp cols
10447 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10448 pr " return NULL;\n"
10450 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10459 and generate_java_struct_return typ jtyp cols =
10460 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10461 pr " jr = (*env)->AllocObject (env, cl);\n";
10465 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10466 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10469 pr " char s[33];\n";
10470 pr " memcpy (s, r->%s, 32);\n" name;
10471 pr " s[32] = 0;\n";
10472 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10473 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10477 pr " int len = r->%s_len;\n" name;
10478 pr " char s[len+1];\n";
10479 pr " memcpy (s, r->%s, len);\n" name;
10480 pr " s[len] = 0;\n";
10481 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10482 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10484 | name, (FBytes|FUInt64|FInt64) ->
10485 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10486 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10487 | name, (FUInt32|FInt32) ->
10488 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10489 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10490 | name, FOptPercent ->
10491 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10492 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10494 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10495 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10500 and generate_java_struct_list_return typ jtyp cols =
10501 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10502 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10503 pr " for (i = 0; i < r->len; ++i) {\n";
10504 pr " jfl = (*env)->AllocObject (env, cl);\n";
10508 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10509 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10512 pr " char s[33];\n";
10513 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10514 pr " s[32] = 0;\n";
10515 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10516 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10520 pr " int len = r->val[i].%s_len;\n" name;
10521 pr " char s[len+1];\n";
10522 pr " memcpy (s, r->val[i].%s, len);\n" name;
10523 pr " s[len] = 0;\n";
10524 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10525 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10527 | name, (FBytes|FUInt64|FInt64) ->
10528 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10529 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10530 | name, (FUInt32|FInt32) ->
10531 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10532 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10533 | name, FOptPercent ->
10534 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10535 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10537 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10538 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10540 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10542 pr " guestfs_free_%s_list (r);\n" typ;
10545 and generate_java_makefile_inc () =
10546 generate_header HashStyle GPLv2plus;
10548 pr "java_built_sources = \\\n";
10551 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10553 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10555 and generate_haskell_hs () =
10556 generate_header HaskellStyle LGPLv2plus;
10558 (* XXX We only know how to generate partial FFI for Haskell
10559 * at the moment. Please help out!
10561 let can_generate style =
10565 | RInt64 _, _ -> true
10567 | RConstString _, _
10568 | RConstOptString _, _
10574 | RBufferOut _, _ -> false in
10577 {-# INCLUDE <guestfs.h> #-}
10578 {-# LANGUAGE ForeignFunctionInterface #-}
10583 (* List out the names of the actions we want to export. *)
10585 fun (name, style, _, _, _, _, _) ->
10586 if can_generate style then pr ",\n %s" name
10592 -- Unfortunately some symbols duplicate ones already present
10593 -- in Prelude. We don't know which, so we hard-code a list
10595 import Prelude hiding (truncate)
10599 import Foreign.C.Types
10601 import Control.Exception
10602 import Data.Typeable
10604 data GuestfsS = GuestfsS -- represents the opaque C struct
10605 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10606 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10608 -- XXX define properly later XXX
10612 data IntBool = IntBool
10614 data StatVFS = StatVFS
10615 data Hashtable = Hashtable
10617 foreign import ccall unsafe \"guestfs_create\" c_create
10619 foreign import ccall unsafe \"&guestfs_close\" c_close
10620 :: FunPtr (GuestfsP -> IO ())
10621 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10622 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10624 create :: IO GuestfsH
10627 c_set_error_handler p nullPtr nullPtr
10628 h <- newForeignPtr c_close p
10631 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10632 :: GuestfsP -> IO CString
10634 -- last_error :: GuestfsH -> IO (Maybe String)
10635 -- last_error h = do
10636 -- str <- withForeignPtr h (\\p -> c_last_error p)
10637 -- maybePeek peekCString str
10639 last_error :: GuestfsH -> IO (String)
10641 str <- withForeignPtr h (\\p -> c_last_error p)
10642 if (str == nullPtr)
10643 then return \"no error\"
10644 else peekCString str
10648 (* Generate wrappers for each foreign function. *)
10650 fun (name, style, _, _, _, _, _) ->
10651 if can_generate style then (
10652 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10654 generate_haskell_prototype ~handle:"GuestfsP" style;
10658 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10660 pr "%s %s = do\n" name
10661 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10663 (* Convert pointer arguments using with* functions. *)
10668 | Pathname n | Device n | Dev_or_Path n | String n ->
10669 pr "withCString %s $ \\%s -> " n n
10671 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10672 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10673 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10674 | Bool _ | Int _ | Int64 _ -> ()
10676 (* Convert integer arguments. *)
10680 | Bool n -> sprintf "(fromBool %s)" n
10681 | Int n -> sprintf "(fromIntegral %s)" n
10682 | Int64 n -> sprintf "(fromIntegral %s)" n
10683 | FileIn n | FileOut n
10684 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10685 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10687 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10688 (String.concat " " ("p" :: args));
10689 (match fst style with
10690 | RErr | RInt _ | RInt64 _ | RBool _ ->
10691 pr " if (r == -1)\n";
10693 pr " err <- last_error h\n";
10695 | RConstString _ | RConstOptString _ | RString _
10696 | RStringList _ | RStruct _
10697 | RStructList _ | RHashtable _ | RBufferOut _ ->
10698 pr " if (r == nullPtr)\n";
10700 pr " err <- last_error h\n";
10703 (match fst style with
10705 pr " else return ()\n"
10707 pr " else return (fromIntegral r)\n"
10709 pr " else return (fromIntegral r)\n"
10711 pr " else return (toBool r)\n"
10713 | RConstOptString _
10720 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10726 and generate_haskell_prototype ~handle ?(hs = false) style =
10727 pr "%s -> " handle;
10728 let string = if hs then "String" else "CString" in
10729 let int = if hs then "Int" else "CInt" in
10730 let bool = if hs then "Bool" else "CInt" in
10731 let int64 = if hs then "Integer" else "Int64" in
10735 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10737 if hs then pr "String"
10738 else pr "CString -> CInt"
10739 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10740 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10741 | Bool _ -> pr "%s" bool
10742 | Int _ -> pr "%s" int
10743 | Int64 _ -> pr "%s" int
10744 | FileIn _ -> pr "%s" string
10745 | FileOut _ -> pr "%s" string
10750 (match fst style with
10751 | RErr -> if not hs then pr "CInt"
10752 | RInt _ -> pr "%s" int
10753 | RInt64 _ -> pr "%s" int64
10754 | RBool _ -> pr "%s" bool
10755 | RConstString _ -> pr "%s" string
10756 | RConstOptString _ -> pr "Maybe %s" string
10757 | RString _ -> pr "%s" string
10758 | RStringList _ -> pr "[%s]" string
10759 | RStruct (_, typ) ->
10760 let name = java_name_of_struct typ in
10762 | RStructList (_, typ) ->
10763 let name = java_name_of_struct typ in
10765 | RHashtable _ -> pr "Hashtable"
10766 | RBufferOut _ -> pr "%s" string
10770 and generate_csharp () =
10771 generate_header CPlusPlusStyle LGPLv2plus;
10773 (* XXX Make this configurable by the C# assembly users. *)
10774 let library = "libguestfs.so.0" in
10777 // These C# bindings are highly experimental at present.
10779 // Firstly they only work on Linux (ie. Mono). In order to get them
10780 // to work on Windows (ie. .Net) you would need to port the library
10781 // itself to Windows first.
10783 // The second issue is that some calls are known to be incorrect and
10784 // can cause Mono to segfault. Particularly: calls which pass or
10785 // return string[], or return any structure value. This is because
10786 // we haven't worked out the correct way to do this from C#.
10788 // The third issue is that when compiling you get a lot of warnings.
10789 // We are not sure whether the warnings are important or not.
10791 // Fourthly we do not routinely build or test these bindings as part
10792 // of the make && make check cycle, which means that regressions might
10795 // Suggestions and patches are welcome.
10799 // gmcs Libguestfs.cs
10800 // mono Libguestfs.exe
10802 // (You'll probably want to add a Test class / static main function
10803 // otherwise this won't do anything useful).
10807 using System.Runtime.InteropServices;
10808 using System.Runtime.Serialization;
10809 using System.Collections;
10813 class Error : System.ApplicationException
10815 public Error (string message) : base (message) {}
10816 protected Error (SerializationInfo info, StreamingContext context) {}
10823 [DllImport (\"%s\")]
10824 static extern IntPtr guestfs_create ();
10828 _handle = guestfs_create ();
10829 if (_handle == IntPtr.Zero)
10830 throw new Error (\"could not create guestfs handle\");
10833 [DllImport (\"%s\")]
10834 static extern void guestfs_close (IntPtr h);
10838 guestfs_close (_handle);
10841 [DllImport (\"%s\")]
10842 static extern string guestfs_last_error (IntPtr h);
10844 " library library library;
10846 (* Generate C# structure bindings. We prefix struct names with
10847 * underscore because C# cannot have conflicting struct names and
10848 * method names (eg. "class stat" and "stat").
10852 pr " [StructLayout (LayoutKind.Sequential)]\n";
10853 pr " public class _%s {\n" typ;
10856 | name, FChar -> pr " char %s;\n" name
10857 | name, FString -> pr " string %s;\n" name
10859 pr " uint %s_len;\n" name;
10860 pr " string %s;\n" name
10862 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10863 pr " string %s;\n" name
10864 | name, FUInt32 -> pr " uint %s;\n" name
10865 | name, FInt32 -> pr " int %s;\n" name
10866 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10867 | name, FInt64 -> pr " long %s;\n" name
10868 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10874 (* Generate C# function bindings. *)
10876 fun (name, style, _, _, _, shortdesc, _) ->
10877 let rec csharp_return_type () =
10878 match fst style with
10880 | RBool n -> "bool"
10882 | RInt64 n -> "long"
10884 | RConstOptString n
10886 | RBufferOut n -> "string"
10887 | RStruct (_,n) -> "_" ^ n
10888 | RHashtable n -> "Hashtable"
10889 | RStringList n -> "string[]"
10890 | RStructList (_,n) -> sprintf "_%s[]" n
10892 and c_return_type () =
10893 match fst style with
10897 | RInt64 _ -> "long"
10899 | RConstOptString _
10901 | RBufferOut _ -> "string"
10902 | RStruct (_,n) -> "_" ^ n
10904 | RStringList _ -> "string[]"
10905 | RStructList (_,n) -> sprintf "_%s[]" n
10907 and c_error_comparison () =
10908 match fst style with
10912 | RInt64 _ -> "== -1"
10914 | RConstOptString _
10920 | RStructList (_,_) -> "== null"
10922 and generate_extern_prototype () =
10923 pr " static extern %s guestfs_%s (IntPtr h"
10924 (c_return_type ()) name;
10927 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10928 | FileIn n | FileOut n
10930 pr ", [In] string %s" n
10931 | StringList n | DeviceList n ->
10932 pr ", [In] string[] %s" n
10942 and generate_public_prototype () =
10943 pr " public %s %s (" (csharp_return_type ()) name;
10944 let comma = ref false in
10946 if !comma then pr ", ";
10951 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10952 | FileIn n | FileOut n
10954 next (); pr "string %s" n
10955 | StringList n | DeviceList n ->
10956 next (); pr "string[] %s" n
10958 next (); pr "bool %s" n
10960 next (); pr "int %s" n
10962 next (); pr "long %s" n
10966 and generate_call () =
10967 pr "guestfs_%s (_handle" name;
10968 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10972 pr " [DllImport (\"%s\")]\n" library;
10973 generate_extern_prototype ();
10975 pr " /// <summary>\n";
10976 pr " /// %s\n" shortdesc;
10977 pr " /// </summary>\n";
10978 generate_public_prototype ();
10980 pr " %s r;\n" (c_return_type ());
10983 pr " if (r %s)\n" (c_error_comparison ());
10984 pr " throw new Error (guestfs_last_error (_handle));\n";
10985 (match fst style with
10988 pr " return r != 0 ? true : false;\n"
10990 pr " Hashtable rr = new Hashtable ();\n";
10991 pr " for (int i = 0; i < r.Length; i += 2)\n";
10992 pr " rr.Add (r[i], r[i+1]);\n";
10994 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10995 | RString _ | RBufferOut _ | RStruct _ | RStringList _
11001 ) all_functions_sorted;
11007 and generate_bindtests () =
11008 generate_header CStyle LGPLv2plus;
11012 #include <stdlib.h>
11013 #include <inttypes.h>
11014 #include <string.h>
11016 #include \"guestfs.h\"
11017 #include \"guestfs-internal.h\"
11018 #include \"guestfs-internal-actions.h\"
11019 #include \"guestfs_protocol.h\"
11021 #define error guestfs_error
11022 #define safe_calloc guestfs_safe_calloc
11023 #define safe_malloc guestfs_safe_malloc
11026 print_strings (char *const *argv)
11031 for (argc = 0; argv[argc] != NULL; ++argc) {
11032 if (argc > 0) printf (\", \");
11033 printf (\"\\\"%%s\\\"\", argv[argc]);
11038 /* The test0 function prints its parameters to stdout. */
11042 match test_functions with
11043 | [] -> assert false
11044 | test0 :: tests -> test0, tests in
11047 let (name, style, _, _, _, _, _) = test0 in
11048 generate_prototype ~extern:false ~semicolon:false ~newline:true
11049 ~handle:"g" ~prefix:"guestfs__" name style;
11054 | Device n | Dev_or_Path n
11057 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
11061 pr " for (i = 0; i < %s_size; ++i)\n" n;
11062 pr " printf (\"<%%02x>\", %s[i]);\n" n;
11063 pr " printf (\"\\n\");\n";
11065 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11066 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
11067 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11068 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
11069 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11071 pr " /* Java changes stdout line buffering so we need this: */\n";
11072 pr " fflush (stdout);\n";
11078 fun (name, style, _, _, _, _, _) ->
11079 if String.sub name (String.length name - 3) 3 <> "err" then (
11080 pr "/* Test normal return. */\n";
11081 generate_prototype ~extern:false ~semicolon:false ~newline:true
11082 ~handle:"g" ~prefix:"guestfs__" name style;
11084 (match fst style with
11089 pr " sscanf (val, \"%%d\", &r);\n";
11092 pr " int64_t r;\n";
11093 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
11096 pr " return STREQ (val, \"true\");\n"
11098 | RConstOptString _ ->
11099 (* Can't return the input string here. Return a static
11100 * string so we ensure we get a segfault if the caller
11101 * tries to free it.
11103 pr " return \"static string\";\n"
11105 pr " return strdup (val);\n"
11107 pr " char **strs;\n";
11109 pr " sscanf (val, \"%%d\", &n);\n";
11110 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11111 pr " for (i = 0; i < n; ++i) {\n";
11112 pr " strs[i] = safe_malloc (g, 16);\n";
11113 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
11115 pr " strs[n] = NULL;\n";
11116 pr " return strs;\n"
11117 | RStruct (_, typ) ->
11118 pr " struct guestfs_%s *r;\n" typ;
11119 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11121 | RStructList (_, typ) ->
11122 pr " struct guestfs_%s_list *r;\n" typ;
11123 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11124 pr " sscanf (val, \"%%d\", &r->len);\n";
11125 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11128 pr " char **strs;\n";
11130 pr " sscanf (val, \"%%d\", &n);\n";
11131 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11132 pr " for (i = 0; i < n; ++i) {\n";
11133 pr " strs[i*2] = safe_malloc (g, 16);\n";
11134 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11135 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11136 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11138 pr " strs[n*2] = NULL;\n";
11139 pr " return strs;\n"
11141 pr " return strdup (val);\n"
11146 pr "/* Test error return. */\n";
11147 generate_prototype ~extern:false ~semicolon:false ~newline:true
11148 ~handle:"g" ~prefix:"guestfs__" name style;
11150 pr " error (g, \"error\");\n";
11151 (match fst style with
11152 | RErr | RInt _ | RInt64 _ | RBool _ ->
11154 | RConstString _ | RConstOptString _
11155 | RString _ | RStringList _ | RStruct _
11159 pr " return NULL;\n"
11166 and generate_ocaml_bindtests () =
11167 generate_header OCamlStyle GPLv2plus;
11171 let g = Guestfs.create () in
11175 String.concat " " (
11178 | CallString s -> "\"" ^ s ^ "\""
11179 | CallOptString None -> "None"
11180 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11181 | CallStringList xs ->
11182 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11183 | CallInt i when i >= 0 -> string_of_int i
11184 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11185 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11186 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11187 | CallBool b -> string_of_bool b
11188 | CallBuffer s -> sprintf "%S" s
11193 generate_lang_bindtests (
11194 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11197 pr "print_endline \"EOF\"\n"
11199 and generate_perl_bindtests () =
11200 pr "#!/usr/bin/perl -w\n";
11201 generate_header HashStyle GPLv2plus;
11208 my $g = Sys::Guestfs->new ();
11212 String.concat ", " (
11215 | CallString s -> "\"" ^ s ^ "\""
11216 | CallOptString None -> "undef"
11217 | CallOptString (Some s) -> sprintf "\"%s\"" s
11218 | CallStringList xs ->
11219 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11220 | CallInt i -> string_of_int i
11221 | CallInt64 i -> Int64.to_string i
11222 | CallBool b -> if b then "1" else "0"
11223 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11228 generate_lang_bindtests (
11229 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11232 pr "print \"EOF\\n\"\n"
11234 and generate_python_bindtests () =
11235 generate_header HashStyle GPLv2plus;
11240 g = guestfs.GuestFS ()
11244 String.concat ", " (
11247 | CallString s -> "\"" ^ s ^ "\""
11248 | CallOptString None -> "None"
11249 | CallOptString (Some s) -> sprintf "\"%s\"" s
11250 | CallStringList xs ->
11251 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11252 | CallInt i -> string_of_int i
11253 | CallInt64 i -> Int64.to_string i
11254 | CallBool b -> if b then "1" else "0"
11255 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11260 generate_lang_bindtests (
11261 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11264 pr "print \"EOF\"\n"
11266 and generate_ruby_bindtests () =
11267 generate_header HashStyle GPLv2plus;
11272 g = Guestfs::create()
11276 String.concat ", " (
11279 | CallString s -> "\"" ^ s ^ "\""
11280 | CallOptString None -> "nil"
11281 | CallOptString (Some s) -> sprintf "\"%s\"" s
11282 | CallStringList xs ->
11283 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11284 | CallInt i -> string_of_int i
11285 | CallInt64 i -> Int64.to_string i
11286 | CallBool b -> string_of_bool b
11287 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11292 generate_lang_bindtests (
11293 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11296 pr "print \"EOF\\n\"\n"
11298 and generate_java_bindtests () =
11299 generate_header CStyle GPLv2plus;
11302 import com.redhat.et.libguestfs.*;
11304 public class Bindtests {
11305 public static void main (String[] argv)
11308 GuestFS g = new GuestFS ();
11312 String.concat ", " (
11315 | CallString s -> "\"" ^ s ^ "\""
11316 | CallOptString None -> "null"
11317 | CallOptString (Some s) -> sprintf "\"%s\"" s
11318 | CallStringList xs ->
11320 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11321 | CallInt i -> string_of_int i
11322 | CallInt64 i -> Int64.to_string i
11323 | CallBool b -> string_of_bool b
11325 "new byte[] { " ^ String.concat "," (
11326 map_chars (fun c -> string_of_int (Char.code c)) s
11332 generate_lang_bindtests (
11333 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11337 System.out.println (\"EOF\");
11339 catch (Exception exn) {
11340 System.err.println (exn);
11347 and generate_haskell_bindtests () =
11348 generate_header HaskellStyle GPLv2plus;
11351 module Bindtests where
11352 import qualified Guestfs
11355 g <- Guestfs.create
11359 String.concat " " (
11362 | CallString s -> "\"" ^ s ^ "\""
11363 | CallOptString None -> "Nothing"
11364 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11365 | CallStringList xs ->
11366 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11367 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11368 | CallInt i -> string_of_int i
11369 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11370 | CallInt64 i -> Int64.to_string i
11371 | CallBool true -> "True"
11372 | CallBool false -> "False"
11373 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11378 generate_lang_bindtests (
11379 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11382 pr " putStrLn \"EOF\"\n"
11384 (* Language-independent bindings tests - we do it this way to
11385 * ensure there is parity in testing bindings across all languages.
11387 and generate_lang_bindtests call =
11388 call "test0" [CallString "abc"; CallOptString (Some "def");
11389 CallStringList []; CallBool false;
11390 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11391 CallBuffer "abc\000abc"];
11392 call "test0" [CallString "abc"; CallOptString None;
11393 CallStringList []; CallBool false;
11394 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11395 CallBuffer "abc\000abc"];
11396 call "test0" [CallString ""; CallOptString (Some "def");
11397 CallStringList []; CallBool false;
11398 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11399 CallBuffer "abc\000abc"];
11400 call "test0" [CallString ""; CallOptString (Some "");
11401 CallStringList []; CallBool false;
11402 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11403 CallBuffer "abc\000abc"];
11404 call "test0" [CallString "abc"; CallOptString (Some "def");
11405 CallStringList ["1"]; CallBool false;
11406 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11407 CallBuffer "abc\000abc"];
11408 call "test0" [CallString "abc"; CallOptString (Some "def");
11409 CallStringList ["1"; "2"]; CallBool false;
11410 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11411 CallBuffer "abc\000abc"];
11412 call "test0" [CallString "abc"; CallOptString (Some "def");
11413 CallStringList ["1"]; CallBool true;
11414 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11415 CallBuffer "abc\000abc"];
11416 call "test0" [CallString "abc"; CallOptString (Some "def");
11417 CallStringList ["1"]; CallBool false;
11418 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11419 CallBuffer "abc\000abc"];
11420 call "test0" [CallString "abc"; CallOptString (Some "def");
11421 CallStringList ["1"]; CallBool false;
11422 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11423 CallBuffer "abc\000abc"];
11424 call "test0" [CallString "abc"; CallOptString (Some "def");
11425 CallStringList ["1"]; CallBool false;
11426 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11427 CallBuffer "abc\000abc"];
11428 call "test0" [CallString "abc"; CallOptString (Some "def");
11429 CallStringList ["1"]; CallBool false;
11430 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11431 CallBuffer "abc\000abc"];
11432 call "test0" [CallString "abc"; CallOptString (Some "def");
11433 CallStringList ["1"]; CallBool false;
11434 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11435 CallBuffer "abc\000abc"];
11436 call "test0" [CallString "abc"; CallOptString (Some "def");
11437 CallStringList ["1"]; CallBool false;
11438 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11439 CallBuffer "abc\000abc"]
11441 (* XXX Add here tests of the return and error functions. *)
11443 (* Code to generator bindings for virt-inspector. Currently only
11444 * implemented for OCaml code (for virt-p2v 2.0).
11446 let rng_input = "inspector/virt-inspector.rng"
11448 (* Read the input file and parse it into internal structures. This is
11449 * by no means a complete RELAX NG parser, but is just enough to be
11450 * able to parse the specific input file.
11453 | Element of string * rng list (* <element name=name/> *)
11454 | Attribute of string * rng list (* <attribute name=name/> *)
11455 | Interleave of rng list (* <interleave/> *)
11456 | ZeroOrMore of rng (* <zeroOrMore/> *)
11457 | OneOrMore of rng (* <oneOrMore/> *)
11458 | Optional of rng (* <optional/> *)
11459 | Choice of string list (* <choice><value/>*</choice> *)
11460 | Value of string (* <value>str</value> *)
11461 | Text (* <text/> *)
11463 let rec string_of_rng = function
11464 | Element (name, xs) ->
11465 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11466 | Attribute (name, xs) ->
11467 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11468 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11469 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11470 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11471 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11472 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11473 | Value value -> "Value \"" ^ value ^ "\""
11476 and string_of_rng_list xs =
11477 String.concat ", " (List.map string_of_rng xs)
11479 let rec parse_rng ?defines context = function
11481 | Xml.Element ("element", ["name", name], children) :: rest ->
11482 Element (name, parse_rng ?defines context children)
11483 :: parse_rng ?defines context rest
11484 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11485 Attribute (name, parse_rng ?defines context children)
11486 :: parse_rng ?defines context rest
11487 | Xml.Element ("interleave", [], children) :: rest ->
11488 Interleave (parse_rng ?defines context children)
11489 :: parse_rng ?defines context rest
11490 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11491 let rng = parse_rng ?defines context [child] in
11493 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11495 failwithf "%s: <zeroOrMore> contains more than one child element"
11498 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11499 let rng = parse_rng ?defines context [child] in
11501 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11503 failwithf "%s: <oneOrMore> contains more than one child element"
11506 | Xml.Element ("optional", [], [child]) :: rest ->
11507 let rng = parse_rng ?defines context [child] in
11509 | [child] -> Optional child :: parse_rng ?defines context rest
11511 failwithf "%s: <optional> contains more than one child element"
11514 | Xml.Element ("choice", [], children) :: rest ->
11515 let values = List.map (
11516 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11518 failwithf "%s: can't handle anything except <value> in <choice>"
11522 :: parse_rng ?defines context rest
11523 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11524 Value value :: parse_rng ?defines context rest
11525 | Xml.Element ("text", [], []) :: rest ->
11526 Text :: parse_rng ?defines context rest
11527 | Xml.Element ("ref", ["name", name], []) :: rest ->
11528 (* Look up the reference. Because of limitations in this parser,
11529 * we can't handle arbitrarily nested <ref> yet. You can only
11530 * use <ref> from inside <start>.
11532 (match defines with
11534 failwithf "%s: contains <ref>, but no refs are defined yet" context
11536 let rng = StringMap.find name map in
11537 rng @ parse_rng ?defines context rest
11540 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11543 let xml = Xml.parse_file rng_input in
11545 | Xml.Element ("grammar", _,
11546 Xml.Element ("start", _, gram) :: defines) ->
11547 (* The <define/> elements are referenced in the <start> section,
11548 * so build a map of those first.
11550 let defines = List.fold_left (
11552 function Xml.Element ("define", ["name", name], defn) ->
11553 StringMap.add name defn map
11555 failwithf "%s: expected <define name=name/>" rng_input
11556 ) StringMap.empty defines in
11557 let defines = StringMap.mapi parse_rng defines in
11559 (* Parse the <start> clause, passing the defines. *)
11560 parse_rng ~defines "<start>" gram
11562 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11565 let name_of_field = function
11566 | Element (name, _) | Attribute (name, _)
11567 | ZeroOrMore (Element (name, _))
11568 | OneOrMore (Element (name, _))
11569 | Optional (Element (name, _)) -> name
11570 | Optional (Attribute (name, _)) -> name
11571 | Text -> (* an unnamed field in an element *)
11574 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11576 (* At the moment this function only generates OCaml types. However we
11577 * should parameterize it later so it can generate types/structs in a
11578 * variety of languages.
11580 let generate_types xs =
11581 (* A simple type is one that can be printed out directly, eg.
11582 * "string option". A complex type is one which has a name and has
11583 * to be defined via another toplevel definition, eg. a struct.
11585 * generate_type generates code for either simple or complex types.
11586 * In the simple case, it returns the string ("string option"). In
11587 * the complex case, it returns the name ("mountpoint"). In the
11588 * complex case it has to print out the definition before returning,
11589 * so it should only be called when we are at the beginning of a
11590 * new line (BOL context).
11592 let rec generate_type = function
11593 | Text -> (* string *)
11595 | Choice values -> (* [`val1|`val2|...] *)
11596 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11597 | ZeroOrMore rng -> (* <rng> list *)
11598 let t, is_simple = generate_type rng in
11599 t ^ " list (* 0 or more *)", is_simple
11600 | OneOrMore rng -> (* <rng> list *)
11601 let t, is_simple = generate_type rng in
11602 t ^ " list (* 1 or more *)", is_simple
11603 (* virt-inspector hack: bool *)
11604 | Optional (Attribute (name, [Value "1"])) ->
11606 | Optional rng -> (* <rng> list *)
11607 let t, is_simple = generate_type rng in
11608 t ^ " option", is_simple
11609 (* type name = { fields ... } *)
11610 | Element (name, fields) when is_attrs_interleave fields ->
11611 generate_type_struct name (get_attrs_interleave fields)
11612 | Element (name, [field]) (* type name = field *)
11613 | Attribute (name, [field]) ->
11614 let t, is_simple = generate_type field in
11615 if is_simple then (t, true)
11617 pr "type %s = %s\n" name t;
11620 | Element (name, fields) -> (* type name = { fields ... } *)
11621 generate_type_struct name fields
11623 failwithf "generate_type failed at: %s" (string_of_rng rng)
11625 and is_attrs_interleave = function
11626 | [Interleave _] -> true
11627 | Attribute _ :: fields -> is_attrs_interleave fields
11628 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11631 and get_attrs_interleave = function
11632 | [Interleave fields] -> fields
11633 | ((Attribute _) as field) :: fields
11634 | ((Optional (Attribute _)) as field) :: fields ->
11635 field :: get_attrs_interleave fields
11636 | _ -> assert false
11638 and generate_types xs =
11639 List.iter (fun x -> ignore (generate_type x)) xs
11641 and generate_type_struct name fields =
11642 (* Calculate the types of the fields first. We have to do this
11643 * before printing anything so we are still in BOL context.
11645 let types = List.map fst (List.map generate_type fields) in
11647 (* Special case of a struct containing just a string and another
11648 * field. Turn it into an assoc list.
11651 | ["string"; other] ->
11652 let fname1, fname2 =
11654 | [f1; f2] -> name_of_field f1, name_of_field f2
11655 | _ -> assert false in
11656 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11660 pr "type %s = {\n" name;
11662 fun (field, ftype) ->
11663 let fname = name_of_field field in
11664 pr " %s_%s : %s;\n" name fname ftype
11665 ) (List.combine fields types);
11667 (* Return the name of this type, and
11668 * false because it's not a simple type.
11675 let generate_parsers xs =
11676 (* As for generate_type above, generate_parser makes a parser for
11677 * some type, and returns the name of the parser it has generated.
11678 * Because it (may) need to print something, it should always be
11679 * called in BOL context.
11681 let rec generate_parser = function
11682 | Text -> (* string *)
11683 "string_child_or_empty"
11684 | Choice values -> (* [`val1|`val2|...] *)
11685 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11687 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11688 | ZeroOrMore rng -> (* <rng> list *)
11689 let pa = generate_parser rng in
11690 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11691 | OneOrMore rng -> (* <rng> list *)
11692 let pa = generate_parser rng in
11693 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11694 (* virt-inspector hack: bool *)
11695 | Optional (Attribute (name, [Value "1"])) ->
11696 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11697 | Optional rng -> (* <rng> list *)
11698 let pa = generate_parser rng in
11699 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11700 (* type name = { fields ... } *)
11701 | Element (name, fields) when is_attrs_interleave fields ->
11702 generate_parser_struct name (get_attrs_interleave fields)
11703 | Element (name, [field]) -> (* type name = field *)
11704 let pa = generate_parser field in
11705 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11706 pr "let %s =\n" parser_name;
11708 pr "let parse_%s = %s\n" name parser_name;
11710 | Attribute (name, [field]) ->
11711 let pa = generate_parser field in
11712 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11713 pr "let %s =\n" parser_name;
11715 pr "let parse_%s = %s\n" name parser_name;
11717 | Element (name, fields) -> (* type name = { fields ... } *)
11718 generate_parser_struct name ([], fields)
11720 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11722 and is_attrs_interleave = function
11723 | [Interleave _] -> true
11724 | Attribute _ :: fields -> is_attrs_interleave fields
11725 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11728 and get_attrs_interleave = function
11729 | [Interleave fields] -> [], fields
11730 | ((Attribute _) as field) :: fields
11731 | ((Optional (Attribute _)) as field) :: fields ->
11732 let attrs, interleaves = get_attrs_interleave fields in
11733 (field :: attrs), interleaves
11734 | _ -> assert false
11736 and generate_parsers xs =
11737 List.iter (fun x -> ignore (generate_parser x)) xs
11739 and generate_parser_struct name (attrs, interleaves) =
11740 (* Generate parsers for the fields first. We have to do this
11741 * before printing anything so we are still in BOL context.
11743 let fields = attrs @ interleaves in
11744 let pas = List.map generate_parser fields in
11746 (* Generate an intermediate tuple from all the fields first.
11747 * If the type is just a string + another field, then we will
11748 * return this directly, otherwise it is turned into a record.
11750 * RELAX NG note: This code treats <interleave> and plain lists of
11751 * fields the same. In other words, it doesn't bother enforcing
11752 * any ordering of fields in the XML.
11754 pr "let parse_%s x =\n" name;
11755 pr " let t = (\n ";
11756 let comma = ref false in
11759 if !comma then pr ",\n ";
11762 | Optional (Attribute (fname, [field])), pa ->
11764 | Optional (Element (fname, [field])), pa ->
11765 pr "%s (optional_child %S x)" pa fname
11766 | Attribute (fname, [Text]), _ ->
11767 pr "attribute %S x" fname
11768 | (ZeroOrMore _ | OneOrMore _), pa ->
11773 let fname = name_of_field field in
11774 pr "%s (child %S x)" pa fname
11775 ) (List.combine fields pas);
11779 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11783 pr " (Obj.magic t : %s)\n" name
11787 | (Optional (Attribute (fname, [field])), pa) ->
11788 pr " %s_%s =\n" name fname;
11790 | (Optional (Element (fname, [field])), pa) ->
11791 pr " %s_%s =\n" name fname;
11792 pr " (let x = optional_child %S x in\n" fname;
11795 let fname = name_of_field field in
11796 pr " %s_%s =\n" name fname;
11797 pr " (let x = child %S x in\n" fname;
11799 ) (List.combine fields pas);
11803 sprintf "parse_%s" name
11806 generate_parsers xs
11808 (* Generate ocaml/guestfs_inspector.mli. *)
11809 let generate_ocaml_inspector_mli () =
11810 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11813 (** This is an OCaml language binding to the external [virt-inspector]
11816 For more information, please read the man page [virt-inspector(1)].
11821 generate_types grammar;
11822 pr "(** The nested information returned from the {!inspect} function. *)\n";
11826 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11827 (** To inspect a libvirt domain called [name], pass a singleton
11828 list: [inspect [name]]. When using libvirt only, you may
11829 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11831 To inspect a disk image or images, pass a list of the filenames
11832 of the disk images: [inspect filenames]
11834 This function inspects the given guest or disk images and
11835 returns a list of operating system(s) found and a large amount
11836 of information about them. In the vast majority of cases,
11837 a virtual machine only contains a single operating system.
11839 If the optional [~xml] parameter is given, then this function
11840 skips running the external virt-inspector program and just
11841 parses the given XML directly (which is expected to be XML
11842 produced from a previous run of virt-inspector). The list of
11843 names and connect URI are ignored in this case.
11845 This function can throw a wide variety of exceptions, for example
11846 if the external virt-inspector program cannot be found, or if
11847 it doesn't generate valid XML.
11851 (* Generate ocaml/guestfs_inspector.ml. *)
11852 let generate_ocaml_inspector_ml () =
11853 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11858 generate_types grammar;
11862 (* Misc functions which are used by the parser code below. *)
11863 let first_child = function
11864 | Xml.Element (_, _, c::_) -> c
11865 | Xml.Element (name, _, []) ->
11866 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11867 | Xml.PCData str ->
11868 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11870 let string_child_or_empty = function
11871 | Xml.Element (_, _, [Xml.PCData s]) -> s
11872 | Xml.Element (_, _, []) -> \"\"
11873 | Xml.Element (x, _, _) ->
11874 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11876 | Xml.PCData str ->
11877 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11879 let optional_child name xml =
11880 let children = Xml.children xml in
11882 Some (List.find (function
11883 | Xml.Element (n, _, _) when n = name -> true
11884 | _ -> false) children)
11888 let child name xml =
11889 match optional_child name xml with
11892 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11894 let attribute name xml =
11895 try Xml.attrib xml name
11896 with Xml.No_attribute _ ->
11897 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11901 generate_parsers grammar;
11905 (* Run external virt-inspector, then use parser to parse the XML. *)
11906 let inspect ?connect ?xml names =
11910 if names = [] then invalid_arg \"inspect: no names given\";
11911 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11912 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11914 let cmd = List.map Filename.quote cmd in
11915 let cmd = String.concat \" \" cmd in
11916 let chan = open_process_in cmd in
11917 let xml = Xml.parse_in chan in
11918 (match close_process_in chan with
11920 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11921 | WSIGNALED i | WSTOPPED i ->
11922 failwith (\"external virt-inspector command died or stopped on sig \" ^
11927 Xml.parse_string doc in
11928 parse_operatingsystems xml
11931 and generate_max_proc_nr () =
11932 pr "%d\n" max_proc_nr
11934 let output_to filename k =
11935 let filename_new = filename ^ ".new" in
11936 chan := open_out filename_new;
11939 chan := Pervasives.stdout;
11941 (* Is the new file different from the current file? *)
11942 if Sys.file_exists filename && files_equal filename filename_new then
11943 unlink filename_new (* same, so skip it *)
11945 (* different, overwrite old one *)
11946 (try chmod filename 0o644 with Unix_error _ -> ());
11947 rename filename_new filename;
11948 chmod filename 0o444;
11949 printf "written %s\n%!" filename;
11952 let perror msg = function
11953 | Unix_error (err, _, _) ->
11954 eprintf "%s: %s\n" msg (error_message err)
11956 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11958 (* Main program. *)
11961 try openfile "HACKING" [O_RDWR] 0
11963 | Unix_error (ENOENT, _, _) ->
11965 You are probably running this from the wrong directory.
11966 Run it from the top source directory using the command
11971 perror "open: HACKING" exn;
11974 (* Acquire a lock so parallel builds won't try to run the generator
11975 * twice at the same time. Subsequent builds will wait for the first
11976 * one to finish. Note the lock is released implicitly when the
11979 (try lockf lock_fd F_LOCK 1
11981 perror "lock: HACKING" exn;
11984 check_functions ();
11986 output_to "src/guestfs_protocol.x" generate_xdr;
11987 output_to "src/guestfs-structs.h" generate_structs_h;
11988 output_to "src/guestfs-actions.h" generate_actions_h;
11989 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11990 output_to "src/guestfs-actions.c" generate_client_actions;
11991 output_to "src/guestfs-bindtests.c" generate_bindtests;
11992 output_to "src/guestfs-structs.pod" generate_structs_pod;
11993 output_to "src/guestfs-actions.pod" generate_actions_pod;
11994 output_to "src/guestfs-availability.pod" generate_availability_pod;
11995 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11996 output_to "src/libguestfs.syms" generate_linker_script;
11997 output_to "daemon/actions.h" generate_daemon_actions_h;
11998 output_to "daemon/stubs.c" generate_daemon_actions;
11999 output_to "daemon/names.c" generate_daemon_names;
12000 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12001 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12002 output_to "capitests/tests.c" generate_tests;
12003 output_to "fish/cmds.c" generate_fish_cmds;
12004 output_to "fish/completion.c" generate_fish_completion;
12005 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12006 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12007 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12008 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12009 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12010 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12011 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12012 output_to "perl/Guestfs.xs" generate_perl_xs;
12013 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12014 output_to "perl/bindtests.pl" generate_perl_bindtests;
12015 output_to "python/guestfs-py.c" generate_python_c;
12016 output_to "python/guestfs.py" generate_python_py;
12017 output_to "python/bindtests.py" generate_python_bindtests;
12018 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12019 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12020 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12024 let cols = cols_of_struct typ in
12025 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12026 output_to filename (generate_java_struct jtyp cols);
12029 output_to "java/Makefile.inc" generate_java_makefile_inc;
12030 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12031 output_to "java/Bindtests.java" generate_java_bindtests;
12032 output_to "haskell/Guestfs.hs" generate_haskell_hs;
12033 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12034 output_to "csharp/Libguestfs.cs" generate_csharp;
12036 (* Always generate this file last, and unconditionally. It's used
12037 * by the Makefile to know when we must re-run the generator.
12039 let chan = open_out "src/stamp-generator" in
12040 fprintf chan "1\n";
12043 printf "generated %d lines of code\n" !lines