3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #load "xml-light.cma";;
50 type style = ret * args
52 (* "RErr" as a return value means an int used as a simple error
53 * indication, ie. 0 or -1.
57 (* "RInt" as a return value means an int which is -1 for error
58 * or any value >= 0 on success. Only use this for smallish
59 * positive ints (0 <= i < 2^30).
63 (* "RInt64" is the same as RInt, but is guaranteed to be able
64 * to return a full 64 bit value, _except_ that -1 means error
65 * (so -1 cannot be a valid, non-error return value).
69 (* "RBool" is a bool return value which can be true/false or
74 (* "RConstString" is a string that refers to a constant value.
75 * The return value must NOT be NULL (since NULL indicates
78 * Try to avoid using this. In particular you cannot use this
79 * for values returned from the daemon, because there is no
80 * thread-safe way to return them in the C API.
82 | RConstString of string
84 (* "RConstOptString" is an even more broken version of
85 * "RConstString". The returned string may be NULL and there
86 * is no way to return an error indication. Avoid using this!
88 | RConstOptString of string
90 (* "RString" is a returned string. It must NOT be NULL, since
91 * a NULL return indicates an error. The caller frees this.
95 (* "RStringList" is a list of strings. No string in the list
96 * can be NULL. The caller frees the strings and the array.
98 | RStringList of string
100 (* "RStruct" is a function which returns a single named structure
101 * or an error indication (in C, a struct, and in other languages
102 * with varying representations, but usually very efficient). See
103 * after the function list below for the structures.
105 | RStruct of string * string (* name of retval, name of struct *)
107 (* "RStructList" is a function which returns either a list/array
108 * of structures (could be zero-length), or an error indication.
110 | RStructList of string * string (* name of retval, name of struct *)
112 (* Key-value pairs of untyped strings. Turns into a hashtable or
113 * dictionary in languages which support it. DON'T use this as a
114 * general "bucket" for results. Prefer a stronger typed return
115 * value if one is available, or write a custom struct. Don't use
116 * this if the list could potentially be very long, since it is
117 * inefficient. Keys should be unique. NULLs are not permitted.
119 | RHashtable of string
121 (* "RBufferOut" is handled almost exactly like RString, but
122 * it allows the string to contain arbitrary 8 bit data including
123 * ASCII NUL. In the C API this causes an implicit extra parameter
124 * to be added of type <size_t *size_r>. The extra parameter
125 * returns the actual size of the return buffer in bytes.
127 * Other programming languages support strings with arbitrary 8 bit
130 * At the RPC layer we have to use the opaque<> type instead of
131 * string<>. Returned data is still limited to the max message
134 | RBufferOut of string
136 and args = argt list (* Function parameters, guestfs handle is implicit. *)
138 (* Note in future we should allow a "variable args" parameter as
139 * the final parameter, to allow commands like
140 * chmod mode file [file(s)...]
141 * This is not implemented yet, but many commands (such as chmod)
142 * are currently defined with the argument order keeping this future
143 * possibility in mind.
146 | String of string (* const char *name, cannot be NULL *)
147 | Device of string (* /dev device name, cannot be NULL *)
148 | Pathname of string (* file name, cannot be NULL *)
149 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
150 | OptString of string (* const char *name, may be NULL *)
151 | StringList of string(* list of strings (each string cannot be NULL) *)
152 | DeviceList of string(* list of Device names (each cannot be NULL) *)
153 | Bool of string (* boolean *)
154 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
155 | Int64 of string (* any 64 bit int *)
156 (* These are treated as filenames (simple string parameters) in
157 * the C API and bindings. But in the RPC protocol, we transfer
158 * the actual file content up to or down from the daemon.
159 * FileIn: local machine -> daemon (in request)
160 * FileOut: daemon -> local machine (in reply)
161 * In guestfish (only), the special name "-" means read from
162 * stdin or write to stdout.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <char *, int> pair.
169 * Most other languages have a string type which can contain
170 * ASCII NUL. We use whatever type is appropriate for each
172 * Buffers are limited by the total message size. To transfer
173 * large blocks of data, use FileIn/FileOut parameters instead.
174 * To return an arbitrary buffer, use RBufferOut.
180 | ProtocolLimitWarning (* display warning about protocol size limits *)
181 | DangerWillRobinson (* flags particularly dangerous commands *)
182 | FishAlias of string (* provide an alias for this cmd in guestfish *)
183 | FishAction of string (* call this function in guestfish *)
184 | NotInFish (* do not export via guestfish *)
185 | NotInDocs (* do not add this function to documentation *)
186 | DeprecatedBy of string (* function is deprecated, use .. instead *)
187 | Optional of string (* function is part of an optional group *)
189 (* You can supply zero or as many tests as you want per API call.
191 * Note that the test environment has 3 block devices, of size 500MB,
192 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
193 * a fourth ISO block device with some known files on it (/dev/sdd).
195 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
196 * Number of cylinders was 63 for IDE emulated disks with precisely
197 * the same size. How exactly this is calculated is a mystery.
199 * The ISO block device (/dev/sdd) comes from images/test.iso.
201 * To be able to run the tests in a reasonable amount of time,
202 * the virtual machine and block devices are reused between tests.
203 * So don't try testing kill_subprocess :-x
205 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207 * Don't assume anything about the previous contents of the block
208 * devices. Use 'Init*' to create some initial scenarios.
210 * You can add a prerequisite clause to any individual test. This
211 * is a run-time check, which, if it fails, causes the test to be
212 * skipped. Useful if testing a command which might not work on
213 * all variations of libguestfs builds. A test that has prerequisite
214 * of 'Always' is run unconditionally.
216 * In addition, packagers can skip individual tests by setting the
217 * environment variables: eg:
218 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
219 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
221 type tests = (test_init * test_prereq * test) list
223 (* Run the command sequence and just expect nothing to fail. *)
226 (* Run the command sequence and expect the output of the final
227 * command to be the string.
229 | TestOutput of seq * string
231 (* Run the command sequence and expect the output of the final
232 * command to be the list of strings.
234 | TestOutputList of seq * string list
236 (* Run the command sequence and expect the output of the final
237 * command to be the list of block devices (could be either
238 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
239 * character of each string).
241 | TestOutputListOfDevices of seq * string list
243 (* Run the command sequence and expect the output of the final
244 * command to be the integer.
246 | TestOutputInt of seq * int
248 (* Run the command sequence and expect the output of the final
249 * command to be <op> <int>, eg. ">=", "1".
251 | TestOutputIntOp of seq * string * int
253 (* Run the command sequence and expect the output of the final
254 * command to be a true value (!= 0 or != NULL).
256 | TestOutputTrue of seq
258 (* Run the command sequence and expect the output of the final
259 * command to be a false value (== 0 or == NULL, but not an error).
261 | TestOutputFalse of seq
263 (* Run the command sequence and expect the output of the final
264 * command to be a list of the given length (but don't care about
267 | TestOutputLength of seq * int
269 (* Run the command sequence and expect the output of the final
270 * command to be a buffer (RBufferOut), ie. string + size.
272 | TestOutputBuffer of seq * string
274 (* Run the command sequence and expect the output of the final
275 * command to be a structure.
277 | TestOutputStruct of seq * test_field_compare list
279 (* Run the command sequence and expect the final command (only)
282 | TestLastFail of seq
284 and test_field_compare =
285 | CompareWithInt of string * int
286 | CompareWithIntOp of string * string * int
287 | CompareWithString of string * string
288 | CompareFieldsIntEq of string * string
289 | CompareFieldsStrEq of string * string
291 (* Test prerequisites. *)
293 (* Test always runs. *)
296 (* Test is currently disabled - eg. it fails, or it tests some
297 * unimplemented feature.
301 (* 'string' is some C code (a function body) that should return
302 * true or false. The test will run if the code returns true.
306 (* As for 'If' but the test runs _unless_ the code returns true. *)
309 (* Some initial scenarios for testing. *)
311 (* Do nothing, block devices could contain random stuff including
312 * LVM PVs, and some filesystems might be mounted. This is usually
317 (* Block devices are empty and no filesystems are mounted. *)
320 (* /dev/sda contains a single partition /dev/sda1, with random
321 * content. /dev/sdb and /dev/sdc may have random content.
326 (* /dev/sda contains a single partition /dev/sda1, which is formatted
327 * as ext2, empty [except for lost+found] and mounted on /.
328 * /dev/sdb and /dev/sdc may have random content.
334 * /dev/sda1 (is a PV):
335 * /dev/VG/LV (size 8MB):
336 * formatted as ext2, empty [except for lost+found], mounted on /
337 * /dev/sdb and /dev/sdc may have random content.
341 (* /dev/sdd (the ISO, see images/ directory in source)
346 (* Sequence of commands for testing. *)
348 and cmd = string list
350 (* Note about long descriptions: When referring to another
351 * action, use the format C<guestfs_other> (ie. the full name of
352 * the C function). This will be replaced as appropriate in other
355 * Apart from that, long descriptions are just perldoc paragraphs.
358 (* Generate a random UUID (used in tests). *)
360 let chan = open_process_in "uuidgen" in
361 let uuid = input_line chan in
362 (match close_process_in chan with
365 failwith "uuidgen: process exited with non-zero status"
366 | WSIGNALED _ | WSTOPPED _ ->
367 failwith "uuidgen: process signalled or stopped by signal"
371 (* These test functions are used in the language binding tests. *)
373 let test_all_args = [
376 StringList "strlist";
384 let test_all_rets = [
385 (* except for RErr, which is tested thoroughly elsewhere *)
386 "test0rint", RInt "valout";
387 "test0rint64", RInt64 "valout";
388 "test0rbool", RBool "valout";
389 "test0rconststring", RConstString "valout";
390 "test0rconstoptstring", RConstOptString "valout";
391 "test0rstring", RString "valout";
392 "test0rstringlist", RStringList "valout";
393 "test0rstruct", RStruct ("valout", "lvm_pv");
394 "test0rstructlist", RStructList ("valout", "lvm_pv");
395 "test0rhashtable", RHashtable "valout";
398 let test_functions = [
399 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401 "internal test function - do not use",
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 parameter type correctly.
407 It echos the contents of each parameter to stdout.
409 You probably don't want to call this function.");
413 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415 "internal test function - do not use",
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
421 It converts string C<val> to the return type.
423 You probably don't want to call this function.");
424 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426 "internal test function - do not use",
428 This is an internal test function which is used to test whether
429 the automatically generated bindings can handle every possible
430 return type correctly.
432 This function always returns an error.
434 You probably don't want to call this function.")]
438 (* non_daemon_functions are any functions which don't get processed
439 * in the daemon, eg. functions for setting and getting local
440 * configuration values.
443 let non_daemon_functions = test_functions @ [
444 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446 "launch the qemu subprocess",
448 Internally libguestfs is implemented by running a virtual machine
451 You should call this after configuring the handle
452 (eg. adding drives) but before performing any actions.");
454 ("wait_ready", (RErr, []), -1, [NotInFish],
456 "wait until the qemu subprocess launches (no op)",
458 This function is a no op.
460 In versions of the API E<lt> 1.0.71 you had to call this function
461 just after calling C<guestfs_launch> to wait for the launch
462 to complete. However this is no longer necessary because
463 C<guestfs_launch> now does the waiting.
465 If you see any calls to this function in code then you can just
466 remove them, unless you want to retain compatibility with older
467 versions of the API.");
469 ("kill_subprocess", (RErr, []), -1, [],
471 "kill the qemu subprocess",
473 This kills the qemu subprocess. You should never need to call this.");
475 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477 "add an image to examine or modify",
479 This function adds a virtual machine disk image C<filename> to the
480 guest. The first time you call this function, the disk appears as IDE
481 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
484 You don't necessarily need to be root when using libguestfs. However
485 you obviously do need sufficient permissions to access the filename
486 for whatever operations you want to perform (ie. read access if you
487 just want to read the image or write access if you want to modify the
490 This is equivalent to the qemu parameter
491 C<-drive file=filename,cache=off,if=...>.
493 C<cache=off> is omitted in cases where it is not supported by
494 the underlying filesystem.
496 C<if=...> is set at compile time by the configuration option
497 C<./configure --with-drive-if=...>. In the rare case where you
498 might need to change this at run time, use C<guestfs_add_drive_with_if>
499 or C<guestfs_add_drive_ro_with_if>.
501 Note that this call checks for the existence of C<filename>. This
502 stops you from specifying other types of drive which are supported
503 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
504 the general C<guestfs_config> call instead.");
506 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508 "add a CD-ROM disk image to examine",
510 This function adds a virtual CD-ROM disk image to the guest.
512 This is equivalent to the qemu parameter C<-cdrom filename>.
520 This call checks for the existence of C<filename>. This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
523 the general C<guestfs_config> call instead.
527 If you just want to add an ISO file (often you use this as an
528 efficient way to transfer large files into the guest), then you
529 should probably use C<guestfs_add_drive_ro> instead.
533 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535 "add a drive in snapshot mode (read-only)",
537 This adds a drive in snapshot mode, making it effectively
540 Note that writes to the device are allowed, and will be seen for
541 the duration of the guestfs handle, but they are written
542 to a temporary file which is discarded as soon as the guestfs
543 handle is closed. We don't currently have any method to enable
544 changes to be committed, although qemu can support this.
546 This is equivalent to the qemu parameter
547 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549 C<if=...> is set at compile time by the configuration option
550 C<./configure --with-drive-if=...>. In the rare case where you
551 might need to change this at run time, use C<guestfs_add_drive_with_if>
552 or C<guestfs_add_drive_ro_with_if>.
554 C<readonly=on> is only added where qemu supports this option.
556 Note that this call checks for the existence of C<filename>. This
557 stops you from specifying other types of drive which are supported
558 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
559 the general C<guestfs_config> call instead.");
561 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563 "add qemu parameters",
565 This can be used to add arbitrary qemu command line parameters
566 of the form C<-param value>. Actually it's not quite arbitrary - we
567 prevent you from setting some parameters which would interfere with
568 parameters that we use.
570 The first character of C<param> string must be a C<-> (dash).
572 C<value> can be NULL.");
574 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576 "set the qemu binary",
578 Set the qemu binary that we will use.
580 The default is chosen when the library was compiled by the
583 You can also override this by setting the C<LIBGUESTFS_QEMU>
584 environment variable.
586 Setting C<qemu> to C<NULL> restores the default qemu binary.
588 Note that you should call this function as early as possible
589 after creating the handle. This is because some pre-launch
590 operations depend on testing qemu features (by running C<qemu -help>).
591 If the qemu binary changes, we don't retest features, and
592 so you might see inconsistent results. Using the environment
593 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
594 the qemu binary at the same time as the handle is created.");
596 ("get_qemu", (RConstString "qemu", []), -1, [],
597 [InitNone, Always, TestRun (
599 "get the qemu binary",
601 Return the current qemu binary.
603 This is always non-NULL. If it wasn't set already, then this will
604 return the default qemu binary name.");
606 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608 "set the search path",
610 Set the path that libguestfs searches for kernel and initrd.img.
612 The default is C<$libdir/guestfs> unless overridden by setting
613 C<LIBGUESTFS_PATH> environment variable.
615 Setting C<path> to C<NULL> restores the default path.");
617 ("get_path", (RConstString "path", []), -1, [],
618 [InitNone, Always, TestRun (
620 "get the search path",
622 Return the current search path.
624 This is always non-NULL. If it wasn't set already, then this will
625 return the default path.");
627 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629 "add options to kernel command line",
631 This function is used to add additional options to the
632 guest kernel command line.
634 The default is C<NULL> unless overridden by setting
635 C<LIBGUESTFS_APPEND> environment variable.
637 Setting C<append> to C<NULL> means I<no> additional options
638 are passed (libguestfs always adds a few of its own).");
640 ("get_append", (RConstOptString "append", []), -1, [],
641 (* This cannot be tested with the current framework. The
642 * function can return NULL in normal operations, which the
643 * test framework interprets as an error.
646 "get the additional kernel options",
648 Return the additional kernel options which are added to the
649 guest kernel command line.
651 If C<NULL> then no options are added.");
653 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
657 If C<autosync> is true, this enables autosync. Libguestfs will make a
658 best effort attempt to run C<guestfs_umount_all> followed by
659 C<guestfs_sync> when the handle is closed
660 (also if the program exits without closing handles).
662 This is disabled by default (except in guestfish where it is
663 enabled by default).");
665 ("get_autosync", (RBool "autosync", []), -1, [],
666 [InitNone, Always, TestRun (
667 [["get_autosync"]])],
670 Get the autosync flag.");
672 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
676 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678 Verbose messages are disabled unless the environment variable
679 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681 ("get_verbose", (RBool "verbose", []), -1, [],
685 This returns the verbose messages flag.");
687 ("is_ready", (RBool "ready", []), -1, [],
688 [InitNone, Always, TestOutputTrue (
690 "is ready to accept commands",
692 This returns true iff this handle is ready to accept commands
693 (in the C<READY> state).
695 For more information on states, see L<guestfs(3)>.");
697 ("is_config", (RBool "config", []), -1, [],
698 [InitNone, Always, TestOutputFalse (
700 "is in configuration state",
702 This returns true iff this handle is being configured
703 (in the C<CONFIG> state).
705 For more information on states, see L<guestfs(3)>.");
707 ("is_launching", (RBool "launching", []), -1, [],
708 [InitNone, Always, TestOutputFalse (
709 [["is_launching"]])],
710 "is launching subprocess",
712 This returns true iff this handle is launching the subprocess
713 (in the C<LAUNCHING> state).
715 For more information on states, see L<guestfs(3)>.");
717 ("is_busy", (RBool "busy", []), -1, [],
718 [InitNone, Always, TestOutputFalse (
720 "is busy processing a command",
722 This returns true iff this handle is busy processing a command
723 (in the C<BUSY> state).
725 For more information on states, see L<guestfs(3)>.");
727 ("get_state", (RInt "state", []), -1, [],
729 "get the current state",
731 This returns the current state as an opaque integer. This is
732 only useful for printing debug and internal error messages.
734 For more information on states, see L<guestfs(3)>.");
736 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
737 [InitNone, Always, TestOutputInt (
738 [["set_memsize"; "500"];
739 ["get_memsize"]], 500)],
740 "set memory allocated to the qemu subprocess",
742 This sets the memory size in megabytes allocated to the
743 qemu subprocess. This only has any effect if called before
746 You can also change this by setting the environment
747 variable C<LIBGUESTFS_MEMSIZE> before the handle is
750 For more information on the architecture of libguestfs,
751 see L<guestfs(3)>.");
753 ("get_memsize", (RInt "memsize", []), -1, [],
754 [InitNone, Always, TestOutputIntOp (
755 [["get_memsize"]], ">=", 256)],
756 "get memory allocated to the qemu subprocess",
758 This gets the memory size in megabytes allocated to the
761 If C<guestfs_set_memsize> was not called
762 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
763 then this returns the compiled-in default value for memsize.
765 For more information on the architecture of libguestfs,
766 see L<guestfs(3)>.");
768 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
769 [InitNone, Always, TestOutputIntOp (
770 [["get_pid"]], ">=", 1)],
771 "get PID of qemu subprocess",
773 Return the process ID of the qemu subprocess. If there is no
774 qemu subprocess, then this will return an error.
776 This is an internal call used for debugging and testing.");
778 ("version", (RStruct ("version", "version"), []), -1, [],
779 [InitNone, Always, TestOutputStruct (
780 [["version"]], [CompareWithInt ("major", 1)])],
781 "get the library version number",
783 Return the libguestfs version number that the program is linked
786 Note that because of dynamic linking this is not necessarily
787 the version of libguestfs that you compiled against. You can
788 compile the program, and then at runtime dynamically link
789 against a completely different C<libguestfs.so> library.
791 This call was added in version C<1.0.58>. In previous
792 versions of libguestfs there was no way to get the version
793 number. From C code you can use ELF weak linking tricks to find out if
794 this symbol exists (if it doesn't, then it's an earlier version).
796 The call returns a structure with four elements. The first
797 three (C<major>, C<minor> and C<release>) are numbers and
798 correspond to the usual version triplet. The fourth element
799 (C<extra>) is a string and is normally empty, but may be
800 used for distro-specific information.
802 To construct the original version string:
803 C<$major.$minor.$release$extra>
805 I<Note:> Don't use this call to test for availability
806 of features. Distro backports makes this unreliable. Use
807 C<guestfs_available> instead.");
809 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
810 [InitNone, Always, TestOutputTrue (
811 [["set_selinux"; "true"];
813 "set SELinux enabled or disabled at appliance boot",
815 This sets the selinux flag that is passed to the appliance
816 at boot time. The default is C<selinux=0> (disabled).
818 Note that if SELinux is enabled, it is always in
819 Permissive mode (C<enforcing=0>).
821 For more information on the architecture of libguestfs,
822 see L<guestfs(3)>.");
824 ("get_selinux", (RBool "selinux", []), -1, [],
826 "get SELinux enabled flag",
828 This returns the current setting of the selinux flag which
829 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
834 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
835 [InitNone, Always, TestOutputFalse (
836 [["set_trace"; "false"];
838 "enable or disable command traces",
840 If the command trace flag is set to 1, then commands are
841 printed on stdout before they are executed in a format
842 which is very similar to the one used by guestfish. In
843 other words, you can run a program with this enabled, and
844 you will get out a script which you can feed to guestfish
845 to perform the same set of actions.
847 If you want to trace C API calls into libguestfs (and
848 other libraries) then possibly a better way is to use
849 the external ltrace(1) command.
851 Command traces are disabled unless the environment variable
852 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854 ("get_trace", (RBool "trace", []), -1, [],
856 "get command trace enabled flag",
858 Return the command trace flag.");
860 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
861 [InitNone, Always, TestOutputFalse (
862 [["set_direct"; "false"];
864 "enable or disable direct appliance mode",
866 If the direct appliance mode flag is enabled, then stdin and
867 stdout are passed directly through to the appliance once it
870 One consequence of this is that log messages aren't caught
871 by the library and handled by C<guestfs_set_log_message_callback>,
872 but go straight to stdout.
874 You probably don't want to use this unless you know what you
877 The default is disabled.");
879 ("get_direct", (RBool "direct", []), -1, [],
881 "get direct appliance mode flag",
883 Return the direct appliance mode flag.");
885 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
886 [InitNone, Always, TestOutputTrue (
887 [["set_recovery_proc"; "true"];
888 ["get_recovery_proc"]])],
889 "enable or disable the recovery process",
891 If this is called with the parameter C<false> then
892 C<guestfs_launch> does not create a recovery process. The
893 purpose of the recovery process is to stop runaway qemu
894 processes in the case where the main program aborts abruptly.
896 This only has any effect if called before C<guestfs_launch>,
897 and the default is true.
899 About the only time when you would want to disable this is
900 if the main process will fork itself into the background
901 (\"daemonize\" itself). In this case the recovery process
902 thinks that the main program has disappeared and so kills
903 qemu, which is not very helpful.");
905 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907 "get recovery process enabled flag",
909 Return the recovery process enabled flag.");
911 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913 "add a drive specifying the QEMU block emulation to use",
915 This is the same as C<guestfs_add_drive> but it allows you
916 to specify the QEMU interface emulation to use at run time.");
918 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920 "add a drive read-only specifying the QEMU block emulation to use",
922 This is the same as C<guestfs_add_drive_ro> but it allows you
923 to specify the QEMU interface emulation to use at run time.");
927 (* daemon_functions are any functions which cause some action
928 * to take place in the daemon.
931 let daemon_functions = [
932 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
933 [InitEmpty, Always, TestOutput (
934 [["part_disk"; "/dev/sda"; "mbr"];
935 ["mkfs"; "ext2"; "/dev/sda1"];
936 ["mount"; "/dev/sda1"; "/"];
937 ["write_file"; "/new"; "new file contents"; "0"];
938 ["cat"; "/new"]], "new file contents")],
939 "mount a guest disk at a position in the filesystem",
941 Mount a guest disk at a position in the filesystem. Block devices
942 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
943 the guest. If those block devices contain partitions, they will have
944 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
947 The rules are the same as for L<mount(2)>: A filesystem must
948 first be mounted on C</> before others can be mounted. Other
949 filesystems can only be mounted on directories which already
952 The mounted filesystem is writable, if we have sufficient permissions
953 on the underlying device.
955 The filesystem options C<sync> and C<noatime> are set with this
956 call, in order to improve reliability.");
958 ("sync", (RErr, []), 2, [],
959 [ InitEmpty, Always, TestRun [["sync"]]],
960 "sync disks, writes are flushed through to the disk image",
962 This syncs the disk, so that any writes are flushed through to the
963 underlying disk image.
965 You should always call this if you have modified a disk image, before
966 closing the handle.");
968 ("touch", (RErr, [Pathname "path"]), 3, [],
969 [InitBasicFS, Always, TestOutputTrue (
971 ["exists"; "/new"]])],
972 "update file timestamps or create a new file",
974 Touch acts like the L<touch(1)> command. It can be used to
975 update the timestamps on a file, or, if the file does not exist,
976 to create a new zero-length file.");
978 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
979 [InitISOFS, Always, TestOutput (
980 [["cat"; "/known-2"]], "abcdef\n")],
981 "list the contents of a file",
983 Return the contents of the file named C<path>.
985 Note that this function cannot correctly handle binary files
986 (specifically, files containing C<\\0> character which is treated
987 as end of string). For those you need to use the C<guestfs_read_file>
988 or C<guestfs_download> functions which have a more complex interface.");
990 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
991 [], (* XXX Tricky to test because it depends on the exact format
992 * of the 'ls -l' command, which changes between F10 and F11.
994 "list the files in a directory (long format)",
996 List the files in C<directory> (relative to the root directory,
997 there is no cwd) in the format of 'ls -la'.
999 This command is mostly useful for interactive sessions. It
1000 is I<not> intended that you try to parse the output string.");
1002 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1003 [InitBasicFS, Always, TestOutputList (
1005 ["touch"; "/newer"];
1006 ["touch"; "/newest"];
1007 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1008 "list the files in a directory",
1010 List the files in C<directory> (relative to the root directory,
1011 there is no cwd). The '.' and '..' entries are not returned, but
1012 hidden files are shown.
1014 This command is mostly useful for interactive sessions. Programs
1015 should probably use C<guestfs_readdir> instead.");
1017 ("list_devices", (RStringList "devices", []), 7, [],
1018 [InitEmpty, Always, TestOutputListOfDevices (
1019 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1020 "list the block devices",
1022 List all the block devices.
1024 The full block device names are returned, eg. C</dev/sda>");
1026 ("list_partitions", (RStringList "partitions", []), 8, [],
1027 [InitBasicFS, Always, TestOutputListOfDevices (
1028 [["list_partitions"]], ["/dev/sda1"]);
1029 InitEmpty, Always, TestOutputListOfDevices (
1030 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1031 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1032 "list the partitions",
1034 List all the partitions detected on all block devices.
1036 The full partition device names are returned, eg. C</dev/sda1>
1038 This does not return logical volumes. For that you will need to
1039 call C<guestfs_lvs>.");
1041 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1042 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1043 [["pvs"]], ["/dev/sda1"]);
1044 InitEmpty, Always, TestOutputListOfDevices (
1045 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1046 ["pvcreate"; "/dev/sda1"];
1047 ["pvcreate"; "/dev/sda2"];
1048 ["pvcreate"; "/dev/sda3"];
1049 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1050 "list the LVM physical volumes (PVs)",
1052 List all the physical volumes detected. This is the equivalent
1053 of the L<pvs(8)> command.
1055 This returns a list of just the device names that contain
1056 PVs (eg. C</dev/sda2>).
1058 See also C<guestfs_pvs_full>.");
1060 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1061 [InitBasicFSonLVM, Always, TestOutputList (
1063 InitEmpty, Always, TestOutputList (
1064 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1065 ["pvcreate"; "/dev/sda1"];
1066 ["pvcreate"; "/dev/sda2"];
1067 ["pvcreate"; "/dev/sda3"];
1068 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1069 ["vgcreate"; "VG2"; "/dev/sda3"];
1070 ["vgs"]], ["VG1"; "VG2"])],
1071 "list the LVM volume groups (VGs)",
1073 List all the volumes groups detected. This is the equivalent
1074 of the L<vgs(8)> command.
1076 This returns a list of just the volume group names that were
1077 detected (eg. C<VolGroup00>).
1079 See also C<guestfs_vgs_full>.");
1081 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1082 [InitBasicFSonLVM, Always, TestOutputList (
1083 [["lvs"]], ["/dev/VG/LV"]);
1084 InitEmpty, Always, TestOutputList (
1085 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1086 ["pvcreate"; "/dev/sda1"];
1087 ["pvcreate"; "/dev/sda2"];
1088 ["pvcreate"; "/dev/sda3"];
1089 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1090 ["vgcreate"; "VG2"; "/dev/sda3"];
1091 ["lvcreate"; "LV1"; "VG1"; "50"];
1092 ["lvcreate"; "LV2"; "VG1"; "50"];
1093 ["lvcreate"; "LV3"; "VG2"; "50"];
1094 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1095 "list the LVM logical volumes (LVs)",
1097 List all the logical volumes detected. This is the equivalent
1098 of the L<lvs(8)> command.
1100 This returns a list of the logical volume device names
1101 (eg. C</dev/VolGroup00/LogVol00>).
1103 See also C<guestfs_lvs_full>.");
1105 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1106 [], (* XXX how to test? *)
1107 "list the LVM physical volumes (PVs)",
1109 List all the physical volumes detected. This is the equivalent
1110 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1112 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1113 [], (* XXX how to test? *)
1114 "list the LVM volume groups (VGs)",
1116 List all the volumes groups detected. This is the equivalent
1117 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1119 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1120 [], (* XXX how to test? *)
1121 "list the LVM logical volumes (LVs)",
1123 List all the logical volumes detected. This is the equivalent
1124 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1126 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1127 [InitISOFS, Always, TestOutputList (
1128 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1129 InitISOFS, Always, TestOutputList (
1130 [["read_lines"; "/empty"]], [])],
1131 "read file as lines",
1133 Return the contents of the file named C<path>.
1135 The file contents are returned as a list of lines. Trailing
1136 C<LF> and C<CRLF> character sequences are I<not> returned.
1138 Note that this function cannot correctly handle binary files
1139 (specifically, files containing C<\\0> character which is treated
1140 as end of line). For those you need to use the C<guestfs_read_file>
1141 function which has a more complex interface.");
1143 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1144 [], (* XXX Augeas code needs tests. *)
1145 "create a new Augeas handle",
1147 Create a new Augeas handle for editing configuration files.
1148 If there was any previous Augeas handle associated with this
1149 guestfs session, then it is closed.
1151 You must call this before using any other C<guestfs_aug_*>
1154 C<root> is the filesystem root. C<root> must not be NULL,
1157 The flags are the same as the flags defined in
1158 E<lt>augeas.hE<gt>, the logical I<or> of the following
1163 =item C<AUG_SAVE_BACKUP> = 1
1165 Keep the original file with a C<.augsave> extension.
1167 =item C<AUG_SAVE_NEWFILE> = 2
1169 Save changes into a file with extension C<.augnew>, and
1170 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1172 =item C<AUG_TYPE_CHECK> = 4
1174 Typecheck lenses (can be expensive).
1176 =item C<AUG_NO_STDINC> = 8
1178 Do not use standard load path for modules.
1180 =item C<AUG_SAVE_NOOP> = 16
1182 Make save a no-op, just record what would have been changed.
1184 =item C<AUG_NO_LOAD> = 32
1186 Do not load the tree in C<guestfs_aug_init>.
1190 To close the handle, you can call C<guestfs_aug_close>.
1192 To find out more about Augeas, see L<http://augeas.net/>.");
1194 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1195 [], (* XXX Augeas code needs tests. *)
1196 "close the current Augeas handle",
1198 Close the current Augeas handle and free up any resources
1199 used by it. After calling this, you have to call
1200 C<guestfs_aug_init> again before you can use any other
1201 Augeas functions.");
1203 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1204 [], (* XXX Augeas code needs tests. *)
1205 "define an Augeas variable",
1207 Defines an Augeas variable C<name> whose value is the result
1208 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1211 On success this returns the number of nodes in C<expr>, or
1212 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "define an Augeas node",
1218 Defines a variable C<name> whose value is the result of
1221 If C<expr> evaluates to an empty nodeset, a node is created,
1222 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1223 C<name> will be the nodeset containing that single node.
1225 On success this returns a pair containing the
1226 number of nodes in the nodeset, and a boolean flag
1227 if a node was created.");
1229 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1230 [], (* XXX Augeas code needs tests. *)
1231 "look up the value of an Augeas path",
1233 Look up the value associated with C<path>. If C<path>
1234 matches exactly one node, the C<value> is returned.");
1236 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1237 [], (* XXX Augeas code needs tests. *)
1238 "set Augeas path to value",
1240 Set the value associated with C<path> to C<value>.");
1242 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "insert a sibling Augeas node",
1246 Create a new sibling C<label> for C<path>, inserting it into
1247 the tree before or after C<path> (depending on the boolean
1250 C<path> must match exactly one existing node in the tree, and
1251 C<label> must be a label, ie. not contain C</>, C<*> or end
1252 with a bracketed index C<[N]>.");
1254 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1255 [], (* XXX Augeas code needs tests. *)
1256 "remove an Augeas path",
1258 Remove C<path> and all of its children.
1260 On success this returns the number of entries which were removed.");
1262 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1263 [], (* XXX Augeas code needs tests. *)
1266 Move the node C<src> to C<dest>. C<src> must match exactly
1267 one node. C<dest> is overwritten if it exists.");
1269 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1270 [], (* XXX Augeas code needs tests. *)
1271 "return Augeas nodes which match augpath",
1273 Returns a list of paths which match the path expression C<path>.
1274 The returned paths are sufficiently qualified so that they match
1275 exactly one node in the current tree.");
1277 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1278 [], (* XXX Augeas code needs tests. *)
1279 "write all pending Augeas changes to disk",
1281 This writes all pending changes to disk.
1283 The flags which were passed to C<guestfs_aug_init> affect exactly
1284 how files are saved.");
1286 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1287 [], (* XXX Augeas code needs tests. *)
1288 "load files into the tree",
1290 Load files into the tree.
1292 See C<aug_load> in the Augeas documentation for the full gory
1295 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1296 [], (* XXX Augeas code needs tests. *)
1297 "list Augeas nodes under augpath",
1299 This is just a shortcut for listing C<guestfs_aug_match>
1300 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302 ("rm", (RErr, [Pathname "path"]), 29, [],
1303 [InitBasicFS, Always, TestRun
1306 InitBasicFS, Always, TestLastFail
1308 InitBasicFS, Always, TestLastFail
1313 Remove the single file C<path>.");
1315 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1316 [InitBasicFS, Always, TestRun
1319 InitBasicFS, Always, TestLastFail
1320 [["rmdir"; "/new"]];
1321 InitBasicFS, Always, TestLastFail
1323 ["rmdir"; "/new"]]],
1324 "remove a directory",
1326 Remove the single directory C<path>.");
1328 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1329 [InitBasicFS, Always, TestOutputFalse
1331 ["mkdir"; "/new/foo"];
1332 ["touch"; "/new/foo/bar"];
1334 ["exists"; "/new"]]],
1335 "remove a file or directory recursively",
1337 Remove the file or directory C<path>, recursively removing the
1338 contents if its a directory. This is like the C<rm -rf> shell
1341 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1342 [InitBasicFS, Always, TestOutputTrue
1344 ["is_dir"; "/new"]];
1345 InitBasicFS, Always, TestLastFail
1346 [["mkdir"; "/new/foo/bar"]]],
1347 "create a directory",
1349 Create a directory named C<path>.");
1351 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1352 [InitBasicFS, Always, TestOutputTrue
1353 [["mkdir_p"; "/new/foo/bar"];
1354 ["is_dir"; "/new/foo/bar"]];
1355 InitBasicFS, Always, TestOutputTrue
1356 [["mkdir_p"; "/new/foo/bar"];
1357 ["is_dir"; "/new/foo"]];
1358 InitBasicFS, Always, TestOutputTrue
1359 [["mkdir_p"; "/new/foo/bar"];
1360 ["is_dir"; "/new"]];
1361 (* Regression tests for RHBZ#503133: *)
1362 InitBasicFS, Always, TestRun
1364 ["mkdir_p"; "/new"]];
1365 InitBasicFS, Always, TestLastFail
1367 ["mkdir_p"; "/new"]]],
1368 "create a directory and parents",
1370 Create a directory named C<path>, creating any parent directories
1371 as necessary. This is like the C<mkdir -p> shell command.");
1373 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1374 [], (* XXX Need stat command to test *)
1377 Change the mode (permissions) of C<path> to C<mode>. Only
1378 numeric modes are supported.
1380 I<Note>: When using this command from guestfish, C<mode>
1381 by default would be decimal, unless you prefix it with
1382 C<0> to get octal, ie. use C<0700> not C<700>.");
1384 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1385 [], (* XXX Need stat command to test *)
1386 "change file owner and group",
1388 Change the file owner to C<owner> and group to C<group>.
1390 Only numeric uid and gid are supported. If you want to use
1391 names, you will need to locate and parse the password file
1392 yourself (Augeas support makes this relatively easy).");
1394 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1395 [InitISOFS, Always, TestOutputTrue (
1396 [["exists"; "/empty"]]);
1397 InitISOFS, Always, TestOutputTrue (
1398 [["exists"; "/directory"]])],
1399 "test if file or directory exists",
1401 This returns C<true> if and only if there is a file, directory
1402 (or anything) with the given C<path> name.
1404 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1407 [InitISOFS, Always, TestOutputTrue (
1408 [["is_file"; "/known-1"]]);
1409 InitISOFS, Always, TestOutputFalse (
1410 [["is_file"; "/directory"]])],
1411 "test if file exists",
1413 This returns C<true> if and only if there is a file
1414 with the given C<path> name. Note that it returns false for
1415 other objects like directories.
1417 See also C<guestfs_stat>.");
1419 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1420 [InitISOFS, Always, TestOutputFalse (
1421 [["is_dir"; "/known-3"]]);
1422 InitISOFS, Always, TestOutputTrue (
1423 [["is_dir"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a directory
1427 with the given C<path> name. Note that it returns false for
1428 other objects like files.
1430 See also C<guestfs_stat>.");
1432 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1433 [InitEmpty, Always, TestOutputListOfDevices (
1434 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1435 ["pvcreate"; "/dev/sda1"];
1436 ["pvcreate"; "/dev/sda2"];
1437 ["pvcreate"; "/dev/sda3"];
1438 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1439 "create an LVM physical volume",
1441 This creates an LVM physical volume on the named C<device>,
1442 where C<device> should usually be a partition name such
1445 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputList (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1452 ["vgcreate"; "VG2"; "/dev/sda3"];
1453 ["vgs"]], ["VG1"; "VG2"])],
1454 "create an LVM volume group",
1456 This creates an LVM volume group called C<volgroup>
1457 from the non-empty list of physical volumes C<physvols>.");
1459 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1460 [InitEmpty, Always, TestOutputList (
1461 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462 ["pvcreate"; "/dev/sda1"];
1463 ["pvcreate"; "/dev/sda2"];
1464 ["pvcreate"; "/dev/sda3"];
1465 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1466 ["vgcreate"; "VG2"; "/dev/sda3"];
1467 ["lvcreate"; "LV1"; "VG1"; "50"];
1468 ["lvcreate"; "LV2"; "VG1"; "50"];
1469 ["lvcreate"; "LV3"; "VG2"; "50"];
1470 ["lvcreate"; "LV4"; "VG2"; "50"];
1471 ["lvcreate"; "LV5"; "VG2"; "50"];
1473 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1474 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1475 "create an LVM volume group",
1477 This creates an LVM volume group called C<logvol>
1478 on the volume group C<volgroup>, with C<size> megabytes.");
1480 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1481 [InitEmpty, Always, TestOutput (
1482 [["part_disk"; "/dev/sda"; "mbr"];
1483 ["mkfs"; "ext2"; "/dev/sda1"];
1484 ["mount_options"; ""; "/dev/sda1"; "/"];
1485 ["write_file"; "/new"; "new file contents"; "0"];
1486 ["cat"; "/new"]], "new file contents")],
1487 "make a filesystem",
1489 This creates a filesystem on C<device> (usually a partition
1490 or LVM logical volume). The filesystem type is C<fstype>, for
1493 ("sfdisk", (RErr, [Device "device";
1494 Int "cyls"; Int "heads"; Int "sectors";
1495 StringList "lines"]), 43, [DangerWillRobinson],
1497 "create partitions on a block device",
1499 This is a direct interface to the L<sfdisk(8)> program for creating
1500 partitions on block devices.
1502 C<device> should be a block device, for example C</dev/sda>.
1504 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1505 and sectors on the device, which are passed directly to sfdisk as
1506 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1507 of these, then the corresponding parameter is omitted. Usually for
1508 'large' disks, you can just pass C<0> for these, but for small
1509 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1510 out the right geometry and you will need to tell it.
1512 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1513 information refer to the L<sfdisk(8)> manpage.
1515 To create a single partition occupying the whole disk, you would
1516 pass C<lines> as a single element list, when the single element being
1517 the string C<,> (comma).
1519 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1520 C<guestfs_part_init>");
1522 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1523 [InitBasicFS, Always, TestOutput (
1524 [["write_file"; "/new"; "new file contents"; "0"];
1525 ["cat"; "/new"]], "new file contents");
1526 InitBasicFS, Always, TestOutput (
1527 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1528 ["cat"; "/new"]], "\nnew file contents\n");
1529 InitBasicFS, Always, TestOutput (
1530 [["write_file"; "/new"; "\n\n"; "0"];
1531 ["cat"; "/new"]], "\n\n");
1532 InitBasicFS, Always, TestOutput (
1533 [["write_file"; "/new"; ""; "0"];
1534 ["cat"; "/new"]], "");
1535 InitBasicFS, Always, TestOutput (
1536 [["write_file"; "/new"; "\n\n\n"; "0"];
1537 ["cat"; "/new"]], "\n\n\n");
1538 InitBasicFS, Always, TestOutput (
1539 [["write_file"; "/new"; "\n"; "0"];
1540 ["cat"; "/new"]], "\n")],
1543 This call creates a file called C<path>. The contents of the
1544 file is the string C<content> (which can contain any 8 bit data),
1545 with length C<size>.
1547 As a special case, if C<size> is C<0>
1548 then the length is calculated using C<strlen> (so in this case
1549 the content cannot contain embedded ASCII NULs).
1551 I<NB.> Owing to a bug, writing content containing ASCII NUL
1552 characters does I<not> work, even if the length is specified.
1553 We hope to resolve this bug in a future version. In the meantime
1554 use C<guestfs_upload>.");
1556 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557 [InitEmpty, Always, TestOutputListOfDevices (
1558 [["part_disk"; "/dev/sda"; "mbr"];
1559 ["mkfs"; "ext2"; "/dev/sda1"];
1560 ["mount_options"; ""; "/dev/sda1"; "/"];
1561 ["mounts"]], ["/dev/sda1"]);
1562 InitEmpty, Always, TestOutputList (
1563 [["part_disk"; "/dev/sda"; "mbr"];
1564 ["mkfs"; "ext2"; "/dev/sda1"];
1565 ["mount_options"; ""; "/dev/sda1"; "/"];
1568 "unmount a filesystem",
1570 This unmounts the given filesystem. The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1574 ("mounts", (RStringList "devices", []), 46, [],
1575 [InitBasicFS, Always, TestOutputListOfDevices (
1576 [["mounts"]], ["/dev/sda1"])],
1577 "show mounted filesystems",
1579 This returns the list of currently mounted filesystems. It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582 Some internal mounts are not shown.
1584 See also: C<guestfs_mountpoints>");
1586 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587 [InitBasicFS, Always, TestOutputList (
1590 (* check that umount_all can unmount nested mounts correctly: *)
1591 InitEmpty, Always, TestOutputList (
1592 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593 ["mkfs"; "ext2"; "/dev/sda1"];
1594 ["mkfs"; "ext2"; "/dev/sda2"];
1595 ["mkfs"; "ext2"; "/dev/sda3"];
1596 ["mount_options"; ""; "/dev/sda1"; "/"];
1598 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599 ["mkdir"; "/mp1/mp2"];
1600 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601 ["mkdir"; "/mp1/mp2/mp3"];
1604 "unmount all filesystems",
1606 This unmounts all mounted filesystems.
1608 Some internal mounts are not unmounted by this call.");
1610 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612 "remove all LVM LVs, VGs and PVs",
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1617 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618 [InitISOFS, Always, TestOutput (
1619 [["file"; "/empty"]], "empty");
1620 InitISOFS, Always, TestOutput (
1621 [["file"; "/known-1"]], "ASCII text");
1622 InitISOFS, Always, TestLastFail (
1623 [["file"; "/notexists"]])],
1624 "determine file type",
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file. This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1630 This call will also transparently look inside various types
1633 The exact command which runs is C<file -zbsL path>. Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1637 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638 [InitBasicFS, Always, TestOutput (
1639 [["upload"; "test-command"; "/test-command"];
1640 ["chmod"; "0o755"; "/test-command"];
1641 ["command"; "/test-command 1"]], "Result1");
1642 InitBasicFS, Always, TestOutput (
1643 [["upload"; "test-command"; "/test-command"];
1644 ["chmod"; "0o755"; "/test-command"];
1645 ["command"; "/test-command 2"]], "Result2\n");
1646 InitBasicFS, Always, TestOutput (
1647 [["upload"; "test-command"; "/test-command"];
1648 ["chmod"; "0o755"; "/test-command"];
1649 ["command"; "/test-command 3"]], "\nResult3");
1650 InitBasicFS, Always, TestOutput (
1651 [["upload"; "test-command"; "/test-command"];
1652 ["chmod"; "0o755"; "/test-command"];
1653 ["command"; "/test-command 4"]], "\nResult4\n");
1654 InitBasicFS, Always, TestOutput (
1655 [["upload"; "test-command"; "/test-command"];
1656 ["chmod"; "0o755"; "/test-command"];
1657 ["command"; "/test-command 5"]], "\nResult5\n\n");
1658 InitBasicFS, Always, TestOutput (
1659 [["upload"; "test-command"; "/test-command"];
1660 ["chmod"; "0o755"; "/test-command"];
1661 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662 InitBasicFS, Always, TestOutput (
1663 [["upload"; "test-command"; "/test-command"];
1664 ["chmod"; "0o755"; "/test-command"];
1665 ["command"; "/test-command 7"]], "");
1666 InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 8"]], "\n");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 9"]], "\n\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682 InitBasicFS, Always, TestLastFail (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command"]])],
1686 "run a command from the guest filesystem",
1688 This call runs a command from the guest filesystem. The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters. The list must be
1696 non-empty (ie. must contain a program name). Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1700 The return value is anything printed to I<stdout> by
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message. The error message
1705 string is the content of I<stderr> from the command.
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>. If you require a program from
1709 another location, you should provide the full path in the
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places. It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1718 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719 [InitBasicFS, Always, TestOutputList (
1720 [["upload"; "test-command"; "/test-command"];
1721 ["chmod"; "0o755"; "/test-command"];
1722 ["command_lines"; "/test-command 1"]], ["Result1"]);
1723 InitBasicFS, Always, TestOutputList (
1724 [["upload"; "test-command"; "/test-command"];
1725 ["chmod"; "0o755"; "/test-command"];
1726 ["command_lines"; "/test-command 2"]], ["Result2"]);
1727 InitBasicFS, Always, TestOutputList (
1728 [["upload"; "test-command"; "/test-command"];
1729 ["chmod"; "0o755"; "/test-command"];
1730 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731 InitBasicFS, Always, TestOutputList (
1732 [["upload"; "test-command"; "/test-command"];
1733 ["chmod"; "0o755"; "/test-command"];
1734 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735 InitBasicFS, Always, TestOutputList (
1736 [["upload"; "test-command"; "/test-command"];
1737 ["chmod"; "0o755"; "/test-command"];
1738 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739 InitBasicFS, Always, TestOutputList (
1740 [["upload"; "test-command"; "/test-command"];
1741 ["chmod"; "0o755"; "/test-command"];
1742 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743 InitBasicFS, Always, TestOutputList (
1744 [["upload"; "test-command"; "/test-command"];
1745 ["chmod"; "0o755"; "/test-command"];
1746 ["command_lines"; "/test-command 7"]], []);
1747 InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 8"]], [""]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 9"]], ["";""]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763 "run a command, returning lines",
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1768 See also: C<guestfs_sh_lines>");
1770 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771 [InitISOFS, Always, TestOutputStruct (
1772 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773 "get file information",
1775 Returns file information for the given C<path>.
1777 This is the same as the C<stat(2)> system call.");
1779 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780 [InitISOFS, Always, TestOutputStruct (
1781 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782 "get file information for a symbolic link",
1784 Returns file information for the given C<path>.
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1790 This is the same as the C<lstat(2)> system call.");
1792 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795 "get file system statistics",
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1801 This is the same as the C<statvfs(2)> system call.");
1803 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805 "get ext2/ext3/ext4 superblock details",
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1810 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1811 manpage for more details. The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1815 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816 [InitEmpty, Always, TestOutputTrue (
1817 [["blockdev_setro"; "/dev/sda"];
1818 ["blockdev_getro"; "/dev/sda"]])],
1819 "set block device to read-only",
1821 Sets the block device named C<device> to read-only.
1823 This uses the L<blockdev(8)> command.");
1825 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826 [InitEmpty, Always, TestOutputFalse (
1827 [["blockdev_setrw"; "/dev/sda"];
1828 ["blockdev_getro"; "/dev/sda"]])],
1829 "set block device to read-write",
1831 Sets the block device named C<device> to read-write.
1833 This uses the L<blockdev(8)> command.");
1835 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836 [InitEmpty, Always, TestOutputTrue (
1837 [["blockdev_setro"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "is block device set to read-only",
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1844 This uses the L<blockdev(8)> command.");
1846 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847 [InitEmpty, Always, TestOutputInt (
1848 [["blockdev_getss"; "/dev/sda"]], 512)],
1849 "get sectorsize of block device",
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862 "get blocksize of block device",
1864 This returns the block size of a device.
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1869 This uses the L<blockdev(8)> command.");
1871 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873 "set blocksize of block device",
1875 This sets the block size of a device.
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883 [InitEmpty, Always, TestOutputInt (
1884 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885 "get total size of device in 512-byte sectors",
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1894 This uses the L<blockdev(8)> command.");
1896 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897 [InitEmpty, Always, TestOutputInt (
1898 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899 "get total size of device in bytes",
1901 This returns the size of the device in bytes.
1903 See also C<guestfs_blockdev_getsz>.
1905 This uses the L<blockdev(8)> command.");
1907 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908 [InitEmpty, Always, TestRun
1909 [["blockdev_flushbufs"; "/dev/sda"]]],
1910 "flush device buffers",
1912 This tells the kernel to flush internal buffers associated
1915 This uses the L<blockdev(8)> command.");
1917 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918 [InitEmpty, Always, TestRun
1919 [["blockdev_rereadpt"; "/dev/sda"]]],
1920 "reread partition table",
1922 Reread the partition table on C<device>.
1924 This uses the L<blockdev(8)> command.");
1926 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927 [InitBasicFS, Always, TestOutput (
1928 (* Pick a file from cwd which isn't likely to change. *)
1929 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930 ["checksum"; "md5"; "/COPYING.LIB"]],
1931 Digest.to_hex (Digest.file "COPYING.LIB"))],
1932 "upload a file from the local machine",
1934 Upload local file C<filename> to C<remotefilename> on the
1937 C<filename> can also be a named pipe.
1939 See also C<guestfs_download>.");
1941 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942 [InitBasicFS, Always, TestOutput (
1943 (* Pick a file from cwd which isn't likely to change. *)
1944 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946 ["upload"; "testdownload.tmp"; "/upload"];
1947 ["checksum"; "md5"; "/upload"]],
1948 Digest.to_hex (Digest.file "COPYING.LIB"))],
1949 "download a file to the local machine",
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1954 C<filename> can also be a named pipe.
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1958 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959 [InitISOFS, Always, TestOutput (
1960 [["checksum"; "crc"; "/known-3"]], "2891671662");
1961 InitISOFS, Always, TestLastFail (
1962 [["checksum"; "crc"; "/notexists"]]);
1963 InitISOFS, Always, TestOutput (
1964 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965 InitISOFS, Always, TestOutput (
1966 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967 InitISOFS, Always, TestOutput (
1968 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969 InitISOFS, Always, TestOutput (
1970 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971 InitISOFS, Always, TestOutput (
1972 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973 InitISOFS, Always, TestOutput (
1974 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1975 "compute MD5, SHAx or CRC checksum of file",
1977 This call computes the MD5, SHAx or CRC checksum of the
1980 The type of checksum to compute is given by the C<csumtype>
1981 parameter which must have one of the following values:
1987 Compute the cyclic redundancy check (CRC) specified by POSIX
1988 for the C<cksum> command.
1992 Compute the MD5 hash (using the C<md5sum> program).
1996 Compute the SHA1 hash (using the C<sha1sum> program).
2000 Compute the SHA224 hash (using the C<sha224sum> program).
2004 Compute the SHA256 hash (using the C<sha256sum> program).
2008 Compute the SHA384 hash (using the C<sha384sum> program).
2012 Compute the SHA512 hash (using the C<sha512sum> program).
2016 The checksum is returned as a printable string.");
2018 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2019 [InitBasicFS, Always, TestOutput (
2020 [["tar_in"; "../images/helloworld.tar"; "/"];
2021 ["cat"; "/hello"]], "hello\n")],
2022 "unpack tarfile to directory",
2024 This command uploads and unpacks local file C<tarfile> (an
2025 I<uncompressed> tar file) into C<directory>.
2027 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2029 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031 "pack directory into tarfile",
2033 This command packs the contents of C<directory> and downloads
2034 it to local file C<tarfile>.
2036 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2039 [InitBasicFS, Always, TestOutput (
2040 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2041 ["cat"; "/hello"]], "hello\n")],
2042 "unpack compressed tarball to directory",
2044 This command uploads and unpacks local file C<tarball> (a
2045 I<gzip compressed> tar file) into C<directory>.
2047 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051 "pack directory into compressed tarball",
2053 This command packs the contents of C<directory> and downloads
2054 it to local file C<tarball>.
2056 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2059 [InitBasicFS, Always, TestLastFail (
2061 ["mount_ro"; "/dev/sda1"; "/"];
2062 ["touch"; "/new"]]);
2063 InitBasicFS, Always, TestOutput (
2064 [["write_file"; "/new"; "data"; "0"];
2066 ["mount_ro"; "/dev/sda1"; "/"];
2067 ["cat"; "/new"]], "data")],
2068 "mount a guest disk, read-only",
2070 This is the same as the C<guestfs_mount> command, but it
2071 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075 "mount a guest disk with mount options",
2077 This is the same as the C<guestfs_mount> command, but it
2078 allows you to set the mount options as for the
2079 L<mount(8)> I<-o> flag.");
2081 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083 "mount a guest disk with mount options and vfstype",
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set both the mount options and the vfstype
2087 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091 "debugging and internals",
2093 The C<guestfs_debug> command exposes some internals of
2094 C<guestfsd> (the guestfs daemon) that runs inside the
2097 There is no comprehensive help for this command. You have
2098 to look at the file C<daemon/debug.c> in the libguestfs source
2099 to find out what you can do.");
2101 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2102 [InitEmpty, Always, TestOutputList (
2103 [["part_disk"; "/dev/sda"; "mbr"];
2104 ["pvcreate"; "/dev/sda1"];
2105 ["vgcreate"; "VG"; "/dev/sda1"];
2106 ["lvcreate"; "LV1"; "VG"; "50"];
2107 ["lvcreate"; "LV2"; "VG"; "50"];
2108 ["lvremove"; "/dev/VG/LV1"];
2109 ["lvs"]], ["/dev/VG/LV2"]);
2110 InitEmpty, Always, TestOutputList (
2111 [["part_disk"; "/dev/sda"; "mbr"];
2112 ["pvcreate"; "/dev/sda1"];
2113 ["vgcreate"; "VG"; "/dev/sda1"];
2114 ["lvcreate"; "LV1"; "VG"; "50"];
2115 ["lvcreate"; "LV2"; "VG"; "50"];
2116 ["lvremove"; "/dev/VG"];
2118 InitEmpty, Always, TestOutputList (
2119 [["part_disk"; "/dev/sda"; "mbr"];
2120 ["pvcreate"; "/dev/sda1"];
2121 ["vgcreate"; "VG"; "/dev/sda1"];
2122 ["lvcreate"; "LV1"; "VG"; "50"];
2123 ["lvcreate"; "LV2"; "VG"; "50"];
2124 ["lvremove"; "/dev/VG"];
2126 "remove an LVM logical volume",
2128 Remove an LVM logical volume C<device>, where C<device> is
2129 the path to the LV, such as C</dev/VG/LV>.
2131 You can also remove all LVs in a volume group by specifying
2132 the VG name, C</dev/VG>.");
2134 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2135 [InitEmpty, Always, TestOutputList (
2136 [["part_disk"; "/dev/sda"; "mbr"];
2137 ["pvcreate"; "/dev/sda1"];
2138 ["vgcreate"; "VG"; "/dev/sda1"];
2139 ["lvcreate"; "LV1"; "VG"; "50"];
2140 ["lvcreate"; "LV2"; "VG"; "50"];
2143 InitEmpty, Always, TestOutputList (
2144 [["part_disk"; "/dev/sda"; "mbr"];
2145 ["pvcreate"; "/dev/sda1"];
2146 ["vgcreate"; "VG"; "/dev/sda1"];
2147 ["lvcreate"; "LV1"; "VG"; "50"];
2148 ["lvcreate"; "LV2"; "VG"; "50"];
2151 "remove an LVM volume group",
2153 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155 This also forcibly removes all logical volumes in the volume
2158 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2159 [InitEmpty, Always, TestOutputListOfDevices (
2160 [["part_disk"; "/dev/sda"; "mbr"];
2161 ["pvcreate"; "/dev/sda1"];
2162 ["vgcreate"; "VG"; "/dev/sda1"];
2163 ["lvcreate"; "LV1"; "VG"; "50"];
2164 ["lvcreate"; "LV2"; "VG"; "50"];
2166 ["pvremove"; "/dev/sda1"];
2168 InitEmpty, Always, TestOutputListOfDevices (
2169 [["part_disk"; "/dev/sda"; "mbr"];
2170 ["pvcreate"; "/dev/sda1"];
2171 ["vgcreate"; "VG"; "/dev/sda1"];
2172 ["lvcreate"; "LV1"; "VG"; "50"];
2173 ["lvcreate"; "LV2"; "VG"; "50"];
2175 ["pvremove"; "/dev/sda1"];
2177 InitEmpty, Always, TestOutputListOfDevices (
2178 [["part_disk"; "/dev/sda"; "mbr"];
2179 ["pvcreate"; "/dev/sda1"];
2180 ["vgcreate"; "VG"; "/dev/sda1"];
2181 ["lvcreate"; "LV1"; "VG"; "50"];
2182 ["lvcreate"; "LV2"; "VG"; "50"];
2184 ["pvremove"; "/dev/sda1"];
2186 "remove an LVM physical volume",
2188 This wipes a physical volume C<device> so that LVM will no longer
2191 The implementation uses the C<pvremove> command which refuses to
2192 wipe physical volumes that contain any volume groups, so you have
2193 to remove those first.");
2195 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2196 [InitBasicFS, Always, TestOutput (
2197 [["set_e2label"; "/dev/sda1"; "testlabel"];
2198 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2199 "set the ext2/3/4 filesystem label",
2201 This sets the ext2/3/4 filesystem label of the filesystem on
2202 C<device> to C<label>. Filesystem labels are limited to
2205 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2206 to return the existing label on a filesystem.");
2208 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210 "get the ext2/3/4 filesystem label",
2212 This returns the ext2/3/4 filesystem label of the filesystem on
2215 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2216 (let uuid = uuidgen () in
2217 [InitBasicFS, Always, TestOutput (
2218 [["set_e2uuid"; "/dev/sda1"; uuid];
2219 ["get_e2uuid"; "/dev/sda1"]], uuid);
2220 InitBasicFS, Always, TestOutput (
2221 [["set_e2uuid"; "/dev/sda1"; "clear"];
2222 ["get_e2uuid"; "/dev/sda1"]], "");
2223 (* We can't predict what UUIDs will be, so just check the commands run. *)
2224 InitBasicFS, Always, TestRun (
2225 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2226 InitBasicFS, Always, TestRun (
2227 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2228 "set the ext2/3/4 filesystem UUID",
2230 This sets the ext2/3/4 filesystem UUID of the filesystem on
2231 C<device> to C<uuid>. The format of the UUID and alternatives
2232 such as C<clear>, C<random> and C<time> are described in the
2233 L<tune2fs(8)> manpage.
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2236 to return the existing UUID of a filesystem.");
2238 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240 "get the ext2/3/4 filesystem UUID",
2242 This returns the ext2/3/4 filesystem UUID of the filesystem on
2245 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2246 [InitBasicFS, Always, TestOutputInt (
2247 [["umount"; "/dev/sda1"];
2248 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2249 InitBasicFS, Always, TestOutputInt (
2250 [["umount"; "/dev/sda1"];
2251 ["zero"; "/dev/sda1"];
2252 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2253 "run the filesystem checker",
2255 This runs the filesystem checker (fsck) on C<device> which
2256 should have filesystem type C<fstype>.
2258 The returned integer is the status. See L<fsck(8)> for the
2259 list of status codes from C<fsck>.
2267 Multiple status codes can be summed together.
2271 A non-zero return code can mean \"success\", for example if
2272 errors have been corrected on the filesystem.
2276 Checking or repairing NTFS volumes is not supported
2281 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283 ("zero", (RErr, [Device "device"]), 85, [],
2284 [InitBasicFS, Always, TestOutput (
2285 [["umount"; "/dev/sda1"];
2286 ["zero"; "/dev/sda1"];
2287 ["file"; "/dev/sda1"]], "data")],
2288 "write zeroes to the device",
2290 This command writes zeroes over the first few blocks of C<device>.
2292 How many blocks are zeroed isn't specified (but it's I<not> enough
2293 to securely wipe the device). It should be sufficient to remove
2294 any partition tables, filesystem superblocks and so on.
2296 See also: C<guestfs_scrub_device>.");
2298 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2299 (* Test disabled because grub-install incompatible with virtio-blk driver.
2300 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302 [InitBasicFS, Disabled, TestOutputTrue (
2303 [["grub_install"; "/"; "/dev/sda1"];
2304 ["is_dir"; "/boot"]])],
2307 This command installs GRUB (the Grand Unified Bootloader) on
2308 C<device>, with the root directory being C<root>.");
2310 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2311 [InitBasicFS, Always, TestOutput (
2312 [["write_file"; "/old"; "file content"; "0"];
2313 ["cp"; "/old"; "/new"];
2314 ["cat"; "/new"]], "file content");
2315 InitBasicFS, Always, TestOutputTrue (
2316 [["write_file"; "/old"; "file content"; "0"];
2317 ["cp"; "/old"; "/new"];
2318 ["is_file"; "/old"]]);
2319 InitBasicFS, Always, TestOutput (
2320 [["write_file"; "/old"; "file content"; "0"];
2322 ["cp"; "/old"; "/dir/new"];
2323 ["cat"; "/dir/new"]], "file content")],
2326 This copies a file from C<src> to C<dest> where C<dest> is
2327 either a destination filename or destination directory.");
2329 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2330 [InitBasicFS, Always, TestOutput (
2331 [["mkdir"; "/olddir"];
2332 ["mkdir"; "/newdir"];
2333 ["write_file"; "/olddir/file"; "file content"; "0"];
2334 ["cp_a"; "/olddir"; "/newdir"];
2335 ["cat"; "/newdir/olddir/file"]], "file content")],
2336 "copy a file or directory recursively",
2338 This copies a file or directory from C<src> to C<dest>
2339 recursively using the C<cp -a> command.");
2341 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2342 [InitBasicFS, Always, TestOutput (
2343 [["write_file"; "/old"; "file content"; "0"];
2344 ["mv"; "/old"; "/new"];
2345 ["cat"; "/new"]], "file content");
2346 InitBasicFS, Always, TestOutputFalse (
2347 [["write_file"; "/old"; "file content"; "0"];
2348 ["mv"; "/old"; "/new"];
2349 ["is_file"; "/old"]])],
2352 This moves a file from C<src> to C<dest> where C<dest> is
2353 either a destination filename or destination directory.");
2355 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2356 [InitEmpty, Always, TestRun (
2357 [["drop_caches"; "3"]])],
2358 "drop kernel page cache, dentries and inodes",
2360 This instructs the guest kernel to drop its page cache,
2361 and/or dentries and inode caches. The parameter C<whattodrop>
2362 tells the kernel what precisely to drop, see
2363 L<http://linux-mm.org/Drop_Caches>
2365 Setting C<whattodrop> to 3 should drop everything.
2367 This automatically calls L<sync(2)> before the operation,
2368 so that the maximum guest memory is freed.");
2370 ("dmesg", (RString "kmsgs", []), 91, [],
2371 [InitEmpty, Always, TestRun (
2373 "return kernel messages",
2375 This returns the kernel messages (C<dmesg> output) from
2376 the guest kernel. This is sometimes useful for extended
2377 debugging of problems.
2379 Another way to get the same information is to enable
2380 verbose messages with C<guestfs_set_verbose> or by setting
2381 the environment variable C<LIBGUESTFS_DEBUG=1> before
2382 running the program.");
2384 ("ping_daemon", (RErr, []), 92, [],
2385 [InitEmpty, Always, TestRun (
2386 [["ping_daemon"]])],
2387 "ping the guest daemon",
2389 This is a test probe into the guestfs daemon running inside
2390 the qemu subprocess. Calling this function checks that the
2391 daemon responds to the ping message, without affecting the daemon
2392 or attached block device(s) in any other way.");
2394 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2395 [InitBasicFS, Always, TestOutputTrue (
2396 [["write_file"; "/file1"; "contents of a file"; "0"];
2397 ["cp"; "/file1"; "/file2"];
2398 ["equal"; "/file1"; "/file2"]]);
2399 InitBasicFS, Always, TestOutputFalse (
2400 [["write_file"; "/file1"; "contents of a file"; "0"];
2401 ["write_file"; "/file2"; "contents of another file"; "0"];
2402 ["equal"; "/file1"; "/file2"]]);
2403 InitBasicFS, Always, TestLastFail (
2404 [["equal"; "/file1"; "/file2"]])],
2405 "test if two files have equal contents",
2407 This compares the two files C<file1> and C<file2> and returns
2408 true if their content is exactly equal, or false otherwise.
2410 The external L<cmp(1)> program is used for the comparison.");
2412 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2413 [InitISOFS, Always, TestOutputList (
2414 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2415 InitISOFS, Always, TestOutputList (
2416 [["strings"; "/empty"]], [])],
2417 "print the printable strings in a file",
2419 This runs the L<strings(1)> command on a file and returns
2420 the list of printable strings found.");
2422 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2423 [InitISOFS, Always, TestOutputList (
2424 [["strings_e"; "b"; "/known-5"]], []);
2425 InitBasicFS, Disabled, TestOutputList (
2426 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2427 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2428 "print the printable strings in a file",
2430 This is like the C<guestfs_strings> command, but allows you to
2431 specify the encoding.
2433 See the L<strings(1)> manpage for the full list of encodings.
2435 Commonly useful encodings are C<l> (lower case L) which will
2436 show strings inside Windows/x86 files.
2438 The returned strings are transcoded to UTF-8.");
2440 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2441 [InitISOFS, Always, TestOutput (
2442 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2443 (* Test for RHBZ#501888c2 regression which caused large hexdump
2444 * commands to segfault.
2446 InitISOFS, Always, TestRun (
2447 [["hexdump"; "/100krandom"]])],
2448 "dump a file in hexadecimal",
2450 This runs C<hexdump -C> on the given C<path>. The result is
2451 the human-readable, canonical hex dump of the file.");
2453 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2454 [InitNone, Always, TestOutput (
2455 [["part_disk"; "/dev/sda"; "mbr"];
2456 ["mkfs"; "ext3"; "/dev/sda1"];
2457 ["mount_options"; ""; "/dev/sda1"; "/"];
2458 ["write_file"; "/new"; "test file"; "0"];
2459 ["umount"; "/dev/sda1"];
2460 ["zerofree"; "/dev/sda1"];
2461 ["mount_options"; ""; "/dev/sda1"; "/"];
2462 ["cat"; "/new"]], "test file")],
2463 "zero unused inodes and disk blocks on ext2/3 filesystem",
2465 This runs the I<zerofree> program on C<device>. This program
2466 claims to zero unused inodes and disk blocks on an ext2/3
2467 filesystem, thus making it possible to compress the filesystem
2470 You should B<not> run this program if the filesystem is
2473 It is possible that using this program can damage the filesystem
2474 or data on the filesystem.");
2476 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478 "resize an LVM physical volume",
2480 This resizes (expands or shrinks) an existing LVM physical
2481 volume to match the new size of the underlying device.");
2483 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2484 Int "cyls"; Int "heads"; Int "sectors";
2485 String "line"]), 99, [DangerWillRobinson],
2487 "modify a single partition on a block device",
2489 This runs L<sfdisk(8)> option to modify just the single
2490 partition C<n> (note: C<n> counts from 1).
2492 For other parameters, see C<guestfs_sfdisk>. You should usually
2493 pass C<0> for the cyls/heads/sectors parameters.
2495 See also: C<guestfs_part_add>");
2497 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499 "display the partition table",
2501 This displays the partition table on C<device>, in the
2502 human-readable output of the L<sfdisk(8)> command. It is
2503 not intended to be parsed.
2505 See also: C<guestfs_part_list>");
2507 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509 "display the kernel geometry",
2511 This displays the kernel's idea of the geometry of C<device>.
2513 The result is in human-readable format, and not designed to
2516 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518 "display the disk geometry from the partition table",
2520 This displays the disk geometry of C<device> read from the
2521 partition table. Especially in the case where the underlying
2522 block device has been resized, this can be different from the
2523 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525 The result is in human-readable format, and not designed to
2528 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530 "activate or deactivate all volume groups",
2532 This command activates or (if C<activate> is false) deactivates
2533 all logical volumes in all volume groups.
2534 If activated, then they are made known to the
2535 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2536 then those devices disappear.
2538 This command is the same as running C<vgchange -a y|n>");
2540 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542 "activate or deactivate some volume groups",
2544 This command activates or (if C<activate> is false) deactivates
2545 all logical volumes in the listed volume groups C<volgroups>.
2546 If activated, then they are made known to the
2547 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2548 then those devices disappear.
2550 This command is the same as running C<vgchange -a y|n volgroups...>
2552 Note that if C<volgroups> is an empty list then B<all> volume groups
2553 are activated or deactivated.");
2555 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2556 [InitNone, Always, TestOutput (
2557 [["part_disk"; "/dev/sda"; "mbr"];
2558 ["pvcreate"; "/dev/sda1"];
2559 ["vgcreate"; "VG"; "/dev/sda1"];
2560 ["lvcreate"; "LV"; "VG"; "10"];
2561 ["mkfs"; "ext2"; "/dev/VG/LV"];
2562 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2563 ["write_file"; "/new"; "test content"; "0"];
2565 ["lvresize"; "/dev/VG/LV"; "20"];
2566 ["e2fsck_f"; "/dev/VG/LV"];
2567 ["resize2fs"; "/dev/VG/LV"];
2568 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2569 ["cat"; "/new"]], "test content")],
2570 "resize an LVM logical volume",
2572 This resizes (expands or shrinks) an existing LVM logical
2573 volume to C<mbytes>. When reducing, data in the reduced part
2576 ("resize2fs", (RErr, [Device "device"]), 106, [],
2577 [], (* lvresize tests this *)
2578 "resize an ext2/ext3 filesystem",
2580 This resizes an ext2 or ext3 filesystem to match the size of
2581 the underlying device.
2583 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2584 on the C<device> before calling this command. For unknown reasons
2585 C<resize2fs> sometimes gives an error about this and sometimes not.
2586 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2587 calling this function.");
2589 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2590 [InitBasicFS, Always, TestOutputList (
2591 [["find"; "/"]], ["lost+found"]);
2592 InitBasicFS, Always, TestOutputList (
2596 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2597 InitBasicFS, Always, TestOutputList (
2598 [["mkdir_p"; "/a/b/c"];
2599 ["touch"; "/a/b/c/d"];
2600 ["find"; "/a/b/"]], ["c"; "c/d"])],
2601 "find all files and directories",
2603 This command lists out all files and directories, recursively,
2604 starting at C<directory>. It is essentially equivalent to
2605 running the shell command C<find directory -print> but some
2606 post-processing happens on the output, described below.
2608 This returns a list of strings I<without any prefix>. Thus
2609 if the directory structure was:
2615 then the returned list from C<guestfs_find> C</tmp> would be
2623 If C<directory> is not a directory, then this command returns
2626 The returned list is sorted.
2628 See also C<guestfs_find0>.");
2630 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2631 [], (* lvresize tests this *)
2632 "check an ext2/ext3 filesystem",
2634 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2635 filesystem checker on C<device>, noninteractively (C<-p>),
2636 even if the filesystem appears to be clean (C<-f>).
2638 This command is only needed because of C<guestfs_resize2fs>
2639 (q.v.). Normally you should use C<guestfs_fsck>.");
2641 ("sleep", (RErr, [Int "secs"]), 109, [],
2642 [InitNone, Always, TestRun (
2644 "sleep for some seconds",
2646 Sleep for C<secs> seconds.");
2648 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2649 [InitNone, Always, TestOutputInt (
2650 [["part_disk"; "/dev/sda"; "mbr"];
2651 ["mkfs"; "ntfs"; "/dev/sda1"];
2652 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2653 InitNone, Always, TestOutputInt (
2654 [["part_disk"; "/dev/sda"; "mbr"];
2655 ["mkfs"; "ext2"; "/dev/sda1"];
2656 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2657 "probe NTFS volume",
2659 This command runs the L<ntfs-3g.probe(8)> command which probes
2660 an NTFS C<device> for mountability. (Not all NTFS volumes can
2661 be mounted read-write, and some cannot be mounted at all).
2663 C<rw> is a boolean flag. Set it to true if you want to test
2664 if the volume can be mounted read-write. Set it to false if
2665 you want to test if the volume can be mounted read-only.
2667 The return value is an integer which C<0> if the operation
2668 would succeed, or some non-zero value documented in the
2669 L<ntfs-3g.probe(8)> manual page.");
2671 ("sh", (RString "output", [String "command"]), 111, [],
2672 [], (* XXX needs tests *)
2673 "run a command via the shell",
2675 This call runs a command from the guest filesystem via the
2678 This is like C<guestfs_command>, but passes the command to:
2680 /bin/sh -c \"command\"
2682 Depending on the guest's shell, this usually results in
2683 wildcards being expanded, shell expressions being interpolated
2686 All the provisos about C<guestfs_command> apply to this call.");
2688 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2689 [], (* XXX needs tests *)
2690 "run a command via the shell returning lines",
2692 This is the same as C<guestfs_sh>, but splits the result
2693 into a list of lines.
2695 See also: C<guestfs_command_lines>");
2697 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2698 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2699 * code in stubs.c, since all valid glob patterns must start with "/".
2700 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702 [InitBasicFS, Always, TestOutputList (
2703 [["mkdir_p"; "/a/b/c"];
2704 ["touch"; "/a/b/c/d"];
2705 ["touch"; "/a/b/c/e"];
2706 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2707 InitBasicFS, Always, TestOutputList (
2708 [["mkdir_p"; "/a/b/c"];
2709 ["touch"; "/a/b/c/d"];
2710 ["touch"; "/a/b/c/e"];
2711 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2712 InitBasicFS, Always, TestOutputList (
2713 [["mkdir_p"; "/a/b/c"];
2714 ["touch"; "/a/b/c/d"];
2715 ["touch"; "/a/b/c/e"];
2716 ["glob_expand"; "/a/*/x/*"]], [])],
2717 "expand a wildcard path",
2719 This command searches for all the pathnames matching
2720 C<pattern> according to the wildcard expansion rules
2723 If no paths match, then this returns an empty list
2724 (note: not an error).
2726 It is just a wrapper around the C L<glob(3)> function
2727 with flags C<GLOB_MARK|GLOB_BRACE>.
2728 See that manual page for more details.");
2730 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2731 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2732 [["scrub_device"; "/dev/sdc"]])],
2733 "scrub (securely wipe) a device",
2735 This command writes patterns over C<device> to make data retrieval
2738 It is an interface to the L<scrub(1)> program. See that
2739 manual page for more details.");
2741 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2742 [InitBasicFS, Always, TestRun (
2743 [["write_file"; "/file"; "content"; "0"];
2744 ["scrub_file"; "/file"]])],
2745 "scrub (securely wipe) a file",
2747 This command writes patterns over a file to make data retrieval
2750 The file is I<removed> after scrubbing.
2752 It is an interface to the L<scrub(1)> program. See that
2753 manual page for more details.");
2755 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2756 [], (* XXX needs testing *)
2757 "scrub (securely wipe) free space",
2759 This command creates the directory C<dir> and then fills it
2760 with files until the filesystem is full, and scrubs the files
2761 as for C<guestfs_scrub_file>, and deletes them.
2762 The intention is to scrub any free space on the partition
2765 It is an interface to the L<scrub(1)> program. See that
2766 manual page for more details.");
2768 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2769 [InitBasicFS, Always, TestRun (
2771 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2772 "create a temporary directory",
2774 This command creates a temporary directory. The
2775 C<template> parameter should be a full pathname for the
2776 temporary directory name with the final six characters being
2779 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2780 the second one being suitable for Windows filesystems.
2782 The name of the temporary directory that was created
2785 The temporary directory is created with mode 0700
2786 and is owned by root.
2788 The caller is responsible for deleting the temporary
2789 directory and its contents after use.
2791 See also: L<mkdtemp(3)>");
2793 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2794 [InitISOFS, Always, TestOutputInt (
2795 [["wc_l"; "/10klines"]], 10000)],
2796 "count lines in a file",
2798 This command counts the lines in a file, using the
2799 C<wc -l> external command.");
2801 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2802 [InitISOFS, Always, TestOutputInt (
2803 [["wc_w"; "/10klines"]], 10000)],
2804 "count words in a file",
2806 This command counts the words in a file, using the
2807 C<wc -w> external command.");
2809 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2810 [InitISOFS, Always, TestOutputInt (
2811 [["wc_c"; "/100kallspaces"]], 102400)],
2812 "count characters in a file",
2814 This command counts the characters in a file, using the
2815 C<wc -c> external command.");
2817 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2818 [InitISOFS, Always, TestOutputList (
2819 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2820 "return first 10 lines of a file",
2822 This command returns up to the first 10 lines of a file as
2823 a list of strings.");
2825 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2826 [InitISOFS, Always, TestOutputList (
2827 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2828 InitISOFS, Always, TestOutputList (
2829 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2830 InitISOFS, Always, TestOutputList (
2831 [["head_n"; "0"; "/10klines"]], [])],
2832 "return first N lines of a file",
2834 If the parameter C<nrlines> is a positive number, this returns the first
2835 C<nrlines> lines of the file C<path>.
2837 If the parameter C<nrlines> is a negative number, this returns lines
2838 from the file C<path>, excluding the last C<nrlines> lines.
2840 If the parameter C<nrlines> is zero, this returns an empty list.");
2842 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2843 [InitISOFS, Always, TestOutputList (
2844 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2845 "return last 10 lines of a file",
2847 This command returns up to the last 10 lines of a file as
2848 a list of strings.");
2850 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2851 [InitISOFS, Always, TestOutputList (
2852 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2853 InitISOFS, Always, TestOutputList (
2854 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2855 InitISOFS, Always, TestOutputList (
2856 [["tail_n"; "0"; "/10klines"]], [])],
2857 "return last N lines of a file",
2859 If the parameter C<nrlines> is a positive number, this returns the last
2860 C<nrlines> lines of the file C<path>.
2862 If the parameter C<nrlines> is a negative number, this returns lines
2863 from the file C<path>, starting with the C<-nrlines>th line.
2865 If the parameter C<nrlines> is zero, this returns an empty list.");
2867 ("df", (RString "output", []), 125, [],
2868 [], (* XXX Tricky to test because it depends on the exact format
2869 * of the 'df' command and other imponderables.
2871 "report file system disk space usage",
2873 This command runs the C<df> command to report disk space used.
2875 This command is mostly useful for interactive sessions. It
2876 is I<not> intended that you try to parse the output string.
2877 Use C<statvfs> from programs.");
2879 ("df_h", (RString "output", []), 126, [],
2880 [], (* XXX Tricky to test because it depends on the exact format
2881 * of the 'df' command and other imponderables.
2883 "report file system disk space usage (human readable)",
2885 This command runs the C<df -h> command to report disk space used
2886 in human-readable format.
2888 This command is mostly useful for interactive sessions. It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2892 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2893 [InitISOFS, Always, TestOutputInt (
2894 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2895 "estimate file space usage",
2897 This command runs the C<du -s> command to estimate file space
2900 C<path> can be a file or a directory. If C<path> is a directory
2901 then the estimate includes the contents of the directory and all
2902 subdirectories (recursively).
2904 The result is the estimated size in I<kilobytes>
2905 (ie. units of 1024 bytes).");
2907 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2908 [InitISOFS, Always, TestOutputList (
2909 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2910 "list files in an initrd",
2912 This command lists out files contained in an initrd.
2914 The files are listed without any initial C</> character. The
2915 files are listed in the order they appear (not necessarily
2916 alphabetical). Directory names are listed as separate items.
2918 Old Linux kernels (2.4 and earlier) used a compressed ext2
2919 filesystem as initrd. We I<only> support the newer initramfs
2920 format (compressed cpio files).");
2922 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924 "mount a file using the loop device",
2926 This command lets you mount C<file> (a filesystem image
2927 in a file) on a mount point. It is entirely equivalent to
2928 the command C<mount -o loop file mountpoint>.");
2930 ("mkswap", (RErr, [Device "device"]), 130, [],
2931 [InitEmpty, Always, TestRun (
2932 [["part_disk"; "/dev/sda"; "mbr"];
2933 ["mkswap"; "/dev/sda1"]])],
2934 "create a swap partition",
2936 Create a swap partition on C<device>.");
2938 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2939 [InitEmpty, Always, TestRun (
2940 [["part_disk"; "/dev/sda"; "mbr"];
2941 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2942 "create a swap partition with a label",
2944 Create a swap partition on C<device> with label C<label>.
2946 Note that you cannot attach a swap label to a block device
2947 (eg. C</dev/sda>), just to a partition. This appears to be
2948 a limitation of the kernel or swap tools.");
2950 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2951 (let uuid = uuidgen () in
2952 [InitEmpty, Always, TestRun (
2953 [["part_disk"; "/dev/sda"; "mbr"];
2954 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2955 "create a swap partition with an explicit UUID",
2957 Create a swap partition on C<device> with UUID C<uuid>.");
2959 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2960 [InitBasicFS, Always, TestOutputStruct (
2961 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2962 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2963 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2964 InitBasicFS, Always, TestOutputStruct (
2965 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2966 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2967 "make block, character or FIFO devices",
2969 This call creates block or character special devices, or
2970 named pipes (FIFOs).
2972 The C<mode> parameter should be the mode, using the standard
2973 constants. C<devmajor> and C<devminor> are the
2974 device major and minor numbers, only used when creating block
2975 and character special devices.");
2977 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2978 [InitBasicFS, Always, TestOutputStruct (
2979 [["mkfifo"; "0o777"; "/node"];
2980 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2981 "make FIFO (named pipe)",
2983 This call creates a FIFO (named pipe) called C<path> with
2984 mode C<mode>. It is just a convenient wrapper around
2985 C<guestfs_mknod>.");
2987 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2988 [InitBasicFS, Always, TestOutputStruct (
2989 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2990 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2991 "make block device node",
2993 This call creates a block device node called C<path> with
2994 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2995 It is just a convenient wrapper around C<guestfs_mknod>.");
2997 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2998 [InitBasicFS, Always, TestOutputStruct (
2999 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3000 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3001 "make char device node",
3003 This call creates a char device node called C<path> with
3004 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3005 It is just a convenient wrapper around C<guestfs_mknod>.");
3007 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3008 [], (* XXX umask is one of those stateful things that we should
3009 * reset between each test.
3011 "set file mode creation mask (umask)",
3013 This function sets the mask used for creating new files and
3014 device nodes to C<mask & 0777>.
3016 Typical umask values would be C<022> which creates new files
3017 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3018 C<002> which creates new files with permissions like
3019 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3021 The default umask is C<022>. This is important because it
3022 means that directories and device nodes will be created with
3023 C<0644> or C<0755> mode even if you specify C<0777>.
3025 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3027 This call returns the previous umask.");
3029 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3031 "read directories entries",
3033 This returns the list of directory entries in directory C<dir>.
3035 All entries in the directory are returned, including C<.> and
3036 C<..>. The entries are I<not> sorted, but returned in the same
3037 order as the underlying filesystem.
3039 Also this call returns basic file type information about each
3040 file. The C<ftyp> field will contain one of the following characters:
3078 The L<readdir(3)> returned a C<d_type> field with an
3083 This function is primarily intended for use by programs. To
3084 get a simple list of names, use C<guestfs_ls>. To get a printable
3085 directory for human consumption, use C<guestfs_ll>.");
3087 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3089 "create partitions on a block device",
3091 This is a simplified interface to the C<guestfs_sfdisk>
3092 command, where partition sizes are specified in megabytes
3093 only (rounded to the nearest cylinder) and you don't need
3094 to specify the cyls, heads and sectors parameters which
3095 were rarely if ever used anyway.
3097 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3098 and C<guestfs_part_disk>");
3100 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3102 "determine file type inside a compressed file",
3104 This command runs C<file> after first decompressing C<path>
3107 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3109 Since 1.0.63, use C<guestfs_file> instead which can now
3110 process compressed files.");
3112 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3114 "list extended attributes of a file or directory",
3116 This call lists the extended attributes of the file or directory
3119 At the system call level, this is a combination of the
3120 L<listxattr(2)> and L<getxattr(2)> calls.
3122 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3124 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3126 "list extended attributes of a file or directory",
3128 This is the same as C<guestfs_getxattrs>, but if C<path>
3129 is a symbolic link, then it returns the extended attributes
3130 of the link itself.");
3132 ("setxattr", (RErr, [String "xattr";
3133 String "val"; Int "vallen"; (* will be BufferIn *)
3134 Pathname "path"]), 143, [Optional "linuxxattrs"],
3136 "set extended attribute of a file or directory",
3138 This call sets the extended attribute named C<xattr>
3139 of the file C<path> to the value C<val> (of length C<vallen>).
3140 The value is arbitrary 8 bit data.
3142 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3144 ("lsetxattr", (RErr, [String "xattr";
3145 String "val"; Int "vallen"; (* will be BufferIn *)
3146 Pathname "path"]), 144, [Optional "linuxxattrs"],
3148 "set extended attribute of a file or directory",
3150 This is the same as C<guestfs_setxattr>, but if C<path>
3151 is a symbolic link, then it sets an extended attribute
3152 of the link itself.");
3154 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3156 "remove extended attribute of a file or directory",
3158 This call removes the extended attribute named C<xattr>
3159 of the file C<path>.
3161 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3163 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3165 "remove extended attribute of a file or directory",
3167 This is the same as C<guestfs_removexattr>, but if C<path>
3168 is a symbolic link, then it removes an extended attribute
3169 of the link itself.");
3171 ("mountpoints", (RHashtable "mps", []), 147, [],
3175 This call is similar to C<guestfs_mounts>. That call returns
3176 a list of devices. This one returns a hash table (map) of
3177 device name to directory where the device is mounted.");
3179 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3180 (* This is a special case: while you would expect a parameter
3181 * of type "Pathname", that doesn't work, because it implies
3182 * NEED_ROOT in the generated calling code in stubs.c, and
3183 * this function cannot use NEED_ROOT.
3186 "create a mountpoint",
3188 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3189 specialized calls that can be used to create extra mountpoints
3190 before mounting the first filesystem.
3192 These calls are I<only> necessary in some very limited circumstances,
3193 mainly the case where you want to mount a mix of unrelated and/or
3194 read-only filesystems together.
3196 For example, live CDs often contain a \"Russian doll\" nest of
3197 filesystems, an ISO outer layer, with a squashfs image inside, with
3198 an ext2/3 image inside that. You can unpack this as follows
3201 add-ro Fedora-11-i686-Live.iso
3204 mkmountpoint /squash
3207 mount-loop /cd/LiveOS/squashfs.img /squash
3208 mount-loop /squash/LiveOS/ext3fs.img /ext3
3210 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3212 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3214 "remove a mountpoint",
3216 This calls removes a mountpoint that was previously created
3217 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3218 for full details.");
3220 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3221 [InitISOFS, Always, TestOutputBuffer (
3222 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3225 This calls returns the contents of the file C<path> as a
3228 Unlike C<guestfs_cat>, this function can correctly
3229 handle files that contain embedded ASCII NUL characters.
3230 However unlike C<guestfs_download>, this function is limited
3231 in the total size of file that can be handled.");
3233 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3234 [InitISOFS, Always, TestOutputList (
3235 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3236 InitISOFS, Always, TestOutputList (
3237 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3238 "return lines matching a pattern",
3240 This calls the external C<grep> program and returns the
3243 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3244 [InitISOFS, Always, TestOutputList (
3245 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3246 "return lines matching a pattern",
3248 This calls the external C<egrep> program and returns the
3251 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3252 [InitISOFS, Always, TestOutputList (
3253 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254 "return lines matching a pattern",
3256 This calls the external C<fgrep> program and returns the
3259 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3260 [InitISOFS, Always, TestOutputList (
3261 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3262 "return lines matching a pattern",
3264 This calls the external C<grep -i> program and returns the
3267 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3268 [InitISOFS, Always, TestOutputList (
3269 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270 "return lines matching a pattern",
3272 This calls the external C<egrep -i> program and returns the
3275 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3276 [InitISOFS, Always, TestOutputList (
3277 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278 "return lines matching a pattern",
3280 This calls the external C<fgrep -i> program and returns the
3283 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3284 [InitISOFS, Always, TestOutputList (
3285 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3286 "return lines matching a pattern",
3288 This calls the external C<zgrep> program and returns the
3291 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3292 [InitISOFS, Always, TestOutputList (
3293 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294 "return lines matching a pattern",
3296 This calls the external C<zegrep> program and returns the
3299 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3300 [InitISOFS, Always, TestOutputList (
3301 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302 "return lines matching a pattern",
3304 This calls the external C<zfgrep> program and returns the
3307 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3308 [InitISOFS, Always, TestOutputList (
3309 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3310 "return lines matching a pattern",
3312 This calls the external C<zgrep -i> program and returns the
3315 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3316 [InitISOFS, Always, TestOutputList (
3317 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318 "return lines matching a pattern",
3320 This calls the external C<zegrep -i> program and returns the
3323 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3324 [InitISOFS, Always, TestOutputList (
3325 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326 "return lines matching a pattern",
3328 This calls the external C<zfgrep -i> program and returns the
3331 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3332 [InitISOFS, Always, TestOutput (
3333 [["realpath"; "/../directory"]], "/directory")],
3334 "canonicalized absolute pathname",
3336 Return the canonicalized absolute pathname of C<path>. The
3337 returned path has no C<.>, C<..> or symbolic link path elements.");
3339 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3340 [InitBasicFS, Always, TestOutputStruct (
3343 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3344 "create a hard link",
3346 This command creates a hard link using the C<ln> command.");
3348 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3349 [InitBasicFS, Always, TestOutputStruct (
3352 ["ln_f"; "/a"; "/b"];
3353 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3354 "create a hard link",
3356 This command creates a hard link using the C<ln -f> command.
3357 The C<-f> option removes the link (C<linkname>) if it exists already.");
3359 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3360 [InitBasicFS, Always, TestOutputStruct (
3362 ["ln_s"; "a"; "/b"];
3363 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3364 "create a symbolic link",
3366 This command creates a symbolic link using the C<ln -s> command.");
3368 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3369 [InitBasicFS, Always, TestOutput (
3370 [["mkdir_p"; "/a/b"];
3371 ["touch"; "/a/b/c"];
3372 ["ln_sf"; "../d"; "/a/b/c"];
3373 ["readlink"; "/a/b/c"]], "../d")],
3374 "create a symbolic link",
3376 This command creates a symbolic link using the C<ln -sf> command,
3377 The C<-f> option removes the link (C<linkname>) if it exists already.");
3379 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3380 [] (* XXX tested above *),
3381 "read the target of a symbolic link",
3383 This command reads the target of a symbolic link.");
3385 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3386 [InitBasicFS, Always, TestOutputStruct (
3387 [["fallocate"; "/a"; "1000000"];
3388 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3389 "preallocate a file in the guest filesystem",
3391 This command preallocates a file (containing zero bytes) named
3392 C<path> of size C<len> bytes. If the file exists already, it
3395 Do not confuse this with the guestfish-specific
3396 C<alloc> command which allocates a file in the host and
3397 attaches it as a device.");
3399 ("swapon_device", (RErr, [Device "device"]), 170, [],
3400 [InitPartition, Always, TestRun (
3401 [["mkswap"; "/dev/sda1"];
3402 ["swapon_device"; "/dev/sda1"];
3403 ["swapoff_device"; "/dev/sda1"]])],
3404 "enable swap on device",
3406 This command enables the libguestfs appliance to use the
3407 swap device or partition named C<device>. The increased
3408 memory is made available for all commands, for example
3409 those run using C<guestfs_command> or C<guestfs_sh>.
3411 Note that you should not swap to existing guest swap
3412 partitions unless you know what you are doing. They may
3413 contain hibernation information, or other information that
3414 the guest doesn't want you to trash. You also risk leaking
3415 information about the host to the guest this way. Instead,
3416 attach a new host device to the guest and swap on that.");
3418 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3419 [], (* XXX tested by swapon_device *)
3420 "disable swap on device",
3422 This command disables the libguestfs appliance swap
3423 device or partition named C<device>.
3424 See C<guestfs_swapon_device>.");
3426 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3427 [InitBasicFS, Always, TestRun (
3428 [["fallocate"; "/swap"; "8388608"];
3429 ["mkswap_file"; "/swap"];
3430 ["swapon_file"; "/swap"];
3431 ["swapoff_file"; "/swap"]])],
3432 "enable swap on file",
3434 This command enables swap to a file.
3435 See C<guestfs_swapon_device> for other notes.");
3437 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3438 [], (* XXX tested by swapon_file *)
3439 "disable swap on file",
3441 This command disables the libguestfs appliance swap on file.");
3443 ("swapon_label", (RErr, [String "label"]), 174, [],
3444 [InitEmpty, Always, TestRun (
3445 [["part_disk"; "/dev/sdb"; "mbr"];
3446 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3447 ["swapon_label"; "swapit"];
3448 ["swapoff_label"; "swapit"];
3449 ["zero"; "/dev/sdb"];
3450 ["blockdev_rereadpt"; "/dev/sdb"]])],
3451 "enable swap on labeled swap partition",
3453 This command enables swap to a labeled swap partition.
3454 See C<guestfs_swapon_device> for other notes.");
3456 ("swapoff_label", (RErr, [String "label"]), 175, [],
3457 [], (* XXX tested by swapon_label *)
3458 "disable swap on labeled swap partition",
3460 This command disables the libguestfs appliance swap on
3461 labeled swap partition.");
3463 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3464 (let uuid = uuidgen () in
3465 [InitEmpty, Always, TestRun (
3466 [["mkswap_U"; uuid; "/dev/sdb"];
3467 ["swapon_uuid"; uuid];
3468 ["swapoff_uuid"; uuid]])]),
3469 "enable swap on swap partition by UUID",
3471 This command enables swap to a swap partition with the given UUID.
3472 See C<guestfs_swapon_device> for other notes.");
3474 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3475 [], (* XXX tested by swapon_uuid *)
3476 "disable swap on swap partition by UUID",
3478 This command disables the libguestfs appliance swap partition
3479 with the given UUID.");
3481 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3482 [InitBasicFS, Always, TestRun (
3483 [["fallocate"; "/swap"; "8388608"];
3484 ["mkswap_file"; "/swap"]])],
3485 "create a swap file",
3489 This command just writes a swap file signature to an existing
3490 file. To create the file itself, use something like C<guestfs_fallocate>.");
3492 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3493 [InitISOFS, Always, TestRun (
3494 [["inotify_init"; "0"]])],
3495 "create an inotify handle",
3497 This command creates a new inotify handle.
3498 The inotify subsystem can be used to notify events which happen to
3499 objects in the guest filesystem.
3501 C<maxevents> is the maximum number of events which will be
3502 queued up between calls to C<guestfs_inotify_read> or
3503 C<guestfs_inotify_files>.
3504 If this is passed as C<0>, then the kernel (or previously set)
3505 default is used. For Linux 2.6.29 the default was 16384 events.
3506 Beyond this limit, the kernel throws away events, but records
3507 the fact that it threw them away by setting a flag
3508 C<IN_Q_OVERFLOW> in the returned structure list (see
3509 C<guestfs_inotify_read>).
3511 Before any events are generated, you have to add some
3512 watches to the internal watch list. See:
3513 C<guestfs_inotify_add_watch>,
3514 C<guestfs_inotify_rm_watch> and
3515 C<guestfs_inotify_watch_all>.
3517 Queued up events should be read periodically by calling
3518 C<guestfs_inotify_read>
3519 (or C<guestfs_inotify_files> which is just a helpful
3520 wrapper around C<guestfs_inotify_read>). If you don't
3521 read the events out often enough then you risk the internal
3524 The handle should be closed after use by calling
3525 C<guestfs_inotify_close>. This also removes any
3526 watches automatically.
3528 See also L<inotify(7)> for an overview of the inotify interface
3529 as exposed by the Linux kernel, which is roughly what we expose
3530 via libguestfs. Note that there is one global inotify handle
3531 per libguestfs instance.");
3533 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3534 [InitBasicFS, Always, TestOutputList (
3535 [["inotify_init"; "0"];
3536 ["inotify_add_watch"; "/"; "1073741823"];
3539 ["inotify_files"]], ["a"; "b"])],
3540 "add an inotify watch",
3542 Watch C<path> for the events listed in C<mask>.
3544 Note that if C<path> is a directory then events within that
3545 directory are watched, but this does I<not> happen recursively
3546 (in subdirectories).
3548 Note for non-C or non-Linux callers: the inotify events are
3549 defined by the Linux kernel ABI and are listed in
3550 C</usr/include/sys/inotify.h>.");
3552 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3554 "remove an inotify watch",
3556 Remove a previously defined inotify watch.
3557 See C<guestfs_inotify_add_watch>.");
3559 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3561 "return list of inotify events",
3563 Return the complete queue of events that have happened
3564 since the previous read call.
3566 If no events have happened, this returns an empty list.
3568 I<Note>: In order to make sure that all events have been
3569 read, you must call this function repeatedly until it
3570 returns an empty list. The reason is that the call will
3571 read events up to the maximum appliance-to-host message
3572 size and leave remaining events in the queue.");
3574 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3576 "return list of watched files that had events",
3578 This function is a helpful wrapper around C<guestfs_inotify_read>
3579 which just returns a list of pathnames of objects that were
3580 touched. The returned pathnames are sorted and deduplicated.");
3582 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3584 "close the inotify handle",
3586 This closes the inotify handle which was previously
3587 opened by inotify_init. It removes all watches, throws
3588 away any pending events, and deallocates all resources.");
3590 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3592 "set SELinux security context",
3594 This sets the SELinux security context of the daemon
3595 to the string C<context>.
3597 See the documentation about SELINUX in L<guestfs(3)>.");
3599 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3601 "get SELinux security context",
3603 This gets the SELinux security context of the daemon.
3605 See the documentation about SELINUX in L<guestfs(3)>,
3606 and C<guestfs_setcon>");
3608 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3609 [InitEmpty, Always, TestOutput (
3610 [["part_disk"; "/dev/sda"; "mbr"];
3611 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3612 ["mount_options"; ""; "/dev/sda1"; "/"];
3613 ["write_file"; "/new"; "new file contents"; "0"];
3614 ["cat"; "/new"]], "new file contents")],
3615 "make a filesystem with block size",
3617 This call is similar to C<guestfs_mkfs>, but it allows you to
3618 control the block size of the resulting filesystem. Supported
3619 block sizes depend on the filesystem type, but typically they
3620 are C<1024>, C<2048> or C<4096> only.");
3622 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3623 [InitEmpty, Always, TestOutput (
3624 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3625 ["mke2journal"; "4096"; "/dev/sda1"];
3626 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3627 ["mount_options"; ""; "/dev/sda2"; "/"];
3628 ["write_file"; "/new"; "new file contents"; "0"];
3629 ["cat"; "/new"]], "new file contents")],
3630 "make ext2/3/4 external journal",
3632 This creates an ext2 external journal on C<device>. It is equivalent
3635 mke2fs -O journal_dev -b blocksize device");
3637 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3638 [InitEmpty, Always, TestOutput (
3639 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3640 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3641 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3642 ["mount_options"; ""; "/dev/sda2"; "/"];
3643 ["write_file"; "/new"; "new file contents"; "0"];
3644 ["cat"; "/new"]], "new file contents")],
3645 "make ext2/3/4 external journal with label",
3647 This creates an ext2 external journal on C<device> with label C<label>.");
3649 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3650 (let uuid = uuidgen () in
3651 [InitEmpty, Always, TestOutput (
3652 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3654 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3655 ["mount_options"; ""; "/dev/sda2"; "/"];
3656 ["write_file"; "/new"; "new file contents"; "0"];
3657 ["cat"; "/new"]], "new file contents")]),
3658 "make ext2/3/4 external journal with UUID",
3660 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3662 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3664 "make ext2/3/4 filesystem with external journal",
3666 This creates an ext2/3/4 filesystem on C<device> with
3667 an external journal on C<journal>. It is equivalent
3670 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3672 See also C<guestfs_mke2journal>.");
3674 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3676 "make ext2/3/4 filesystem with external journal",
3678 This creates an ext2/3/4 filesystem on C<device> with
3679 an external journal on the journal labeled C<label>.
3681 See also C<guestfs_mke2journal_L>.");
3683 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3685 "make ext2/3/4 filesystem with external journal",
3687 This creates an ext2/3/4 filesystem on C<device> with
3688 an external journal on the journal with UUID C<uuid>.
3690 See also C<guestfs_mke2journal_U>.");
3692 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3693 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3694 "load a kernel module",
3696 This loads a kernel module in the appliance.
3698 The kernel module must have been whitelisted when libguestfs
3699 was built (see C<appliance/kmod.whitelist.in> in the source).");
3701 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3702 [InitNone, Always, TestOutput (
3703 [["echo_daemon"; "This is a test"]], "This is a test"
3705 "echo arguments back to the client",
3707 This command concatenate the list of C<words> passed with single spaces between
3708 them and returns the resulting string.
3710 You can use this command to test the connection through to the daemon.
3712 See also C<guestfs_ping_daemon>.");
3714 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3715 [], (* There is a regression test for this. *)
3716 "find all files and directories, returning NUL-separated list",
3718 This command lists out all files and directories, recursively,
3719 starting at C<directory>, placing the resulting list in the
3720 external file called C<files>.
3722 This command works the same way as C<guestfs_find> with the
3723 following exceptions:
3729 The resulting list is written to an external file.
3733 Items (filenames) in the result are separated
3734 by C<\\0> characters. See L<find(1)> option I<-print0>.
3738 This command is not limited in the number of names that it
3743 The result list is not sorted.
3747 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3748 [InitISOFS, Always, TestOutput (
3749 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3750 InitISOFS, Always, TestOutput (
3751 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3752 InitISOFS, Always, TestOutput (
3753 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3754 InitISOFS, Always, TestLastFail (
3755 [["case_sensitive_path"; "/Known-1/"]]);
3756 InitBasicFS, Always, TestOutput (
3758 ["mkdir"; "/a/bbb"];
3759 ["touch"; "/a/bbb/c"];
3760 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3761 InitBasicFS, Always, TestOutput (
3763 ["mkdir"; "/a/bbb"];
3764 ["touch"; "/a/bbb/c"];
3765 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3766 InitBasicFS, Always, TestLastFail (
3768 ["mkdir"; "/a/bbb"];
3769 ["touch"; "/a/bbb/c"];
3770 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3771 "return true path on case-insensitive filesystem",
3773 This can be used to resolve case insensitive paths on
3774 a filesystem which is case sensitive. The use case is
3775 to resolve paths which you have read from Windows configuration
3776 files or the Windows Registry, to the true path.
3778 The command handles a peculiarity of the Linux ntfs-3g
3779 filesystem driver (and probably others), which is that although
3780 the underlying filesystem is case-insensitive, the driver
3781 exports the filesystem to Linux as case-sensitive.
3783 One consequence of this is that special directories such
3784 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3785 (or other things) depending on the precise details of how
3786 they were created. In Windows itself this would not be
3789 Bug or feature? You decide:
3790 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3792 This function resolves the true case of each element in the
3793 path and returns the case-sensitive path.
3795 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3796 might return C<\"/WINDOWS/system32\"> (the exact return value
3797 would depend on details of how the directories were originally
3798 created under Windows).
3801 This function does not handle drive names, backslashes etc.
3803 See also C<guestfs_realpath>.");
3805 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3806 [InitBasicFS, Always, TestOutput (
3807 [["vfs_type"; "/dev/sda1"]], "ext2")],
3808 "get the Linux VFS type corresponding to a mounted device",
3810 This command gets the block device type corresponding to
3811 a mounted device called C<device>.
3813 Usually the result is the name of the Linux VFS module that
3814 is used to mount this device (probably determined automatically
3815 if you used the C<guestfs_mount> call).");
3817 ("truncate", (RErr, [Pathname "path"]), 199, [],
3818 [InitBasicFS, Always, TestOutputStruct (
3819 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3820 ["truncate"; "/test"];
3821 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3822 "truncate a file to zero size",
3824 This command truncates C<path> to a zero-length file. The
3825 file must exist already.");
3827 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3828 [InitBasicFS, Always, TestOutputStruct (
3829 [["touch"; "/test"];
3830 ["truncate_size"; "/test"; "1000"];
3831 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3832 "truncate a file to a particular size",
3834 This command truncates C<path> to size C<size> bytes. The file
3835 must exist already. If the file is smaller than C<size> then
3836 the file is extended to the required size with null bytes.");
3838 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3839 [InitBasicFS, Always, TestOutputStruct (
3840 [["touch"; "/test"];
3841 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3842 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3843 "set timestamp of a file with nanosecond precision",
3845 This command sets the timestamps of a file with nanosecond
3848 C<atsecs, atnsecs> are the last access time (atime) in secs and
3849 nanoseconds from the epoch.
3851 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3852 secs and nanoseconds from the epoch.
3854 If the C<*nsecs> field contains the special value C<-1> then
3855 the corresponding timestamp is set to the current time. (The
3856 C<*secs> field is ignored in this case).
3858 If the C<*nsecs> field contains the special value C<-2> then
3859 the corresponding timestamp is left unchanged. (The
3860 C<*secs> field is ignored in this case).");
3862 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3863 [InitBasicFS, Always, TestOutputStruct (
3864 [["mkdir_mode"; "/test"; "0o111"];
3865 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3866 "create a directory with a particular mode",
3868 This command creates a directory, setting the initial permissions
3869 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3871 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3873 "change file owner and group",
3875 Change the file owner to C<owner> and group to C<group>.
3876 This is like C<guestfs_chown> but if C<path> is a symlink then
3877 the link itself is changed, not the target.
3879 Only numeric uid and gid are supported. If you want to use
3880 names, you will need to locate and parse the password file
3881 yourself (Augeas support makes this relatively easy).");
3883 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3885 "lstat on multiple files",
3887 This call allows you to perform the C<guestfs_lstat> operation
3888 on multiple files, where all files are in the directory C<path>.
3889 C<names> is the list of files from this directory.
3891 On return you get a list of stat structs, with a one-to-one
3892 correspondence to the C<names> list. If any name did not exist
3893 or could not be lstat'd, then the C<ino> field of that structure
3896 This call is intended for programs that want to efficiently
3897 list a directory contents without making many round-trips.
3898 See also C<guestfs_lxattrlist> for a similarly efficient call
3899 for getting extended attributes. Very long directory listings
3900 might cause the protocol message size to be exceeded, causing
3901 this call to fail. The caller must split up such requests
3902 into smaller groups of names.");
3904 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3906 "lgetxattr on multiple files",
3908 This call allows you to get the extended attributes
3909 of multiple files, where all files are in the directory C<path>.
3910 C<names> is the list of files from this directory.
3912 On return you get a flat list of xattr structs which must be
3913 interpreted sequentially. The first xattr struct always has a zero-length
3914 C<attrname>. C<attrval> in this struct is zero-length
3915 to indicate there was an error doing C<lgetxattr> for this
3916 file, I<or> is a C string which is a decimal number
3917 (the number of following attributes for this file, which could
3918 be C<\"0\">). Then after the first xattr struct are the
3919 zero or more attributes for the first named file.
3920 This repeats for the second and subsequent files.
3922 This call is intended for programs that want to efficiently
3923 list a directory contents without making many round-trips.
3924 See also C<guestfs_lstatlist> for a similarly efficient call
3925 for getting standard stats. Very long directory listings
3926 might cause the protocol message size to be exceeded, causing
3927 this call to fail. The caller must split up such requests
3928 into smaller groups of names.");
3930 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3932 "readlink on multiple files",
3934 This call allows you to do a C<readlink> operation
3935 on multiple files, where all files are in the directory C<path>.
3936 C<names> is the list of files from this directory.
3938 On return you get a list of strings, with a one-to-one
3939 correspondence to the C<names> list. Each string is the
3940 value of the symbol link.
3942 If the C<readlink(2)> operation fails on any name, then
3943 the corresponding result string is the empty string C<\"\">.
3944 However the whole operation is completed even if there
3945 were C<readlink(2)> errors, and so you can call this
3946 function with names where you don't know if they are
3947 symbolic links already (albeit slightly less efficient).
3949 This call is intended for programs that want to efficiently
3950 list a directory contents without making many round-trips.
3951 Very long directory listings might cause the protocol
3952 message size to be exceeded, causing
3953 this call to fail. The caller must split up such requests
3954 into smaller groups of names.");
3956 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3957 [InitISOFS, Always, TestOutputBuffer (
3958 [["pread"; "/known-4"; "1"; "3"]], "\n");
3959 InitISOFS, Always, TestOutputBuffer (
3960 [["pread"; "/empty"; "0"; "100"]], "")],
3961 "read part of a file",
3963 This command lets you read part of a file. It reads C<count>
3964 bytes of the file, starting at C<offset>, from file C<path>.
3966 This may read fewer bytes than requested. For further details
3967 see the L<pread(2)> system call.");
3969 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3970 [InitEmpty, Always, TestRun (
3971 [["part_init"; "/dev/sda"; "gpt"]])],
3972 "create an empty partition table",
3974 This creates an empty partition table on C<device> of one of the
3975 partition types listed below. Usually C<parttype> should be
3976 either C<msdos> or C<gpt> (for large disks).
3978 Initially there are no partitions. Following this, you should
3979 call C<guestfs_part_add> for each partition required.
3981 Possible values for C<parttype> are:
3985 =item B<efi> | B<gpt>
3987 Intel EFI / GPT partition table.
3989 This is recommended for >= 2 TB partitions that will be accessed
3990 from Linux and Intel-based Mac OS X. It also has limited backwards
3991 compatibility with the C<mbr> format.
3993 =item B<mbr> | B<msdos>
3995 The standard PC \"Master Boot Record\" (MBR) format used
3996 by MS-DOS and Windows. This partition type will B<only> work
3997 for device sizes up to 2 TB. For large disks we recommend
4002 Other partition table types that may work but are not
4011 =item B<amiga> | B<rdb>
4013 Amiga \"Rigid Disk Block\" format.
4021 DASD, used on IBM mainframes.
4029 Old Mac partition format. Modern Macs use C<gpt>.
4033 NEC PC-98 format, common in Japan apparently.
4041 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4042 [InitEmpty, Always, TestRun (
4043 [["part_init"; "/dev/sda"; "mbr"];
4044 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4045 InitEmpty, Always, TestRun (
4046 [["part_init"; "/dev/sda"; "gpt"];
4047 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4048 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4049 InitEmpty, Always, TestRun (
4050 [["part_init"; "/dev/sda"; "mbr"];
4051 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4052 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4053 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4054 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4055 "add a partition to the device",
4057 This command adds a partition to C<device>. If there is no partition
4058 table on the device, call C<guestfs_part_init> first.
4060 The C<prlogex> parameter is the type of partition. Normally you
4061 should pass C<p> or C<primary> here, but MBR partition tables also
4062 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4065 C<startsect> and C<endsect> are the start and end of the partition
4066 in I<sectors>. C<endsect> may be negative, which means it counts
4067 backwards from the end of the disk (C<-1> is the last sector).
4069 Creating a partition which covers the whole disk is not so easy.
4070 Use C<guestfs_part_disk> to do that.");
4072 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4073 [InitEmpty, Always, TestRun (
4074 [["part_disk"; "/dev/sda"; "mbr"]]);
4075 InitEmpty, Always, TestRun (
4076 [["part_disk"; "/dev/sda"; "gpt"]])],
4077 "partition whole disk with a single primary partition",
4079 This command is simply a combination of C<guestfs_part_init>
4080 followed by C<guestfs_part_add> to create a single primary partition
4081 covering the whole disk.
4083 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4084 but other possible values are described in C<guestfs_part_init>.");
4086 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4087 [InitEmpty, Always, TestRun (
4088 [["part_disk"; "/dev/sda"; "mbr"];
4089 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4090 "make a partition bootable",
4092 This sets the bootable flag on partition numbered C<partnum> on
4093 device C<device>. Note that partitions are numbered from 1.
4095 The bootable flag is used by some PC BIOSes to determine which
4096 partition to boot from. It is by no means universally recognized,
4097 and in any case if your operating system installed a boot
4098 sector on the device itself, then that takes precedence.");
4100 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4101 [InitEmpty, Always, TestRun (
4102 [["part_disk"; "/dev/sda"; "gpt"];
4103 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4104 "set partition name",
4106 This sets the partition name on partition numbered C<partnum> on
4107 device C<device>. Note that partitions are numbered from 1.
4109 The partition name can only be set on certain types of partition
4110 table. This works on C<gpt> but not on C<mbr> partitions.");
4112 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4113 [], (* XXX Add a regression test for this. *)
4114 "list partitions on a device",
4116 This command parses the partition table on C<device> and
4117 returns the list of partitions found.
4119 The fields in the returned structure are:
4125 Partition number, counting from 1.
4129 Start of the partition I<in bytes>. To get sectors you have to
4130 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4134 End of the partition in bytes.
4138 Size of the partition in bytes.
4142 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4143 [InitEmpty, Always, TestOutput (
4144 [["part_disk"; "/dev/sda"; "gpt"];
4145 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4146 "get the partition table type",
4148 This command examines the partition table on C<device> and
4149 returns the partition table type (format) being used.
4151 Common return values include: C<msdos> (a DOS/Windows style MBR
4152 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4153 values are possible, although unusual. See C<guestfs_part_init>
4156 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4157 [InitBasicFS, Always, TestOutputBuffer (
4158 [["fill"; "0x63"; "10"; "/test"];
4159 ["read_file"; "/test"]], "cccccccccc")],
4160 "fill a file with octets",
4162 This command creates a new file called C<path>. The initial
4163 content of the file is C<len> octets of C<c>, where C<c>
4164 must be a number in the range C<[0..255]>.
4166 To fill a file with zero bytes (sparsely), it is
4167 much more efficient to use C<guestfs_truncate_size>.");
4169 ("available", (RErr, [StringList "groups"]), 216, [],
4170 [InitNone, Always, TestRun [["available"; ""]]],
4171 "test availability of some parts of the API",
4173 This command is used to check the availability of some
4174 groups of functionality in the appliance, which not all builds of
4175 the libguestfs appliance will be able to provide.
4177 The libguestfs groups, and the functions that those
4178 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4180 The argument C<groups> is a list of group names, eg:
4181 C<[\"inotify\", \"augeas\"]> would check for the availability of
4182 the Linux inotify functions and Augeas (configuration file
4185 The command returns no error if I<all> requested groups are available.
4187 It fails with an error if one or more of the requested
4188 groups is unavailable in the appliance.
4190 If an unknown group name is included in the
4191 list of groups then an error is always returned.
4199 You must call C<guestfs_launch> before calling this function.
4201 The reason is because we don't know what groups are
4202 supported by the appliance/daemon until it is running and can
4207 If a group of functions is available, this does not necessarily
4208 mean that they will work. You still have to check for errors
4209 when calling individual API functions even if they are
4214 It is usually the job of distro packagers to build
4215 complete functionality into the libguestfs appliance.
4216 Upstream libguestfs, if built from source with all
4217 requirements satisfied, will support everything.
4221 This call was added in version C<1.0.80>. In previous
4222 versions of libguestfs all you could do would be to speculatively
4223 execute a command to find out if the daemon implemented it.
4224 See also C<guestfs_version>.
4228 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4229 [InitBasicFS, Always, TestOutputBuffer (
4230 [["write_file"; "/src"; "hello, world"; "0"];
4231 ["dd"; "/src"; "/dest"];
4232 ["read_file"; "/dest"]], "hello, world")],
4233 "copy from source to destination using dd",
4235 This command copies from one source device or file C<src>
4236 to another destination device or file C<dest>. Normally you
4237 would use this to copy to or from a device or partition, for
4238 example to duplicate a filesystem.
4240 If the destination is a device, it must be as large or larger
4241 than the source file or device, otherwise the copy will fail.
4242 This command cannot do partial copies.");
4244 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4245 [InitBasicFS, Always, TestOutputInt (
4246 [["write_file"; "/file"; "hello, world"; "0"];
4247 ["filesize"; "/file"]], 12)],
4248 "return the size of the file in bytes",
4250 This command returns the size of C<file> in bytes.
4252 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4253 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4254 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4256 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4257 [InitBasicFSonLVM, Always, TestOutputList (
4258 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4259 ["lvs"]], ["/dev/VG/LV2"])],
4260 "rename an LVM logical volume",
4262 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4264 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4265 [InitBasicFSonLVM, Always, TestOutputList (
4267 ["vg_activate"; "false"; "VG"];
4268 ["vgrename"; "VG"; "VG2"];
4269 ["vg_activate"; "true"; "VG2"];
4270 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4271 ["vgs"]], ["VG2"])],
4272 "rename an LVM volume group",
4274 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4276 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4277 [InitISOFS, Always, TestOutputBuffer (
4278 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4279 "list the contents of a single file in an initrd",
4281 This command unpacks the file C<filename> from the initrd file
4282 called C<initrdpath>. The filename must be given I<without> the
4283 initial C</> character.
4285 For example, in guestfish you could use the following command
4286 to examine the boot script (usually called C</init>)
4287 contained in a Linux initrd or initramfs image:
4289 initrd-cat /boot/initrd-<version>.img init
4291 See also C<guestfs_initrd_list>.");
4295 let all_functions = non_daemon_functions @ daemon_functions
4297 (* In some places we want the functions to be displayed sorted
4298 * alphabetically, so this is useful:
4300 let all_functions_sorted =
4301 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4302 compare n1 n2) all_functions
4304 (* Field types for structures. *)
4306 | FChar (* C 'char' (really, a 7 bit byte). *)
4307 | FString (* nul-terminated ASCII string, NOT NULL. *)
4308 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4313 | FBytes (* Any int measure that counts bytes. *)
4314 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4315 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4317 (* Because we generate extra parsing code for LVM command line tools,
4318 * we have to pull out the LVM columns separately here.
4328 "pv_attr", FString (* XXX *);
4329 "pv_pe_count", FInt64;
4330 "pv_pe_alloc_count", FInt64;
4333 "pv_mda_count", FInt64;
4334 "pv_mda_free", FBytes;
4335 (* Not in Fedora 10:
4336 "pv_mda_size", FBytes;
4343 "vg_attr", FString (* XXX *);
4346 "vg_sysid", FString;
4347 "vg_extent_size", FBytes;
4348 "vg_extent_count", FInt64;
4349 "vg_free_count", FInt64;
4354 "snap_count", FInt64;
4357 "vg_mda_count", FInt64;
4358 "vg_mda_free", FBytes;
4359 (* Not in Fedora 10:
4360 "vg_mda_size", FBytes;
4366 "lv_attr", FString (* XXX *);
4369 "lv_kernel_major", FInt64;
4370 "lv_kernel_minor", FInt64;
4372 "seg_count", FInt64;
4374 "snap_percent", FOptPercent;
4375 "copy_percent", FOptPercent;
4378 "mirror_log", FString;
4382 (* Names and fields in all structures (in RStruct and RStructList)
4386 (* The old RIntBool return type, only ever used for aug_defnode. Do
4387 * not use this struct in any new code.
4390 "i", FInt32; (* for historical compatibility *)
4391 "b", FInt32; (* for historical compatibility *)
4394 (* LVM PVs, VGs, LVs. *)
4395 "lvm_pv", lvm_pv_cols;
4396 "lvm_vg", lvm_vg_cols;
4397 "lvm_lv", lvm_lv_cols;
4399 (* Column names and types from stat structures.
4400 * NB. Can't use things like 'st_atime' because glibc header files
4401 * define some of these as macros. Ugh.
4432 (* Column names in dirent structure. *)
4435 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4440 (* Version numbers. *)
4448 (* Extended attribute. *)
4450 "attrname", FString;
4454 (* Inotify events. *)
4458 "in_cookie", FUInt32;
4462 (* Partition table entry. *)
4465 "part_start", FBytes;
4467 "part_size", FBytes;
4469 ] (* end of structs *)
4471 (* Ugh, Java has to be different ..
4472 * These names are also used by the Haskell bindings.
4474 let java_structs = [
4475 "int_bool", "IntBool";
4480 "statvfs", "StatVFS";
4482 "version", "Version";
4484 "inotify_event", "INotifyEvent";
4485 "partition", "Partition";
4488 (* What structs are actually returned. *)
4489 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4491 (* Returns a list of RStruct/RStructList structs that are returned
4492 * by any function. Each element of returned list is a pair:
4494 * (structname, RStructOnly)
4495 * == there exists function which returns RStruct (_, structname)
4496 * (structname, RStructListOnly)
4497 * == there exists function which returns RStructList (_, structname)
4498 * (structname, RStructAndList)
4499 * == there are functions returning both RStruct (_, structname)
4500 * and RStructList (_, structname)
4502 let rstructs_used_by functions =
4503 (* ||| is a "logical OR" for rstructs_used_t *)
4507 | _, RStructAndList -> RStructAndList
4508 | RStructOnly, RStructListOnly
4509 | RStructListOnly, RStructOnly -> RStructAndList
4510 | RStructOnly, RStructOnly -> RStructOnly
4511 | RStructListOnly, RStructListOnly -> RStructListOnly
4514 let h = Hashtbl.create 13 in
4516 (* if elem->oldv exists, update entry using ||| operator,
4517 * else just add elem->newv to the hash
4519 let update elem newv =
4520 try let oldv = Hashtbl.find h elem in
4521 Hashtbl.replace h elem (newv ||| oldv)
4522 with Not_found -> Hashtbl.add h elem newv
4526 fun (_, style, _, _, _, _, _) ->
4527 match fst style with
4528 | RStruct (_, structname) -> update structname RStructOnly
4529 | RStructList (_, structname) -> update structname RStructListOnly
4533 (* return key->values as a list of (key,value) *)
4534 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4536 (* Used for testing language bindings. *)
4538 | CallString of string
4539 | CallOptString of string option
4540 | CallStringList of string list
4542 | CallInt64 of int64
4545 (* Used to memoize the result of pod2text. *)
4546 let pod2text_memo_filename = "src/.pod2text.data"
4547 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4549 let chan = open_in pod2text_memo_filename in
4550 let v = input_value chan in
4554 _ -> Hashtbl.create 13
4555 let pod2text_memo_updated () =
4556 let chan = open_out pod2text_memo_filename in
4557 output_value chan pod2text_memo;
4560 (* Useful functions.
4561 * Note we don't want to use any external OCaml libraries which
4562 * makes this a bit harder than it should be.
4564 module StringMap = Map.Make (String)
4566 let failwithf fs = ksprintf failwith fs
4568 let unique = let i = ref 0 in fun () -> incr i; !i
4570 let replace_char s c1 c2 =
4571 let s2 = String.copy s in
4572 let r = ref false in
4573 for i = 0 to String.length s2 - 1 do
4574 if String.unsafe_get s2 i = c1 then (
4575 String.unsafe_set s2 i c2;
4579 if not !r then s else s2
4583 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4585 let triml ?(test = isspace) str =
4587 let n = ref (String.length str) in
4588 while !n > 0 && test str.[!i]; do
4593 else String.sub str !i !n
4595 let trimr ?(test = isspace) str =
4596 let n = ref (String.length str) in
4597 while !n > 0 && test str.[!n-1]; do
4600 if !n = String.length str then str
4601 else String.sub str 0 !n
4603 let trim ?(test = isspace) str =
4604 trimr ~test (triml ~test str)
4606 let rec find s sub =
4607 let len = String.length s in
4608 let sublen = String.length sub in
4610 if i <= len-sublen then (
4612 if j < sublen then (
4613 if s.[i+j] = sub.[j] then loop2 (j+1)
4619 if r = -1 then loop (i+1) else r
4625 let rec replace_str s s1 s2 =
4626 let len = String.length s in
4627 let sublen = String.length s1 in
4628 let i = find s s1 in
4631 let s' = String.sub s 0 i in
4632 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4633 s' ^ s2 ^ replace_str s'' s1 s2
4636 let rec string_split sep str =
4637 let len = String.length str in
4638 let seplen = String.length sep in
4639 let i = find str sep in
4640 if i = -1 then [str]
4642 let s' = String.sub str 0 i in
4643 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4644 s' :: string_split sep s''
4647 let files_equal n1 n2 =
4648 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4649 match Sys.command cmd with
4652 | i -> failwithf "%s: failed with error code %d" cmd i
4654 let rec filter_map f = function
4658 | Some y -> y :: filter_map f xs
4659 | None -> filter_map f xs
4661 let rec find_map f = function
4662 | [] -> raise Not_found
4666 | None -> find_map f xs
4669 let rec loop i = function
4671 | x :: xs -> f i x; loop (i+1) xs
4676 let rec loop i = function
4678 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4682 let count_chars c str =
4683 let count = ref 0 in
4684 for i = 0 to String.length str - 1 do
4685 if c = String.unsafe_get str i then incr count
4689 let name_of_argt = function
4690 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4691 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4692 | FileIn n | FileOut n -> n
4694 let java_name_of_struct typ =
4695 try List.assoc typ java_structs
4698 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4700 let cols_of_struct typ =
4701 try List.assoc typ structs
4703 failwithf "cols_of_struct: unknown struct %s" typ
4705 let seq_of_test = function
4706 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4707 | TestOutputListOfDevices (s, _)
4708 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4709 | TestOutputTrue s | TestOutputFalse s
4710 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4711 | TestOutputStruct (s, _)
4712 | TestLastFail s -> s
4714 (* Handling for function flags. *)
4715 let protocol_limit_warning =
4716 "Because of the message protocol, there is a transfer limit
4717 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4719 let danger_will_robinson =
4720 "B<This command is dangerous. Without careful use you
4721 can easily destroy all your data>."
4723 let deprecation_notice flags =
4726 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4728 sprintf "This function is deprecated.
4729 In new code, use the C<%s> call instead.
4731 Deprecated functions will not be removed from the API, but the
4732 fact that they are deprecated indicates that there are problems
4733 with correct use of these functions." alt in
4738 (* Create list of optional groups. *)
4740 let h = Hashtbl.create 13 in
4742 fun (name, _, _, flags, _, _, _) ->
4746 let names = try Hashtbl.find h group with Not_found -> [] in
4747 Hashtbl.replace h group (name :: names)
4751 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4754 fun group -> group, List.sort compare (Hashtbl.find h group)
4756 List.sort (fun x y -> compare (fst x) (fst y)) groups
4758 (* Check function names etc. for consistency. *)
4759 let check_functions () =
4760 let contains_uppercase str =
4761 let len = String.length str in
4763 if i >= len then false
4766 if c >= 'A' && c <= 'Z' then true
4773 (* Check function names. *)
4775 fun (name, _, _, _, _, _, _) ->
4776 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4777 failwithf "function name %s does not need 'guestfs' prefix" name;
4779 failwithf "function name is empty";
4780 if name.[0] < 'a' || name.[0] > 'z' then
4781 failwithf "function name %s must start with lowercase a-z" name;
4782 if String.contains name '-' then
4783 failwithf "function name %s should not contain '-', use '_' instead."
4787 (* Check function parameter/return names. *)
4789 fun (name, style, _, _, _, _, _) ->
4790 let check_arg_ret_name n =
4791 if contains_uppercase n then
4792 failwithf "%s param/ret %s should not contain uppercase chars"
4794 if String.contains n '-' || String.contains n '_' then
4795 failwithf "%s param/ret %s should not contain '-' or '_'"
4798 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;
4799 if n = "int" || n = "char" || n = "short" || n = "long" then
4800 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4801 if n = "i" || n = "n" then
4802 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4803 if n = "argv" || n = "args" then
4804 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4806 (* List Haskell, OCaml and C keywords here.
4807 * http://www.haskell.org/haskellwiki/Keywords
4808 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4809 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4810 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4811 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4812 * Omitting _-containing words, since they're handled above.
4813 * Omitting the OCaml reserved word, "val", is ok,
4814 * and saves us from renaming several parameters.
4817 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4818 "char"; "class"; "const"; "constraint"; "continue"; "data";
4819 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4820 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4821 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4822 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4823 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4825 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4826 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4827 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4828 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4829 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4830 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4831 "volatile"; "when"; "where"; "while";
4833 if List.mem n reserved then
4834 failwithf "%s has param/ret using reserved word %s" name n;
4837 (match fst style with
4839 | RInt n | RInt64 n | RBool n
4840 | RConstString n | RConstOptString n | RString n
4841 | RStringList n | RStruct (n, _) | RStructList (n, _)
4842 | RHashtable n | RBufferOut n ->
4843 check_arg_ret_name n
4845 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4848 (* Check short descriptions. *)
4850 fun (name, _, _, _, _, shortdesc, _) ->
4851 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4852 failwithf "short description of %s should begin with lowercase." name;
4853 let c = shortdesc.[String.length shortdesc-1] in
4854 if c = '\n' || c = '.' then
4855 failwithf "short description of %s should not end with . or \\n." name
4858 (* Check long dscriptions. *)
4860 fun (name, _, _, _, _, _, longdesc) ->
4861 if longdesc.[String.length longdesc-1] = '\n' then
4862 failwithf "long description of %s should not end with \\n." name
4865 (* Check proc_nrs. *)
4867 fun (name, _, proc_nr, _, _, _, _) ->
4868 if proc_nr <= 0 then
4869 failwithf "daemon function %s should have proc_nr > 0" name
4873 fun (name, _, proc_nr, _, _, _, _) ->
4874 if proc_nr <> -1 then
4875 failwithf "non-daemon function %s should have proc_nr -1" name
4876 ) non_daemon_functions;
4879 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4882 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4883 let rec loop = function
4886 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4888 | (name1,nr1) :: (name2,nr2) :: _ ->
4889 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4897 (* Ignore functions that have no tests. We generate a
4898 * warning when the user does 'make check' instead.
4900 | name, _, _, _, [], _, _ -> ()
4901 | name, _, _, _, tests, _, _ ->
4905 match seq_of_test test with
4907 failwithf "%s has a test containing an empty sequence" name
4908 | cmds -> List.map List.hd cmds
4910 let funcs = List.flatten funcs in
4912 let tested = List.mem name funcs in
4915 failwithf "function %s has tests but does not test itself" name
4918 (* 'pr' prints to the current output file. *)
4919 let chan = ref Pervasives.stdout
4924 let i = count_chars '\n' str in
4925 lines := !lines + i;
4926 output_string !chan str
4929 let copyright_years =
4930 let this_year = 1900 + (localtime (time ())).tm_year in
4931 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4933 (* Generate a header block in a number of standard styles. *)
4934 type comment_style =
4935 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4936 type license = GPLv2plus | LGPLv2plus
4938 let generate_header ?(extra_inputs = []) comment license =
4939 let inputs = "src/generator.ml" :: extra_inputs in
4940 let c = match comment with
4941 | CStyle -> pr "/* "; " *"
4942 | CPlusPlusStyle -> pr "// "; "//"
4943 | HashStyle -> pr "# "; "#"
4944 | OCamlStyle -> pr "(* "; " *"
4945 | HaskellStyle -> pr "{- "; " " in
4946 pr "libguestfs generated file\n";
4947 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4948 List.iter (pr "%s %s\n" c) inputs;
4949 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4951 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4955 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4956 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4957 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4958 pr "%s (at your option) any later version.\n" c;
4960 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4961 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4962 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4963 pr "%s GNU General Public License for more details.\n" c;
4965 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4966 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4967 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4970 pr "%s This library is free software; you can redistribute it and/or\n" c;
4971 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4972 pr "%s License as published by the Free Software Foundation; either\n" c;
4973 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4975 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4976 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4977 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4978 pr "%s Lesser General Public License for more details.\n" c;
4980 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4981 pr "%s License along with this library; if not, write to the Free Software\n" c;
4982 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4985 | CStyle -> pr " */\n"
4988 | OCamlStyle -> pr " *)\n"
4989 | HaskellStyle -> pr "-}\n"
4993 (* Start of main code generation functions below this line. *)
4995 (* Generate the pod documentation for the C API. *)
4996 let rec generate_actions_pod () =
4998 fun (shortname, style, _, flags, _, _, longdesc) ->
4999 if not (List.mem NotInDocs flags) then (
5000 let name = "guestfs_" ^ shortname in
5001 pr "=head2 %s\n\n" name;
5003 generate_prototype ~extern:false ~handle:"handle" name style;
5005 pr "%s\n\n" longdesc;
5006 (match fst style with
5008 pr "This function returns 0 on success or -1 on error.\n\n"
5010 pr "On error this function returns -1.\n\n"
5012 pr "On error this function returns -1.\n\n"
5014 pr "This function returns a C truth value on success or -1 on error.\n\n"
5016 pr "This function returns a string, or NULL on error.
5017 The string is owned by the guest handle and must I<not> be freed.\n\n"
5018 | RConstOptString _ ->
5019 pr "This function returns a string which may be NULL.
5020 There is way to return an error from this function.
5021 The string is owned by the guest handle and must I<not> be freed.\n\n"
5023 pr "This function returns a string, or NULL on error.
5024 I<The caller must free the returned string after use>.\n\n"
5026 pr "This function returns a NULL-terminated array of strings
5027 (like L<environ(3)>), or NULL if there was an error.
5028 I<The caller must free the strings and the array after use>.\n\n"
5029 | RStruct (_, typ) ->
5030 pr "This function returns a C<struct guestfs_%s *>,
5031 or NULL if there was an error.
5032 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5033 | RStructList (_, typ) ->
5034 pr "This function returns a C<struct guestfs_%s_list *>
5035 (see E<lt>guestfs-structs.hE<gt>),
5036 or NULL if there was an error.
5037 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5039 pr "This function returns a NULL-terminated array of
5040 strings, or NULL if there was an error.
5041 The array of strings will always have length C<2n+1>, where
5042 C<n> keys and values alternate, followed by the trailing NULL entry.
5043 I<The caller must free the strings and the array after use>.\n\n"
5045 pr "This function returns a buffer, or NULL on error.
5046 The size of the returned buffer is written to C<*size_r>.
5047 I<The caller must free the returned buffer after use>.\n\n"
5049 if List.mem ProtocolLimitWarning flags then
5050 pr "%s\n\n" protocol_limit_warning;
5051 if List.mem DangerWillRobinson flags then
5052 pr "%s\n\n" danger_will_robinson;
5053 match deprecation_notice flags with
5055 | Some txt -> pr "%s\n\n" txt
5057 ) all_functions_sorted
5059 and generate_structs_pod () =
5060 (* Structs documentation. *)
5063 pr "=head2 guestfs_%s\n" typ;
5065 pr " struct guestfs_%s {\n" typ;
5068 | name, FChar -> pr " char %s;\n" name
5069 | name, FUInt32 -> pr " uint32_t %s;\n" name
5070 | name, FInt32 -> pr " int32_t %s;\n" name
5071 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5072 | name, FInt64 -> pr " int64_t %s;\n" name
5073 | name, FString -> pr " char *%s;\n" name
5075 pr " /* The next two fields describe a byte array. */\n";
5076 pr " uint32_t %s_len;\n" name;
5077 pr " char *%s;\n" name
5079 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5080 pr " char %s[32];\n" name
5081 | name, FOptPercent ->
5082 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5083 pr " float %s;\n" name
5087 pr " struct guestfs_%s_list {\n" typ;
5088 pr " uint32_t len; /* Number of elements in list. */\n";
5089 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5092 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5093 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5098 and generate_availability_pod () =
5099 (* Availability documentation. *)
5103 fun (group, functions) ->
5104 pr "=item B<%s>\n" group;
5106 pr "The following functions:\n";
5107 List.iter (pr "L</guestfs_%s>\n") functions;
5113 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5114 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5116 * We have to use an underscore instead of a dash because otherwise
5117 * rpcgen generates incorrect code.
5119 * This header is NOT exported to clients, but see also generate_structs_h.
5121 and generate_xdr () =
5122 generate_header CStyle LGPLv2plus;
5124 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5125 pr "typedef string str<>;\n";
5128 (* Internal structures. *)
5132 pr "struct guestfs_int_%s {\n" typ;
5134 | name, FChar -> pr " char %s;\n" name
5135 | name, FString -> pr " string %s<>;\n" name
5136 | name, FBuffer -> pr " opaque %s<>;\n" name
5137 | name, FUUID -> pr " opaque %s[32];\n" name
5138 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5139 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5140 | name, FOptPercent -> pr " float %s;\n" name
5144 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5149 fun (shortname, style, _, _, _, _, _) ->
5150 let name = "guestfs_" ^ shortname in
5152 (match snd style with
5155 pr "struct %s_args {\n" name;
5158 | Pathname n | Device n | Dev_or_Path n | String n ->
5159 pr " string %s<>;\n" n
5160 | OptString n -> pr " str *%s;\n" n
5161 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5162 | Bool n -> pr " bool %s;\n" n
5163 | Int n -> pr " int %s;\n" n
5164 | Int64 n -> pr " hyper %s;\n" n
5165 | FileIn _ | FileOut _ -> ()
5169 (match fst style with
5172 pr "struct %s_ret {\n" name;
5176 pr "struct %s_ret {\n" name;
5177 pr " hyper %s;\n" n;
5180 pr "struct %s_ret {\n" name;
5183 | RConstString _ | RConstOptString _ ->
5184 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5186 pr "struct %s_ret {\n" name;
5187 pr " string %s<>;\n" n;
5190 pr "struct %s_ret {\n" name;
5191 pr " str %s<>;\n" n;
5193 | RStruct (n, typ) ->
5194 pr "struct %s_ret {\n" name;
5195 pr " guestfs_int_%s %s;\n" typ n;
5197 | RStructList (n, typ) ->
5198 pr "struct %s_ret {\n" name;
5199 pr " guestfs_int_%s_list %s;\n" typ n;
5202 pr "struct %s_ret {\n" name;
5203 pr " str %s<>;\n" n;
5206 pr "struct %s_ret {\n" name;
5207 pr " opaque %s<>;\n" n;
5212 (* Table of procedure numbers. *)
5213 pr "enum guestfs_procedure {\n";
5215 fun (shortname, _, proc_nr, _, _, _, _) ->
5216 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5218 pr " GUESTFS_PROC_NR_PROCS\n";
5222 (* Having to choose a maximum message size is annoying for several
5223 * reasons (it limits what we can do in the API), but it (a) makes
5224 * the protocol a lot simpler, and (b) provides a bound on the size
5225 * of the daemon which operates in limited memory space.
5227 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5230 (* Message header, etc. *)
5232 /* The communication protocol is now documented in the guestfs(3)
5236 const GUESTFS_PROGRAM = 0x2000F5F5;
5237 const GUESTFS_PROTOCOL_VERSION = 1;
5239 /* These constants must be larger than any possible message length. */
5240 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5241 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5243 enum guestfs_message_direction {
5244 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5245 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5248 enum guestfs_message_status {
5249 GUESTFS_STATUS_OK = 0,
5250 GUESTFS_STATUS_ERROR = 1
5253 const GUESTFS_ERROR_LEN = 256;
5255 struct guestfs_message_error {
5256 string error_message<GUESTFS_ERROR_LEN>;
5259 struct guestfs_message_header {
5260 unsigned prog; /* GUESTFS_PROGRAM */
5261 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5262 guestfs_procedure proc; /* GUESTFS_PROC_x */
5263 guestfs_message_direction direction;
5264 unsigned serial; /* message serial number */
5265 guestfs_message_status status;
5268 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5270 struct guestfs_chunk {
5271 int cancel; /* if non-zero, transfer is cancelled */
5272 /* data size is 0 bytes if the transfer has finished successfully */
5273 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5277 (* Generate the guestfs-structs.h file. *)
5278 and generate_structs_h () =
5279 generate_header CStyle LGPLv2plus;
5281 (* This is a public exported header file containing various
5282 * structures. The structures are carefully written to have
5283 * exactly the same in-memory format as the XDR structures that
5284 * we use on the wire to the daemon. The reason for creating
5285 * copies of these structures here is just so we don't have to
5286 * export the whole of guestfs_protocol.h (which includes much
5287 * unrelated and XDR-dependent stuff that we don't want to be
5288 * public, or required by clients).
5290 * To reiterate, we will pass these structures to and from the
5291 * client with a simple assignment or memcpy, so the format
5292 * must be identical to what rpcgen / the RFC defines.
5295 (* Public structures. *)
5298 pr "struct guestfs_%s {\n" typ;
5301 | name, FChar -> pr " char %s;\n" name
5302 | name, FString -> pr " char *%s;\n" name
5304 pr " uint32_t %s_len;\n" name;
5305 pr " char *%s;\n" name
5306 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5307 | name, FUInt32 -> pr " uint32_t %s;\n" name
5308 | name, FInt32 -> pr " int32_t %s;\n" name
5309 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5310 | name, FInt64 -> pr " int64_t %s;\n" name
5311 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5315 pr "struct guestfs_%s_list {\n" typ;
5316 pr " uint32_t len;\n";
5317 pr " struct guestfs_%s *val;\n" typ;
5320 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5321 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5325 (* Generate the guestfs-actions.h file. *)
5326 and generate_actions_h () =
5327 generate_header CStyle LGPLv2plus;
5329 fun (shortname, style, _, _, _, _, _) ->
5330 let name = "guestfs_" ^ shortname in
5331 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5335 (* Generate the guestfs-internal-actions.h file. *)
5336 and generate_internal_actions_h () =
5337 generate_header CStyle LGPLv2plus;
5339 fun (shortname, style, _, _, _, _, _) ->
5340 let name = "guestfs__" ^ shortname in
5341 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5343 ) non_daemon_functions
5345 (* Generate the client-side dispatch stubs. *)
5346 and generate_client_actions () =
5347 generate_header CStyle LGPLv2plus;
5353 #include <inttypes.h>
5355 #include \"guestfs.h\"
5356 #include \"guestfs-internal.h\"
5357 #include \"guestfs-internal-actions.h\"
5358 #include \"guestfs_protocol.h\"
5360 #define error guestfs_error
5361 //#define perrorf guestfs_perrorf
5362 #define safe_malloc guestfs_safe_malloc
5363 #define safe_realloc guestfs_safe_realloc
5364 //#define safe_strdup guestfs_safe_strdup
5365 #define safe_memdup guestfs_safe_memdup
5367 /* Check the return message from a call for validity. */
5369 check_reply_header (guestfs_h *g,
5370 const struct guestfs_message_header *hdr,
5371 unsigned int proc_nr, unsigned int serial)
5373 if (hdr->prog != GUESTFS_PROGRAM) {
5374 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5377 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5378 error (g, \"wrong protocol version (%%d/%%d)\",
5379 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5382 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5383 error (g, \"unexpected message direction (%%d/%%d)\",
5384 hdr->direction, GUESTFS_DIRECTION_REPLY);
5387 if (hdr->proc != proc_nr) {
5388 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5391 if (hdr->serial != serial) {
5392 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5399 /* Check we are in the right state to run a high-level action. */
5401 check_state (guestfs_h *g, const char *caller)
5403 if (!guestfs__is_ready (g)) {
5404 if (guestfs__is_config (g) || guestfs__is_launching (g))
5405 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5408 error (g, \"%%s called from the wrong state, %%d != READY\",
5409 caller, guestfs__get_state (g));
5417 (* Generate code to generate guestfish call traces. *)
5418 let trace_call shortname style =
5419 pr " if (guestfs__get_trace (g)) {\n";
5422 List.exists (function
5423 | StringList _ | DeviceList _ -> true
5424 | _ -> false) (snd style) in
5430 pr " printf (\"%s\");\n" shortname;
5433 | String n (* strings *)
5439 (* guestfish doesn't support string escaping, so neither do we *)
5440 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5441 | OptString n -> (* string option *)
5442 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5443 pr " else printf (\" null\");\n"
5445 | DeviceList n -> (* string list *)
5446 pr " putchar (' ');\n";
5447 pr " putchar ('\"');\n";
5448 pr " for (i = 0; %s[i]; ++i) {\n" n;
5449 pr " if (i > 0) putchar (' ');\n";
5450 pr " fputs (%s[i], stdout);\n" n;
5452 pr " putchar ('\"');\n";
5453 | Bool n -> (* boolean *)
5454 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5455 | Int n -> (* int *)
5456 pr " printf (\" %%d\", %s);\n" n
5458 pr " printf (\" %%\" PRIi64, %s);\n" n
5460 pr " putchar ('\\n');\n";
5465 (* For non-daemon functions, generate a wrapper around each function. *)
5467 fun (shortname, style, _, _, _, _, _) ->
5468 let name = "guestfs_" ^ shortname in
5470 generate_prototype ~extern:false ~semicolon:false ~newline:true
5471 ~handle:"g" name style;
5473 trace_call shortname style;
5474 pr " return guestfs__%s " shortname;
5475 generate_c_call_args ~handle:"g" style;
5479 ) non_daemon_functions;
5481 (* Client-side stubs for each function. *)
5483 fun (shortname, style, _, _, _, _, _) ->
5484 let name = "guestfs_" ^ shortname in
5486 (* Generate the action stub. *)
5487 generate_prototype ~extern:false ~semicolon:false ~newline:true
5488 ~handle:"g" name style;
5491 match fst style with
5492 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5493 | RConstString _ | RConstOptString _ ->
5494 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5495 | RString _ | RStringList _
5496 | RStruct _ | RStructList _
5497 | RHashtable _ | RBufferOut _ ->
5502 (match snd style with
5504 | _ -> pr " struct %s_args args;\n" name
5507 pr " guestfs_message_header hdr;\n";
5508 pr " guestfs_message_error err;\n";
5510 match fst style with
5512 | RConstString _ | RConstOptString _ ->
5513 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5515 | RBool _ | RString _ | RStringList _
5516 | RStruct _ | RStructList _
5517 | RHashtable _ | RBufferOut _ ->
5518 pr " struct %s_ret ret;\n" name;
5521 pr " int serial;\n";
5524 trace_call shortname style;
5525 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5526 pr " guestfs___set_busy (g);\n";
5529 (* Send the main header and arguments. *)
5530 (match snd style with
5532 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5533 (String.uppercase shortname)
5537 | Pathname n | Device n | Dev_or_Path n | String n ->
5538 pr " args.%s = (char *) %s;\n" n n
5540 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5541 | StringList n | DeviceList n ->
5542 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5543 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5545 pr " args.%s = %s;\n" n n
5547 pr " args.%s = %s;\n" n n
5549 pr " args.%s = %s;\n" n n
5550 | FileIn _ | FileOut _ -> ()
5552 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5553 (String.uppercase shortname);
5554 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5557 pr " if (serial == -1) {\n";
5558 pr " guestfs___end_busy (g);\n";
5559 pr " return %s;\n" error_code;
5563 (* Send any additional files (FileIn) requested. *)
5564 let need_read_reply_label = ref false in
5568 pr " r = guestfs___send_file (g, %s);\n" n;
5569 pr " if (r == -1) {\n";
5570 pr " guestfs___end_busy (g);\n";
5571 pr " return %s;\n" error_code;
5573 pr " if (r == -2) /* daemon cancelled */\n";
5574 pr " goto read_reply;\n";
5575 need_read_reply_label := true;
5580 (* Wait for the reply from the remote end. *)
5581 if !need_read_reply_label then pr " read_reply:\n";
5582 pr " memset (&hdr, 0, sizeof hdr);\n";
5583 pr " memset (&err, 0, sizeof err);\n";
5584 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5586 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5590 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5593 pr " if (r == -1) {\n";
5594 pr " guestfs___end_busy (g);\n";
5595 pr " return %s;\n" error_code;
5599 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5600 (String.uppercase shortname);
5601 pr " guestfs___end_busy (g);\n";
5602 pr " return %s;\n" error_code;
5606 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5607 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5608 pr " free (err.error_message);\n";
5609 pr " guestfs___end_busy (g);\n";
5610 pr " return %s;\n" error_code;
5614 (* Expecting to receive further files (FileOut)? *)
5618 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5619 pr " guestfs___end_busy (g);\n";
5620 pr " return %s;\n" error_code;
5626 pr " guestfs___end_busy (g);\n";
5628 (match fst style with
5629 | RErr -> pr " return 0;\n"
5630 | RInt n | RInt64 n | RBool n ->
5631 pr " return ret.%s;\n" n
5632 | RConstString _ | RConstOptString _ ->
5633 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5635 pr " return ret.%s; /* caller will free */\n" n
5636 | RStringList n | RHashtable n ->
5637 pr " /* caller will free this, but we need to add a NULL entry */\n";
5638 pr " ret.%s.%s_val =\n" n n;
5639 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5640 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5642 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5643 pr " return ret.%s.%s_val;\n" n n
5645 pr " /* caller will free this */\n";
5646 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5647 | RStructList (n, _) ->
5648 pr " /* caller will free this */\n";
5649 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5651 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5652 pr " * _val might be NULL here. To make the API saner for\n";
5653 pr " * callers, we turn this case into a unique pointer (using\n";
5654 pr " * malloc(1)).\n";
5656 pr " if (ret.%s.%s_len > 0) {\n" n n;
5657 pr " *size_r = ret.%s.%s_len;\n" n n;
5658 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5660 pr " free (ret.%s.%s_val);\n" n n;
5661 pr " char *p = safe_malloc (g, 1);\n";
5662 pr " *size_r = ret.%s.%s_len;\n" n n;
5670 (* Functions to free structures. *)
5671 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5672 pr " * structure format is identical to the XDR format. See note in\n";
5673 pr " * generator.ml.\n";
5680 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5682 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5688 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5690 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5697 (* Generate daemon/actions.h. *)
5698 and generate_daemon_actions_h () =
5699 generate_header CStyle GPLv2plus;
5701 pr "#include \"../src/guestfs_protocol.h\"\n";
5705 fun (name, style, _, _, _, _, _) ->
5707 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5711 (* Generate the linker script which controls the visibility of
5712 * symbols in the public ABI and ensures no other symbols get
5713 * exported accidentally.
5715 and generate_linker_script () =
5716 generate_header HashStyle GPLv2plus;
5721 "guestfs_get_error_handler";
5722 "guestfs_get_out_of_memory_handler";
5723 "guestfs_last_error";
5724 "guestfs_set_error_handler";
5725 "guestfs_set_launch_done_callback";
5726 "guestfs_set_log_message_callback";
5727 "guestfs_set_out_of_memory_handler";
5728 "guestfs_set_subprocess_quit_callback";
5730 (* Unofficial parts of the API: the bindings code use these
5731 * functions, so it is useful to export them.
5733 "guestfs_safe_calloc";
5734 "guestfs_safe_malloc";
5737 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5741 List.map (fun (typ, _) ->
5742 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5745 let globals = List.sort compare (globals @ functions @ structs) in
5749 List.iter (pr " %s;\n") globals;
5756 (* Generate the server-side stubs. *)
5757 and generate_daemon_actions () =
5758 generate_header CStyle GPLv2plus;
5760 pr "#include <config.h>\n";
5762 pr "#include <stdio.h>\n";
5763 pr "#include <stdlib.h>\n";
5764 pr "#include <string.h>\n";
5765 pr "#include <inttypes.h>\n";
5766 pr "#include <rpc/types.h>\n";
5767 pr "#include <rpc/xdr.h>\n";
5769 pr "#include \"daemon.h\"\n";
5770 pr "#include \"c-ctype.h\"\n";
5771 pr "#include \"../src/guestfs_protocol.h\"\n";
5772 pr "#include \"actions.h\"\n";
5776 fun (name, style, _, _, _, _, _) ->
5777 (* Generate server-side stubs. *)
5778 pr "static void %s_stub (XDR *xdr_in)\n" name;
5781 match fst style with
5782 | RErr | RInt _ -> pr " int r;\n"; "-1"
5783 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5784 | RBool _ -> pr " int r;\n"; "-1"
5785 | RConstString _ | RConstOptString _ ->
5786 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5787 | RString _ -> pr " char *r;\n"; "NULL"
5788 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5789 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5790 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5792 pr " size_t size = 1;\n";
5796 (match snd style with
5799 pr " struct guestfs_%s_args args;\n" name;
5802 | Device n | Dev_or_Path n
5805 | OptString n -> pr " char *%s;\n" n
5806 | StringList n | DeviceList n -> pr " char **%s;\n" n
5807 | Bool n -> pr " int %s;\n" n
5808 | Int n -> pr " int %s;\n" n
5809 | Int64 n -> pr " int64_t %s;\n" n
5810 | FileIn _ | FileOut _ -> ()
5815 (match snd style with
5818 pr " memset (&args, 0, sizeof args);\n";
5820 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5821 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5825 pr " char *%s = args.%s;\n" n n
5827 let pr_list_handling_code n =
5828 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5829 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5830 pr " if (%s == NULL) {\n" n;
5831 pr " reply_with_perror (\"realloc\");\n";
5834 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5835 pr " args.%s.%s_val = %s;\n" n n n;
5841 pr " ABS_PATH (%s, goto done);\n" n;
5844 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5847 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5848 | String n -> pr_args n
5849 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5851 pr_list_handling_code n;
5853 pr_list_handling_code n;
5854 pr " /* Ensure that each is a device,\n";
5855 pr " * and perform device name translation. */\n";
5856 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5857 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5859 | Bool n -> pr " %s = args.%s;\n" n n
5860 | Int n -> pr " %s = args.%s;\n" n n
5861 | Int64 n -> pr " %s = args.%s;\n" n n
5862 | FileIn _ | FileOut _ -> ()
5868 (* this is used at least for do_equal *)
5869 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5870 (* Emit NEED_ROOT just once, even when there are two or
5871 more Pathname args *)
5872 pr " NEED_ROOT (goto done);\n";
5875 (* Don't want to call the impl with any FileIn or FileOut
5876 * parameters, since these go "outside" the RPC protocol.
5879 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5881 pr " r = do_%s " name;
5882 generate_c_call_args (fst style, args');
5885 (match fst style with
5886 | RErr | RInt _ | RInt64 _ | RBool _
5887 | RConstString _ | RConstOptString _
5888 | RString _ | RStringList _ | RHashtable _
5889 | RStruct (_, _) | RStructList (_, _) ->
5890 pr " if (r == %s)\n" error_code;
5891 pr " /* do_%s has already called reply_with_error */\n" name;
5895 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
5896 pr " * an ordinary zero-length buffer), so be careful ...\n";
5898 pr " if (size == 1 && r == %s)\n" error_code;
5899 pr " /* do_%s has already called reply_with_error */\n" name;
5904 (* If there are any FileOut parameters, then the impl must
5905 * send its own reply.
5908 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5910 pr " /* do_%s has already sent a reply */\n" name
5912 match fst style with
5913 | RErr -> pr " reply (NULL, NULL);\n"
5914 | RInt n | RInt64 n | RBool n ->
5915 pr " struct guestfs_%s_ret ret;\n" name;
5916 pr " ret.%s = r;\n" n;
5917 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5919 | RConstString _ | RConstOptString _ ->
5920 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5922 pr " struct guestfs_%s_ret ret;\n" name;
5923 pr " ret.%s = r;\n" n;
5924 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5927 | RStringList n | RHashtable n ->
5928 pr " struct guestfs_%s_ret ret;\n" name;
5929 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5930 pr " ret.%s.%s_val = r;\n" n n;
5931 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5933 pr " free_strings (r);\n"
5935 pr " struct guestfs_%s_ret ret;\n" name;
5936 pr " ret.%s = *r;\n" n;
5937 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5939 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5941 | RStructList (n, _) ->
5942 pr " struct guestfs_%s_ret ret;\n" name;
5943 pr " ret.%s = *r;\n" n;
5944 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5946 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5949 pr " struct guestfs_%s_ret ret;\n" name;
5950 pr " ret.%s.%s_val = r;\n" n n;
5951 pr " ret.%s.%s_len = size;\n" n n;
5952 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5957 (* Free the args. *)
5958 (match snd style with
5963 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5970 (* Dispatch function. *)
5971 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5973 pr " switch (proc_nr) {\n";
5976 fun (name, style, _, _, _, _, _) ->
5977 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5978 pr " %s_stub (xdr_in);\n" name;
5983 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";
5988 (* LVM columns and tokenization functions. *)
5989 (* XXX This generates crap code. We should rethink how we
5995 pr "static const char *lvm_%s_cols = \"%s\";\n"
5996 typ (String.concat "," (List.map fst cols));
5999 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6001 pr " char *tok, *p, *next;\n";
6005 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6008 pr " if (!str) {\n";
6009 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6012 pr " if (!*str || c_isspace (*str)) {\n";
6013 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6018 fun (name, coltype) ->
6019 pr " if (!tok) {\n";
6020 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6023 pr " p = strchrnul (tok, ',');\n";
6024 pr " if (*p) next = p+1; else next = NULL;\n";
6025 pr " *p = '\\0';\n";
6028 pr " r->%s = strdup (tok);\n" name;
6029 pr " if (r->%s == NULL) {\n" name;
6030 pr " perror (\"strdup\");\n";
6034 pr " for (i = j = 0; i < 32; ++j) {\n";
6035 pr " if (tok[j] == '\\0') {\n";
6036 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6038 pr " } else if (tok[j] != '-')\n";
6039 pr " r->%s[i++] = tok[j];\n" name;
6042 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6043 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6047 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6048 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6052 pr " if (tok[0] == '\\0')\n";
6053 pr " r->%s = -1;\n" name;
6054 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6055 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6058 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6059 assert false (* can never be an LVM column *)
6061 pr " tok = next;\n";
6064 pr " if (tok != NULL) {\n";
6065 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6072 pr "guestfs_int_lvm_%s_list *\n" typ;
6073 pr "parse_command_line_%ss (void)\n" typ;
6075 pr " char *out, *err;\n";
6076 pr " char *p, *pend;\n";
6078 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6079 pr " void *newp;\n";
6081 pr " ret = malloc (sizeof *ret);\n";
6082 pr " if (!ret) {\n";
6083 pr " reply_with_perror (\"malloc\");\n";
6084 pr " return NULL;\n";
6087 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6088 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6090 pr " r = command (&out, &err,\n";
6091 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
6092 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6093 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6094 pr " if (r == -1) {\n";
6095 pr " reply_with_error (\"%%s\", err);\n";
6096 pr " free (out);\n";
6097 pr " free (err);\n";
6098 pr " free (ret);\n";
6099 pr " return NULL;\n";
6102 pr " free (err);\n";
6104 pr " /* Tokenize each line of the output. */\n";
6107 pr " while (p) {\n";
6108 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6109 pr " if (pend) {\n";
6110 pr " *pend = '\\0';\n";
6114 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6117 pr " if (!*p) { /* Empty line? Skip it. */\n";
6122 pr " /* Allocate some space to store this next entry. */\n";
6123 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6124 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6125 pr " if (newp == NULL) {\n";
6126 pr " reply_with_perror (\"realloc\");\n";
6127 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6128 pr " free (ret);\n";
6129 pr " free (out);\n";
6130 pr " return NULL;\n";
6132 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6134 pr " /* Tokenize the next entry. */\n";
6135 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6136 pr " if (r == -1) {\n";
6137 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6138 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6139 pr " free (ret);\n";
6140 pr " free (out);\n";
6141 pr " return NULL;\n";
6148 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6150 pr " free (out);\n";
6151 pr " return ret;\n";
6154 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6156 (* Generate a list of function names, for debugging in the daemon.. *)
6157 and generate_daemon_names () =
6158 generate_header CStyle GPLv2plus;
6160 pr "#include <config.h>\n";
6162 pr "#include \"daemon.h\"\n";
6165 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6166 pr "const char *function_names[] = {\n";
6168 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6172 (* Generate the optional groups for the daemon to implement
6173 * guestfs_available.
6175 and generate_daemon_optgroups_c () =
6176 generate_header CStyle GPLv2plus;
6178 pr "#include <config.h>\n";
6180 pr "#include \"daemon.h\"\n";
6181 pr "#include \"optgroups.h\"\n";
6184 pr "struct optgroup optgroups[] = {\n";
6187 pr " { \"%s\", optgroup_%s_available },\n" group group
6189 pr " { NULL, NULL }\n";
6192 and generate_daemon_optgroups_h () =
6193 generate_header CStyle GPLv2plus;
6197 pr "extern int optgroup_%s_available (void);\n" group
6200 (* Generate the tests. *)
6201 and generate_tests () =
6202 generate_header CStyle GPLv2plus;
6209 #include <sys/types.h>
6212 #include \"guestfs.h\"
6213 #include \"guestfs-internal.h\"
6215 static guestfs_h *g;
6216 static int suppress_error = 0;
6218 static void print_error (guestfs_h *g, void *data, const char *msg)
6220 if (!suppress_error)
6221 fprintf (stderr, \"%%s\\n\", msg);
6224 /* FIXME: nearly identical code appears in fish.c */
6225 static void print_strings (char *const *argv)
6229 for (argc = 0; argv[argc] != NULL; ++argc)
6230 printf (\"\\t%%s\\n\", argv[argc]);
6234 static void print_table (char const *const *argv)
6238 for (i = 0; argv[i] != NULL; i += 2)
6239 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6245 (* Generate a list of commands which are not tested anywhere. *)
6246 pr "static void no_test_warnings (void)\n";
6249 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6251 fun (_, _, _, _, tests, _, _) ->
6252 let tests = filter_map (
6254 | (_, (Always|If _|Unless _), test) -> Some test
6255 | (_, Disabled, _) -> None
6257 let seq = List.concat (List.map seq_of_test tests) in
6258 let cmds_tested = List.map List.hd seq in
6259 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6263 fun (name, _, _, _, _, _, _) ->
6264 if not (Hashtbl.mem hash name) then
6265 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6271 (* Generate the actual tests. Note that we generate the tests
6272 * in reverse order, deliberately, so that (in general) the
6273 * newest tests run first. This makes it quicker and easier to
6278 fun (name, _, _, flags, tests, _, _) ->
6279 mapi (generate_one_test name flags) tests
6280 ) (List.rev all_functions) in
6281 let test_names = List.concat test_names in
6282 let nr_tests = List.length test_names in
6285 int main (int argc, char *argv[])
6288 unsigned long int n_failed = 0;
6289 const char *filename;
6291 int nr_tests, test_num = 0;
6293 setbuf (stdout, NULL);
6295 no_test_warnings ();
6297 g = guestfs_create ();
6299 printf (\"guestfs_create FAILED\\n\");
6300 exit (EXIT_FAILURE);
6303 guestfs_set_error_handler (g, print_error, NULL);
6305 guestfs_set_path (g, \"../appliance\");
6307 filename = \"test1.img\";
6308 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6311 exit (EXIT_FAILURE);
6313 if (lseek (fd, %d, SEEK_SET) == -1) {
6317 exit (EXIT_FAILURE);
6319 if (write (fd, &c, 1) == -1) {
6323 exit (EXIT_FAILURE);
6325 if (close (fd) == -1) {
6328 exit (EXIT_FAILURE);
6330 if (guestfs_add_drive (g, filename) == -1) {
6331 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6332 exit (EXIT_FAILURE);
6335 filename = \"test2.img\";
6336 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6339 exit (EXIT_FAILURE);
6341 if (lseek (fd, %d, SEEK_SET) == -1) {
6345 exit (EXIT_FAILURE);
6347 if (write (fd, &c, 1) == -1) {
6351 exit (EXIT_FAILURE);
6353 if (close (fd) == -1) {
6356 exit (EXIT_FAILURE);
6358 if (guestfs_add_drive (g, filename) == -1) {
6359 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6360 exit (EXIT_FAILURE);
6363 filename = \"test3.img\";
6364 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6367 exit (EXIT_FAILURE);
6369 if (lseek (fd, %d, SEEK_SET) == -1) {
6373 exit (EXIT_FAILURE);
6375 if (write (fd, &c, 1) == -1) {
6379 exit (EXIT_FAILURE);
6381 if (close (fd) == -1) {
6384 exit (EXIT_FAILURE);
6386 if (guestfs_add_drive (g, filename) == -1) {
6387 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6388 exit (EXIT_FAILURE);
6391 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6392 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6393 exit (EXIT_FAILURE);
6396 if (guestfs_launch (g) == -1) {
6397 printf (\"guestfs_launch FAILED\\n\");
6398 exit (EXIT_FAILURE);
6401 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6404 /* Cancel previous alarm. */
6409 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6413 pr " test_num++;\n";
6414 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6415 pr " if (%s () == -1) {\n" test_name;
6416 pr " printf (\"%s FAILED\\n\");\n" test_name;
6417 pr " n_failed++;\n";
6422 pr " guestfs_close (g);\n";
6423 pr " unlink (\"test1.img\");\n";
6424 pr " unlink (\"test2.img\");\n";
6425 pr " unlink (\"test3.img\");\n";
6428 pr " if (n_failed > 0) {\n";
6429 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6430 pr " exit (EXIT_FAILURE);\n";
6434 pr " exit (EXIT_SUCCESS);\n";
6437 and generate_one_test name flags i (init, prereq, test) =
6438 let test_name = sprintf "test_%s_%d" name i in
6441 static int %s_skip (void)
6445 str = getenv (\"TEST_ONLY\");
6447 return strstr (str, \"%s\") == NULL;
6448 str = getenv (\"SKIP_%s\");
6449 if (str && STREQ (str, \"1\")) return 1;
6450 str = getenv (\"SKIP_TEST_%s\");
6451 if (str && STREQ (str, \"1\")) return 1;
6455 " test_name name (String.uppercase test_name) (String.uppercase name);
6458 | Disabled | Always -> ()
6459 | If code | Unless code ->
6460 pr "static int %s_prereq (void)\n" test_name;
6468 static int %s (void)
6471 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6475 " test_name test_name test_name;
6477 (* Optional functions should only be tested if the relevant
6478 * support is available in the daemon.
6484 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6486 pr " suppress_error = 1;\n";
6487 pr " r = guestfs_available (g, (char **) groups);\n";
6488 pr " suppress_error = 0;\n";
6489 pr " if (r == -1) {\n";
6490 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6499 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6501 pr " if (! %s_prereq ()) {\n" test_name;
6502 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6506 generate_one_test_body name i test_name init test;
6508 pr " if (%s_prereq ()) {\n" test_name;
6509 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6513 generate_one_test_body name i test_name init test;
6515 generate_one_test_body name i test_name init test
6523 and generate_one_test_body name i test_name init test =
6525 | InitNone (* XXX at some point, InitNone and InitEmpty became
6526 * folded together as the same thing. Really we should
6527 * make InitNone do nothing at all, but the tests may
6528 * need to be checked to make sure this is OK.
6531 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6532 List.iter (generate_test_command_call test_name)
6533 [["blockdev_setrw"; "/dev/sda"];
6537 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6538 List.iter (generate_test_command_call test_name)
6539 [["blockdev_setrw"; "/dev/sda"];
6542 ["part_disk"; "/dev/sda"; "mbr"]]
6544 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6545 List.iter (generate_test_command_call test_name)
6546 [["blockdev_setrw"; "/dev/sda"];
6549 ["part_disk"; "/dev/sda"; "mbr"];
6550 ["mkfs"; "ext2"; "/dev/sda1"];
6551 ["mount_options"; ""; "/dev/sda1"; "/"]]
6552 | InitBasicFSonLVM ->
6553 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6555 List.iter (generate_test_command_call test_name)
6556 [["blockdev_setrw"; "/dev/sda"];
6559 ["part_disk"; "/dev/sda"; "mbr"];
6560 ["pvcreate"; "/dev/sda1"];
6561 ["vgcreate"; "VG"; "/dev/sda1"];
6562 ["lvcreate"; "LV"; "VG"; "8"];
6563 ["mkfs"; "ext2"; "/dev/VG/LV"];
6564 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6566 pr " /* InitISOFS for %s */\n" test_name;
6567 List.iter (generate_test_command_call test_name)
6568 [["blockdev_setrw"; "/dev/sda"];
6571 ["mount_ro"; "/dev/sdd"; "/"]]
6574 let get_seq_last = function
6576 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6579 let seq = List.rev seq in
6580 List.rev (List.tl seq), List.hd seq
6585 pr " /* TestRun for %s (%d) */\n" name i;
6586 List.iter (generate_test_command_call test_name) seq
6587 | TestOutput (seq, expected) ->
6588 pr " /* TestOutput for %s (%d) */\n" name i;
6589 pr " const char *expected = \"%s\";\n" (c_quote expected);
6590 let seq, last = get_seq_last seq in
6592 pr " if (STRNEQ (r, expected)) {\n";
6593 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6597 List.iter (generate_test_command_call test_name) seq;
6598 generate_test_command_call ~test test_name last
6599 | TestOutputList (seq, expected) ->
6600 pr " /* TestOutputList for %s (%d) */\n" name i;
6601 let seq, last = get_seq_last seq in
6605 pr " if (!r[%d]) {\n" i;
6606 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6607 pr " print_strings (r);\n";
6611 pr " const char *expected = \"%s\";\n" (c_quote str);
6612 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6613 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6618 pr " if (r[%d] != NULL) {\n" (List.length expected);
6619 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6621 pr " print_strings (r);\n";
6625 List.iter (generate_test_command_call test_name) seq;
6626 generate_test_command_call ~test test_name last
6627 | TestOutputListOfDevices (seq, expected) ->
6628 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6629 let seq, last = get_seq_last seq in
6633 pr " if (!r[%d]) {\n" i;
6634 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6635 pr " print_strings (r);\n";
6639 pr " const char *expected = \"%s\";\n" (c_quote str);
6640 pr " r[%d][5] = 's';\n" i;
6641 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6642 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6647 pr " if (r[%d] != NULL) {\n" (List.length expected);
6648 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6650 pr " print_strings (r);\n";
6654 List.iter (generate_test_command_call test_name) seq;
6655 generate_test_command_call ~test test_name last
6656 | TestOutputInt (seq, expected) ->
6657 pr " /* TestOutputInt for %s (%d) */\n" name i;
6658 let seq, last = get_seq_last seq in
6660 pr " if (r != %d) {\n" expected;
6661 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6667 List.iter (generate_test_command_call test_name) seq;
6668 generate_test_command_call ~test test_name last
6669 | TestOutputIntOp (seq, op, expected) ->
6670 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6671 let seq, last = get_seq_last seq in
6673 pr " if (! (r %s %d)) {\n" op expected;
6674 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6675 test_name op expected;
6680 List.iter (generate_test_command_call test_name) seq;
6681 generate_test_command_call ~test test_name last
6682 | TestOutputTrue seq ->
6683 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6684 let seq, last = get_seq_last seq in
6687 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6692 List.iter (generate_test_command_call test_name) seq;
6693 generate_test_command_call ~test test_name last
6694 | TestOutputFalse seq ->
6695 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6696 let seq, last = get_seq_last seq in
6699 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6704 List.iter (generate_test_command_call test_name) seq;
6705 generate_test_command_call ~test test_name last
6706 | TestOutputLength (seq, expected) ->
6707 pr " /* TestOutputLength for %s (%d) */\n" name i;
6708 let seq, last = get_seq_last seq in
6711 pr " for (j = 0; j < %d; ++j)\n" expected;
6712 pr " if (r[j] == NULL) {\n";
6713 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6715 pr " print_strings (r);\n";
6718 pr " if (r[j] != NULL) {\n";
6719 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6721 pr " print_strings (r);\n";
6725 List.iter (generate_test_command_call test_name) seq;
6726 generate_test_command_call ~test test_name last
6727 | TestOutputBuffer (seq, expected) ->
6728 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6729 pr " const char *expected = \"%s\";\n" (c_quote expected);
6730 let seq, last = get_seq_last seq in
6731 let len = String.length expected in
6733 pr " if (size != %d) {\n" len;
6734 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6737 pr " if (STRNEQLEN (r, expected, size)) {\n";
6738 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6742 List.iter (generate_test_command_call test_name) seq;
6743 generate_test_command_call ~test test_name last
6744 | TestOutputStruct (seq, checks) ->
6745 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6746 let seq, last = get_seq_last seq in
6750 | CompareWithInt (field, expected) ->
6751 pr " if (r->%s != %d) {\n" field expected;
6752 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6753 test_name field expected;
6754 pr " (int) r->%s);\n" field;
6757 | CompareWithIntOp (field, op, expected) ->
6758 pr " if (!(r->%s %s %d)) {\n" field op expected;
6759 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6760 test_name field op expected;
6761 pr " (int) r->%s);\n" field;
6764 | CompareWithString (field, expected) ->
6765 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6766 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6767 test_name field expected;
6768 pr " r->%s);\n" field;
6771 | CompareFieldsIntEq (field1, field2) ->
6772 pr " if (r->%s != r->%s) {\n" field1 field2;
6773 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6774 test_name field1 field2;
6775 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6778 | CompareFieldsStrEq (field1, field2) ->
6779 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6780 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6781 test_name field1 field2;
6782 pr " r->%s, r->%s);\n" field1 field2;
6787 List.iter (generate_test_command_call test_name) seq;
6788 generate_test_command_call ~test test_name last
6789 | TestLastFail seq ->
6790 pr " /* TestLastFail for %s (%d) */\n" name i;
6791 let seq, last = get_seq_last seq in
6792 List.iter (generate_test_command_call test_name) seq;
6793 generate_test_command_call test_name ~expect_error:true last
6795 (* Generate the code to run a command, leaving the result in 'r'.
6796 * If you expect to get an error then you should set expect_error:true.
6798 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6800 | [] -> assert false
6802 (* Look up the command to find out what args/ret it has. *)
6805 let _, style, _, _, _, _, _ =
6806 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6809 failwithf "%s: in test, command %s was not found" test_name name in
6811 if List.length (snd style) <> List.length args then
6812 failwithf "%s: in test, wrong number of args given to %s"
6819 | OptString n, "NULL" -> ()
6822 | Dev_or_Path n, arg
6824 | OptString n, arg ->
6825 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6829 | FileIn _, _ | FileOut _, _ -> ()
6830 | StringList n, "" | DeviceList n, "" ->
6831 pr " const char *const %s[1] = { NULL };\n" n
6832 | StringList n, arg | DeviceList n, arg ->
6833 let strs = string_split " " arg in
6836 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
6838 pr " const char *const %s[] = {\n" n;
6840 fun i _ -> pr " %s_%d,\n" n i
6844 ) (List.combine (snd style) args);
6847 match fst style with
6848 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6849 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6850 | RConstString _ | RConstOptString _ ->
6851 pr " const char *r;\n"; "NULL"
6852 | RString _ -> pr " char *r;\n"; "NULL"
6853 | RStringList _ | RHashtable _ ->
6857 | RStruct (_, typ) ->
6858 pr " struct guestfs_%s *r;\n" typ; "NULL"
6859 | RStructList (_, typ) ->
6860 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6863 pr " size_t size;\n";
6866 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
6867 pr " r = guestfs_%s (g" name;
6869 (* Generate the parameters. *)
6872 | OptString _, "NULL" -> pr ", NULL"
6874 | Device n, _ | Dev_or_Path n, _
6878 | FileIn _, arg | FileOut _, arg ->
6879 pr ", \"%s\"" (c_quote arg)
6880 | StringList n, _ | DeviceList n, _ ->
6881 pr ", (char **) %s" n
6884 try int_of_string arg
6885 with Failure "int_of_string" ->
6886 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6890 try Int64.of_string arg
6891 with Failure "int_of_string" ->
6892 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6895 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6896 ) (List.combine (snd style) args);
6898 (match fst style with
6899 | RBufferOut _ -> pr ", &size"
6905 if not expect_error then
6906 pr " if (r == %s)\n" error_code
6908 pr " if (r != %s)\n" error_code;
6911 (* Insert the test code. *)
6917 (match fst style with
6918 | RErr | RInt _ | RInt64 _ | RBool _
6919 | RConstString _ | RConstOptString _ -> ()
6920 | RString _ | RBufferOut _ -> pr " free (r);\n"
6921 | RStringList _ | RHashtable _ ->
6922 pr " for (i = 0; r[i] != NULL; ++i)\n";
6923 pr " free (r[i]);\n";
6925 | RStruct (_, typ) ->
6926 pr " guestfs_free_%s (r);\n" typ
6927 | RStructList (_, typ) ->
6928 pr " guestfs_free_%s_list (r);\n" typ
6934 let str = replace_str str "\r" "\\r" in
6935 let str = replace_str str "\n" "\\n" in
6936 let str = replace_str str "\t" "\\t" in
6937 let str = replace_str str "\000" "\\0" in
6940 (* Generate a lot of different functions for guestfish. *)
6941 and generate_fish_cmds () =
6942 generate_header CStyle GPLv2plus;
6946 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6948 let all_functions_sorted =
6950 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6951 ) all_functions_sorted in
6953 pr "#include <config.h>\n";
6955 pr "#include <stdio.h>\n";
6956 pr "#include <stdlib.h>\n";
6957 pr "#include <string.h>\n";
6958 pr "#include <inttypes.h>\n";
6960 pr "#include <guestfs.h>\n";
6961 pr "#include \"c-ctype.h\"\n";
6962 pr "#include \"full-write.h\"\n";
6963 pr "#include \"xstrtol.h\"\n";
6964 pr "#include \"fish.h\"\n";
6967 (* list_commands function, which implements guestfish -h *)
6968 pr "void list_commands (void)\n";
6970 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6971 pr " list_builtin_commands ();\n";
6973 fun (name, _, _, flags, _, shortdesc, _) ->
6974 let name = replace_char name '_' '-' in
6975 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6977 ) all_functions_sorted;
6978 pr " printf (\" %%s\\n\",";
6979 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6983 (* display_command function, which implements guestfish -h cmd *)
6984 pr "void display_command (const char *cmd)\n";
6987 fun (name, style, _, flags, _, shortdesc, longdesc) ->
6988 let name2 = replace_char name '_' '-' in
6990 try find_map (function FishAlias n -> Some n | _ -> None) flags
6991 with Not_found -> name in
6992 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6994 match snd style with
6998 name2 (String.concat " " (List.map name_of_argt args)) in
7001 if List.mem ProtocolLimitWarning flags then
7002 ("\n\n" ^ protocol_limit_warning)
7005 (* For DangerWillRobinson commands, we should probably have
7006 * guestfish prompt before allowing you to use them (especially
7007 * in interactive mode). XXX
7011 if List.mem DangerWillRobinson flags then
7012 ("\n\n" ^ danger_will_robinson)
7017 match deprecation_notice flags with
7019 | Some txt -> "\n\n" ^ txt in
7021 let describe_alias =
7022 if name <> alias then
7023 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7027 pr "STRCASEEQ (cmd, \"%s\")" name;
7028 if name <> name2 then
7029 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7030 if name <> alias then
7031 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7033 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7035 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7036 "=head1 DESCRIPTION\n\n" ^
7037 longdesc ^ warnings ^ describe_alias);
7040 pr " display_builtin_command (cmd);\n";
7044 let emit_print_list_function typ =
7045 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7048 pr " unsigned int i;\n";
7050 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7051 pr " printf (\"[%%d] = {\\n\", i);\n";
7052 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7053 pr " printf (\"}\\n\");\n";
7059 (* print_* functions *)
7063 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7065 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7068 pr " unsigned int i;\n";
7074 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7076 pr " printf (\"%%s%s: \", indent);\n" name;
7077 pr " for (i = 0; i < 32; ++i)\n";
7078 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7079 pr " printf (\"\\n\");\n"
7081 pr " printf (\"%%s%s: \", indent);\n" name;
7082 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7083 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7084 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7086 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7087 pr " printf (\"\\n\");\n"
7088 | name, (FUInt64|FBytes) ->
7089 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7092 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7095 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7098 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7101 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7103 | name, FOptPercent ->
7104 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7105 typ name name typ name;
7106 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7112 (* Emit a print_TYPE_list function definition only if that function is used. *)
7115 | typ, (RStructListOnly | RStructAndList) ->
7116 (* generate the function for typ *)
7117 emit_print_list_function typ
7118 | typ, _ -> () (* empty *)
7119 ) (rstructs_used_by all_functions);
7121 (* Emit a print_TYPE function definition only if that function is used. *)
7124 | typ, (RStructOnly | RStructAndList) ->
7125 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7127 pr " print_%s_indent (%s, \"\");\n" typ typ;
7130 | typ, _ -> () (* empty *)
7131 ) (rstructs_used_by all_functions);
7133 (* run_<action> actions *)
7135 fun (name, style, _, flags, _, _, _) ->
7136 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7138 (match fst style with
7141 | RBool _ -> pr " int r;\n"
7142 | RInt64 _ -> pr " int64_t r;\n"
7143 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7144 | RString _ -> pr " char *r;\n"
7145 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7146 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7147 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7150 pr " size_t size;\n";
7158 | FileOut n -> pr " const char *%s;\n" n
7160 | Dev_or_Path n -> pr " char *%s;\n" n
7161 | StringList n | DeviceList n -> pr " char **%s;\n" n
7162 | Bool n -> pr " int %s;\n" n
7163 | Int n -> pr " int %s;\n" n
7164 | Int64 n -> pr " int64_t %s;\n" n
7167 (* Check and convert parameters. *)
7168 let argc_expected = List.length (snd style) in
7169 pr " if (argc != %d) {\n" argc_expected;
7170 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7172 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7176 let parse_integer fn fntyp rtyp range name i =
7178 pr " strtol_error xerr;\n";
7179 pr " %s r;\n" fntyp;
7181 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7182 pr " if (xerr != LONGINT_OK) {\n";
7183 pr " fprintf (stderr,\n";
7184 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7185 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7190 | Some (min, max, comment) ->
7191 pr " /* %s */\n" comment;
7192 pr " if (r < %s || r > %s) {\n" min max;
7193 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7197 pr " /* The check above should ensure this assignment does not overflow. */\n";
7199 pr " %s = r;\n" name;
7208 pr " %s = argv[%d];\n" name i
7210 | Dev_or_Path name ->
7211 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7212 pr " if (%s == NULL) return -1;\n" name
7214 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7217 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7220 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7222 | StringList name | DeviceList name ->
7223 pr " %s = parse_string_list (argv[%d]);\n" name i;
7224 pr " if (%s == NULL) return -1;\n" name;
7226 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7229 let min = "(-(2LL<<30))"
7230 and max = "((2LL<<30)-1)"
7232 "The Int type in the generator is a signed 31 bit int." in
7233 Some (min, max, comment) in
7234 parse_integer "xstrtoll" "long long" "int" range name i
7236 parse_integer "xstrtoll" "long long" "int64_t" None name i
7239 (* Call C API function. *)
7241 try find_map (function FishAction n -> Some n | _ -> None) flags
7242 with Not_found -> sprintf "guestfs_%s" name in
7244 generate_c_call_args ~handle:"g" style;
7249 | Device name | String name
7250 | OptString name | FileIn name | FileOut name | Bool name
7251 | Int name | Int64 name -> ()
7252 | Pathname name | Dev_or_Path name ->
7253 pr " free (%s);\n" name
7254 | StringList name | DeviceList name ->
7255 pr " free_strings (%s);\n" name
7258 (* Check return value for errors and display command results. *)
7259 (match fst style with
7260 | RErr -> pr " return r;\n"
7262 pr " if (r == -1) return -1;\n";
7263 pr " printf (\"%%d\\n\", r);\n";
7266 pr " if (r == -1) return -1;\n";
7267 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7270 pr " if (r == -1) return -1;\n";
7271 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7274 pr " if (r == NULL) return -1;\n";
7275 pr " printf (\"%%s\\n\", r);\n";
7277 | RConstOptString _ ->
7278 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7281 pr " if (r == NULL) return -1;\n";
7282 pr " printf (\"%%s\\n\", r);\n";
7286 pr " if (r == NULL) return -1;\n";
7287 pr " print_strings (r);\n";
7288 pr " free_strings (r);\n";
7290 | RStruct (_, typ) ->
7291 pr " if (r == NULL) return -1;\n";
7292 pr " print_%s (r);\n" typ;
7293 pr " guestfs_free_%s (r);\n" typ;
7295 | RStructList (_, typ) ->
7296 pr " if (r == NULL) return -1;\n";
7297 pr " print_%s_list (r);\n" typ;
7298 pr " guestfs_free_%s_list (r);\n" typ;
7301 pr " if (r == NULL) return -1;\n";
7302 pr " print_table (r);\n";
7303 pr " free_strings (r);\n";
7306 pr " if (r == NULL) return -1;\n";
7307 pr " if (full_write (1, r, size) != size) {\n";
7308 pr " perror (\"write\");\n";
7319 (* run_action function *)
7320 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7323 fun (name, _, _, flags, _, _, _) ->
7324 let name2 = replace_char name '_' '-' in
7326 try find_map (function FishAlias n -> Some n | _ -> None) flags
7327 with Not_found -> name in
7329 pr "STRCASEEQ (cmd, \"%s\")" name;
7330 if name <> name2 then
7331 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7332 if name <> alias then
7333 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7335 pr " return run_%s (cmd, argc, argv);\n" name;
7339 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7346 (* Readline completion for guestfish. *)
7347 and generate_fish_completion () =
7348 generate_header CStyle GPLv2plus;
7352 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7362 #ifdef HAVE_LIBREADLINE
7363 #include <readline/readline.h>
7368 #ifdef HAVE_LIBREADLINE
7370 static const char *const commands[] = {
7371 BUILTIN_COMMANDS_FOR_COMPLETION,
7374 (* Get the commands, including the aliases. They don't need to be
7375 * sorted - the generator() function just does a dumb linear search.
7379 fun (name, _, _, flags, _, _, _) ->
7380 let name2 = replace_char name '_' '-' in
7382 try find_map (function FishAlias n -> Some n | _ -> None) flags
7383 with Not_found -> name in
7385 if name <> alias then [name2; alias] else [name2]
7387 let commands = List.flatten commands in
7389 List.iter (pr " \"%s\",\n") commands;
7395 generator (const char *text, int state)
7397 static int index, len;
7402 len = strlen (text);
7405 rl_attempted_completion_over = 1;
7407 while ((name = commands[index]) != NULL) {
7409 if (STRCASEEQLEN (name, text, len))
7410 return strdup (name);
7416 #endif /* HAVE_LIBREADLINE */
7418 char **do_completion (const char *text, int start, int end)
7420 char **matches = NULL;
7422 #ifdef HAVE_LIBREADLINE
7423 rl_completion_append_character = ' ';
7426 matches = rl_completion_matches (text, generator);
7427 else if (complete_dest_paths)
7428 matches = rl_completion_matches (text, complete_dest_paths_generator);
7435 (* Generate the POD documentation for guestfish. *)
7436 and generate_fish_actions_pod () =
7437 let all_functions_sorted =
7439 fun (_, _, _, flags, _, _, _) ->
7440 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7441 ) all_functions_sorted in
7443 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7446 fun (name, style, _, flags, _, _, longdesc) ->
7448 Str.global_substitute rex (
7451 try Str.matched_group 1 s
7453 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7454 "C<" ^ replace_char sub '_' '-' ^ ">"
7456 let name = replace_char name '_' '-' in
7458 try find_map (function FishAlias n -> Some n | _ -> None) flags
7459 with Not_found -> name in
7461 pr "=head2 %s" name;
7462 if name <> alias then
7469 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7470 | OptString n -> pr " %s" n
7471 | StringList n | DeviceList n -> pr " '%s ...'" n
7472 | Bool _ -> pr " true|false"
7473 | Int n -> pr " %s" n
7474 | Int64 n -> pr " %s" n
7475 | FileIn n | FileOut n -> pr " (%s|-)" n
7479 pr "%s\n\n" longdesc;
7481 if List.exists (function FileIn _ | FileOut _ -> true
7482 | _ -> false) (snd style) then
7483 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7485 if List.mem ProtocolLimitWarning flags then
7486 pr "%s\n\n" protocol_limit_warning;
7488 if List.mem DangerWillRobinson flags then
7489 pr "%s\n\n" danger_will_robinson;
7491 match deprecation_notice flags with
7493 | Some txt -> pr "%s\n\n" txt
7494 ) all_functions_sorted
7496 (* Generate a C function prototype. *)
7497 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7498 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7500 ?handle name style =
7501 if extern then pr "extern ";
7502 if static then pr "static ";
7503 (match fst style with
7505 | RInt _ -> pr "int "
7506 | RInt64 _ -> pr "int64_t "
7507 | RBool _ -> pr "int "
7508 | RConstString _ | RConstOptString _ -> pr "const char *"
7509 | RString _ | RBufferOut _ -> pr "char *"
7510 | RStringList _ | RHashtable _ -> pr "char **"
7511 | RStruct (_, typ) ->
7512 if not in_daemon then pr "struct guestfs_%s *" typ
7513 else pr "guestfs_int_%s *" typ
7514 | RStructList (_, typ) ->
7515 if not in_daemon then pr "struct guestfs_%s_list *" typ
7516 else pr "guestfs_int_%s_list *" typ
7518 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7519 pr "%s%s (" prefix name;
7520 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7523 let comma = ref false in
7526 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7530 if single_line then pr ", " else pr ",\n\t\t"
7537 | Device n | Dev_or_Path n
7541 pr "const char *%s" n
7542 | StringList n | DeviceList n ->
7544 pr "char *const *%s" n
7545 | Bool n -> next (); pr "int %s" n
7546 | Int n -> next (); pr "int %s" n
7547 | Int64 n -> next (); pr "int64_t %s" n
7550 if not in_daemon then (next (); pr "const char *%s" n)
7552 if is_RBufferOut then (next (); pr "size_t *size_r");
7555 if semicolon then pr ";";
7556 if newline then pr "\n"
7558 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7559 and generate_c_call_args ?handle ?(decl = false) style =
7561 let comma = ref false in
7563 if !comma then pr ", ";
7568 | Some handle -> pr "%s" handle; comma := true
7573 pr "%s" (name_of_argt arg)
7575 (* For RBufferOut calls, add implicit &size parameter. *)
7577 match fst style with
7585 (* Generate the OCaml bindings interface. *)
7586 and generate_ocaml_mli () =
7587 generate_header OCamlStyle LGPLv2plus;
7590 (** For API documentation you should refer to the C API
7591 in the guestfs(3) manual page. The OCaml API uses almost
7592 exactly the same calls. *)
7595 (** A [guestfs_h] handle. *)
7597 exception Error of string
7598 (** This exception is raised when there is an error. *)
7600 exception Handle_closed of string
7601 (** This exception is raised if you use a {!Guestfs.t} handle
7602 after calling {!close} on it. The string is the name of
7605 val create : unit -> t
7606 (** Create a {!Guestfs.t} handle. *)
7608 val close : t -> unit
7609 (** Close the {!Guestfs.t} handle and free up all resources used
7612 Handles are closed by the garbage collector when they become
7613 unreferenced, but callers can call this in order to provide
7614 predictable cleanup. *)
7617 generate_ocaml_structure_decls ();
7621 fun (name, style, _, _, _, shortdesc, _) ->
7622 generate_ocaml_prototype name style;
7623 pr "(** %s *)\n" shortdesc;
7625 ) all_functions_sorted
7627 (* Generate the OCaml bindings implementation. *)
7628 and generate_ocaml_ml () =
7629 generate_header OCamlStyle LGPLv2plus;
7634 exception Error of string
7635 exception Handle_closed of string
7637 external create : unit -> t = \"ocaml_guestfs_create\"
7638 external close : t -> unit = \"ocaml_guestfs_close\"
7640 (* Give the exceptions names, so they can be raised from the C code. *)
7642 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7643 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7647 generate_ocaml_structure_decls ();
7651 fun (name, style, _, _, _, shortdesc, _) ->
7652 generate_ocaml_prototype ~is_external:true name style;
7653 ) all_functions_sorted
7655 (* Generate the OCaml bindings C implementation. *)
7656 and generate_ocaml_c () =
7657 generate_header CStyle LGPLv2plus;
7664 #include <caml/config.h>
7665 #include <caml/alloc.h>
7666 #include <caml/callback.h>
7667 #include <caml/fail.h>
7668 #include <caml/memory.h>
7669 #include <caml/mlvalues.h>
7670 #include <caml/signals.h>
7672 #include <guestfs.h>
7674 #include \"guestfs_c.h\"
7676 /* Copy a hashtable of string pairs into an assoc-list. We return
7677 * the list in reverse order, but hashtables aren't supposed to be
7680 static CAMLprim value
7681 copy_table (char * const * argv)
7684 CAMLlocal5 (rv, pairv, kv, vv, cons);
7688 for (i = 0; argv[i] != NULL; i += 2) {
7689 kv = caml_copy_string (argv[i]);
7690 vv = caml_copy_string (argv[i+1]);
7691 pairv = caml_alloc (2, 0);
7692 Store_field (pairv, 0, kv);
7693 Store_field (pairv, 1, vv);
7694 cons = caml_alloc (2, 0);
7695 Store_field (cons, 1, rv);
7697 Store_field (cons, 0, pairv);
7705 (* Struct copy functions. *)
7707 let emit_ocaml_copy_list_function typ =
7708 pr "static CAMLprim value\n";
7709 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7711 pr " CAMLparam0 ();\n";
7712 pr " CAMLlocal2 (rv, v);\n";
7713 pr " unsigned int i;\n";
7715 pr " if (%ss->len == 0)\n" typ;
7716 pr " CAMLreturn (Atom (0));\n";
7718 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7719 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7720 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7721 pr " caml_modify (&Field (rv, i), v);\n";
7723 pr " CAMLreturn (rv);\n";
7731 let has_optpercent_col =
7732 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7734 pr "static CAMLprim value\n";
7735 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7737 pr " CAMLparam0 ();\n";
7738 if has_optpercent_col then
7739 pr " CAMLlocal3 (rv, v, v2);\n"
7741 pr " CAMLlocal2 (rv, v);\n";
7743 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7748 pr " v = caml_copy_string (%s->%s);\n" typ name
7750 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7751 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7754 pr " v = caml_alloc_string (32);\n";
7755 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7756 | name, (FBytes|FInt64|FUInt64) ->
7757 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7758 | name, (FInt32|FUInt32) ->
7759 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7760 | name, FOptPercent ->
7761 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7762 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7763 pr " v = caml_alloc (1, 0);\n";
7764 pr " Store_field (v, 0, v2);\n";
7765 pr " } else /* None */\n";
7766 pr " v = Val_int (0);\n";
7768 pr " v = Val_int (%s->%s);\n" typ name
7770 pr " Store_field (rv, %d, v);\n" i
7772 pr " CAMLreturn (rv);\n";
7777 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7780 | typ, (RStructListOnly | RStructAndList) ->
7781 (* generate the function for typ *)
7782 emit_ocaml_copy_list_function typ
7783 | typ, _ -> () (* empty *)
7784 ) (rstructs_used_by all_functions);
7788 fun (name, style, _, _, _, _, _) ->
7789 pr "/* Automatically generated wrapper for function\n";
7791 generate_ocaml_prototype name style;
7796 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7798 let needs_extra_vs =
7799 match fst style with RConstOptString _ -> true | _ -> false in
7801 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7802 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7803 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7806 pr "CAMLprim value\n";
7807 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7808 List.iter (pr ", value %s") (List.tl params);
7813 | [p1; p2; p3; p4; p5] ->
7814 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7815 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7816 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7817 pr " CAMLxparam%d (%s);\n"
7818 (List.length rest) (String.concat ", " rest)
7820 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7822 if not needs_extra_vs then
7823 pr " CAMLlocal1 (rv);\n"
7825 pr " CAMLlocal3 (rv, v, v2);\n";
7828 pr " guestfs_h *g = Guestfs_val (gv);\n";
7829 pr " if (g == NULL)\n";
7830 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
7836 | Device n | Dev_or_Path n
7840 pr " const char *%s = String_val (%sv);\n" n n
7842 pr " const char *%s =\n" n;
7843 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7845 | StringList n | DeviceList n ->
7846 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7848 pr " int %s = Bool_val (%sv);\n" n n
7850 pr " int %s = Int_val (%sv);\n" n n
7852 pr " int64_t %s = Int64_val (%sv);\n" n n
7855 match fst style with
7856 | RErr -> pr " int r;\n"; "-1"
7857 | RInt _ -> pr " int r;\n"; "-1"
7858 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7859 | RBool _ -> pr " int r;\n"; "-1"
7860 | RConstString _ | RConstOptString _ ->
7861 pr " const char *r;\n"; "NULL"
7862 | RString _ -> pr " char *r;\n"; "NULL"
7867 | RStruct (_, typ) ->
7868 pr " struct guestfs_%s *r;\n" typ; "NULL"
7869 | RStructList (_, typ) ->
7870 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7877 pr " size_t size;\n";
7881 pr " caml_enter_blocking_section ();\n";
7882 pr " r = guestfs_%s " name;
7883 generate_c_call_args ~handle:"g" style;
7885 pr " caml_leave_blocking_section ();\n";
7889 | StringList n | DeviceList n ->
7890 pr " ocaml_guestfs_free_strings (%s);\n" n;
7891 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7892 | Bool _ | Int _ | Int64 _
7893 | FileIn _ | FileOut _ -> ()
7896 pr " if (r == %s)\n" error_code;
7897 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7900 (match fst style with
7901 | RErr -> pr " rv = Val_unit;\n"
7902 | RInt _ -> pr " rv = Val_int (r);\n"
7904 pr " rv = caml_copy_int64 (r);\n"
7905 | RBool _ -> pr " rv = Val_bool (r);\n"
7907 pr " rv = caml_copy_string (r);\n"
7908 | RConstOptString _ ->
7909 pr " if (r) { /* Some string */\n";
7910 pr " v = caml_alloc (1, 0);\n";
7911 pr " v2 = caml_copy_string (r);\n";
7912 pr " Store_field (v, 0, v2);\n";
7913 pr " } else /* None */\n";
7914 pr " v = Val_int (0);\n";
7916 pr " rv = caml_copy_string (r);\n";
7919 pr " rv = caml_copy_string_array ((const char **) r);\n";
7920 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7922 | RStruct (_, typ) ->
7923 pr " rv = copy_%s (r);\n" typ;
7924 pr " guestfs_free_%s (r);\n" typ;
7925 | RStructList (_, typ) ->
7926 pr " rv = copy_%s_list (r);\n" typ;
7927 pr " guestfs_free_%s_list (r);\n" typ;
7929 pr " rv = copy_table (r);\n";
7930 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7933 pr " rv = caml_alloc_string (size);\n";
7934 pr " memcpy (String_val (rv), r, size);\n";
7937 pr " CAMLreturn (rv);\n";
7941 if List.length params > 5 then (
7942 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7943 pr "CAMLprim value ";
7944 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7945 pr "CAMLprim value\n";
7946 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7948 pr " return ocaml_guestfs_%s (argv[0]" name;
7949 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7954 ) all_functions_sorted
7956 and generate_ocaml_structure_decls () =
7959 pr "type %s = {\n" typ;
7962 | name, FString -> pr " %s : string;\n" name
7963 | name, FBuffer -> pr " %s : string;\n" name
7964 | name, FUUID -> pr " %s : string;\n" name
7965 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
7966 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
7967 | name, FChar -> pr " %s : char;\n" name
7968 | name, FOptPercent -> pr " %s : float option;\n" name
7974 and generate_ocaml_prototype ?(is_external = false) name style =
7975 if is_external then pr "external " else pr "val ";
7976 pr "%s : t -> " name;
7979 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7980 | OptString _ -> pr "string option -> "
7981 | StringList _ | DeviceList _ -> pr "string array -> "
7982 | Bool _ -> pr "bool -> "
7983 | Int _ -> pr "int -> "
7984 | Int64 _ -> pr "int64 -> "
7986 (match fst style with
7987 | RErr -> pr "unit" (* all errors are turned into exceptions *)
7988 | RInt _ -> pr "int"
7989 | RInt64 _ -> pr "int64"
7990 | RBool _ -> pr "bool"
7991 | RConstString _ -> pr "string"
7992 | RConstOptString _ -> pr "string option"
7993 | RString _ | RBufferOut _ -> pr "string"
7994 | RStringList _ -> pr "string array"
7995 | RStruct (_, typ) -> pr "%s" typ
7996 | RStructList (_, typ) -> pr "%s array" typ
7997 | RHashtable _ -> pr "(string * string) list"
7999 if is_external then (
8001 if List.length (snd style) + 1 > 5 then
8002 pr "\"ocaml_guestfs_%s_byte\" " name;
8003 pr "\"ocaml_guestfs_%s\"" name
8007 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8008 and generate_perl_xs () =
8009 generate_header CStyle LGPLv2plus;
8012 #include \"EXTERN.h\"
8016 #include <guestfs.h>
8019 #define PRId64 \"lld\"
8023 my_newSVll(long long val) {
8024 #ifdef USE_64_BIT_ALL
8025 return newSViv(val);
8029 len = snprintf(buf, 100, \"%%\" PRId64, val);
8030 return newSVpv(buf, len);
8035 #define PRIu64 \"llu\"
8039 my_newSVull(unsigned long long val) {
8040 #ifdef USE_64_BIT_ALL
8041 return newSVuv(val);
8045 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8046 return newSVpv(buf, len);
8050 /* http://www.perlmonks.org/?node_id=680842 */
8052 XS_unpack_charPtrPtr (SV *arg) {
8057 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8058 croak (\"array reference expected\");
8060 av = (AV *)SvRV (arg);
8061 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8063 croak (\"malloc failed\");
8065 for (i = 0; i <= av_len (av); i++) {
8066 SV **elem = av_fetch (av, i, 0);
8068 if (!elem || !*elem)
8069 croak (\"missing element in list\");
8071 ret[i] = SvPV_nolen (*elem);
8079 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8086 RETVAL = guestfs_create ();
8088 croak (\"could not create guestfs handle\");
8089 guestfs_set_error_handler (RETVAL, NULL, NULL);
8102 fun (name, style, _, _, _, _, _) ->
8103 (match fst style with
8104 | RErr -> pr "void\n"
8105 | RInt _ -> pr "SV *\n"
8106 | RInt64 _ -> pr "SV *\n"
8107 | RBool _ -> pr "SV *\n"
8108 | RConstString _ -> pr "SV *\n"
8109 | RConstOptString _ -> pr "SV *\n"
8110 | RString _ -> pr "SV *\n"
8111 | RBufferOut _ -> pr "SV *\n"
8113 | RStruct _ | RStructList _
8115 pr "void\n" (* all lists returned implictly on the stack *)
8117 (* Call and arguments. *)
8119 generate_c_call_args ~handle:"g" ~decl:true style;
8121 pr " guestfs_h *g;\n";
8125 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8128 (* http://www.perlmonks.org/?node_id=554277
8129 * Note that the implicit handle argument means we have
8130 * to add 1 to the ST(x) operator.
8132 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8133 | StringList n | DeviceList n -> pr " char **%s;\n" n
8134 | Bool n -> pr " int %s;\n" n
8135 | Int n -> pr " int %s;\n" n
8136 | Int64 n -> pr " int64_t %s;\n" n
8139 let do_cleanups () =
8142 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8143 | Bool _ | Int _ | Int64 _
8144 | FileIn _ | FileOut _ -> ()
8145 | StringList n | DeviceList n -> pr " free (%s);\n" n
8150 (match fst style with
8155 pr " r = guestfs_%s " name;
8156 generate_c_call_args ~handle:"g" style;
8159 pr " if (r == -1)\n";
8160 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8166 pr " %s = guestfs_%s " n name;
8167 generate_c_call_args ~handle:"g" style;
8170 pr " if (%s == -1)\n" n;
8171 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8172 pr " RETVAL = newSViv (%s);\n" n;
8177 pr " int64_t %s;\n" n;
8179 pr " %s = guestfs_%s " n name;
8180 generate_c_call_args ~handle:"g" style;
8183 pr " if (%s == -1)\n" n;
8184 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8185 pr " RETVAL = my_newSVll (%s);\n" n;
8190 pr " const char *%s;\n" n;
8192 pr " %s = guestfs_%s " n name;
8193 generate_c_call_args ~handle:"g" style;
8196 pr " if (%s == NULL)\n" n;
8197 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8198 pr " RETVAL = newSVpv (%s, 0);\n" n;
8201 | RConstOptString n ->
8203 pr " const char *%s;\n" n;
8205 pr " %s = guestfs_%s " n name;
8206 generate_c_call_args ~handle:"g" style;
8209 pr " if (%s == NULL)\n" n;
8210 pr " RETVAL = &PL_sv_undef;\n";
8212 pr " RETVAL = newSVpv (%s, 0);\n" n;
8217 pr " char *%s;\n" n;
8219 pr " %s = guestfs_%s " n name;
8220 generate_c_call_args ~handle:"g" style;
8223 pr " if (%s == NULL)\n" n;
8224 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8225 pr " RETVAL = newSVpv (%s, 0);\n" n;
8226 pr " free (%s);\n" n;
8229 | RStringList n | RHashtable n ->
8231 pr " char **%s;\n" n;
8234 pr " %s = guestfs_%s " n name;
8235 generate_c_call_args ~handle:"g" style;
8238 pr " if (%s == NULL)\n" n;
8239 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8240 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8241 pr " EXTEND (SP, n);\n";
8242 pr " for (i = 0; i < n; ++i) {\n";
8243 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8244 pr " free (%s[i]);\n" n;
8246 pr " free (%s);\n" n;
8247 | RStruct (n, typ) ->
8248 let cols = cols_of_struct typ in
8249 generate_perl_struct_code typ cols name style n do_cleanups
8250 | RStructList (n, typ) ->
8251 let cols = cols_of_struct typ in
8252 generate_perl_struct_list_code typ cols name style n do_cleanups
8255 pr " char *%s;\n" n;
8256 pr " size_t size;\n";
8258 pr " %s = guestfs_%s " n name;
8259 generate_c_call_args ~handle:"g" style;
8262 pr " if (%s == NULL)\n" n;
8263 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8264 pr " RETVAL = newSVpv (%s, size);\n" n;
8265 pr " free (%s);\n" n;
8273 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8275 pr " struct guestfs_%s_list *%s;\n" typ n;
8279 pr " %s = guestfs_%s " n name;
8280 generate_c_call_args ~handle:"g" style;
8283 pr " if (%s == NULL)\n" n;
8284 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8285 pr " EXTEND (SP, %s->len);\n" n;
8286 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8287 pr " hv = newHV ();\n";
8291 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8292 name (String.length name) n name
8294 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8295 name (String.length name) n name
8297 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8298 name (String.length name) n name n name
8299 | name, (FBytes|FUInt64) ->
8300 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8301 name (String.length name) n name
8303 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8304 name (String.length name) n name
8305 | name, (FInt32|FUInt32) ->
8306 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8307 name (String.length name) n name
8309 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8310 name (String.length name) n name
8311 | name, FOptPercent ->
8312 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8313 name (String.length name) n name
8315 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8317 pr " guestfs_free_%s_list (%s);\n" typ n
8319 and generate_perl_struct_code typ cols name style n do_cleanups =
8321 pr " struct guestfs_%s *%s;\n" typ n;
8323 pr " %s = guestfs_%s " n name;
8324 generate_c_call_args ~handle:"g" style;
8327 pr " if (%s == NULL)\n" n;
8328 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8329 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8331 fun ((name, _) as col) ->
8332 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8336 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8339 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8342 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8344 | name, (FBytes|FUInt64) ->
8345 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8348 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8350 | name, (FInt32|FUInt32) ->
8351 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8354 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8356 | name, FOptPercent ->
8357 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8360 pr " free (%s);\n" n
8362 (* Generate Sys/Guestfs.pm. *)
8363 and generate_perl_pm () =
8364 generate_header HashStyle LGPLv2plus;
8371 Sys::Guestfs - Perl bindings for libguestfs
8377 my $h = Sys::Guestfs->new ();
8378 $h->add_drive ('guest.img');
8380 $h->mount ('/dev/sda1', '/');
8381 $h->touch ('/hello');
8386 The C<Sys::Guestfs> module provides a Perl XS binding to the
8387 libguestfs API for examining and modifying virtual machine
8390 Amongst the things this is good for: making batch configuration
8391 changes to guests, getting disk used/free statistics (see also:
8392 virt-df), migrating between virtualization systems (see also:
8393 virt-p2v), performing partial backups, performing partial guest
8394 clones, cloning guests and changing registry/UUID/hostname info, and
8397 Libguestfs uses Linux kernel and qemu code, and can access any type of
8398 guest filesystem that Linux and qemu can, including but not limited
8399 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8400 schemes, qcow, qcow2, vmdk.
8402 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8403 LVs, what filesystem is in each LV, etc.). It can also run commands
8404 in the context of the guest. Also you can access filesystems over
8407 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8408 functions for using libguestfs from Perl, including integration
8413 All errors turn into calls to C<croak> (see L<Carp(3)>).
8421 package Sys::Guestfs;
8427 XSLoader::load ('Sys::Guestfs');
8429 =item $h = Sys::Guestfs->new ();
8431 Create a new guestfs handle.
8437 my $class = ref ($proto) || $proto;
8439 my $self = Sys::Guestfs::_create ();
8440 bless $self, $class;
8446 (* Actions. We only need to print documentation for these as
8447 * they are pulled in from the XS code automatically.
8450 fun (name, style, _, flags, _, _, longdesc) ->
8451 if not (List.mem NotInDocs flags) then (
8452 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8454 generate_perl_prototype name style;
8456 pr "%s\n\n" longdesc;
8457 if List.mem ProtocolLimitWarning flags then
8458 pr "%s\n\n" protocol_limit_warning;
8459 if List.mem DangerWillRobinson flags then
8460 pr "%s\n\n" danger_will_robinson;
8461 match deprecation_notice flags with
8463 | Some txt -> pr "%s\n\n" txt
8465 ) all_functions_sorted;
8477 Copyright (C) %s Red Hat Inc.
8481 Please see the file COPYING.LIB for the full license.
8487 L<http://libguestfs.org>,
8488 L<Sys::Guestfs::Lib(3)>.
8493 and generate_perl_prototype name style =
8494 (match fst style with
8502 | RBufferOut n -> pr "$%s = " n
8504 | RHashtable n -> pr "%%%s = " n
8506 | RStructList (n,_) -> pr "@%s = " n
8509 let comma = ref false in
8512 if !comma then pr ", ";
8515 | Pathname n | Device n | Dev_or_Path n | String n
8516 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8518 | StringList n | DeviceList n ->
8523 (* Generate Python C module. *)
8524 and generate_python_c () =
8525 generate_header CStyle LGPLv2plus;
8534 #include \"guestfs.h\"
8542 get_handle (PyObject *obj)
8545 assert (obj != Py_None);
8546 return ((Pyguestfs_Object *) obj)->g;
8550 put_handle (guestfs_h *g)
8554 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8557 /* This list should be freed (but not the strings) after use. */
8559 get_string_list (PyObject *obj)
8566 if (!PyList_Check (obj)) {
8567 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8571 len = PyList_Size (obj);
8572 r = malloc (sizeof (char *) * (len+1));
8574 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8578 for (i = 0; i < len; ++i)
8579 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8586 put_string_list (char * const * const argv)
8591 for (argc = 0; argv[argc] != NULL; ++argc)
8594 list = PyList_New (argc);
8595 for (i = 0; i < argc; ++i)
8596 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8602 put_table (char * const * const argv)
8604 PyObject *list, *item;
8607 for (argc = 0; argv[argc] != NULL; ++argc)
8610 list = PyList_New (argc >> 1);
8611 for (i = 0; i < argc; i += 2) {
8612 item = PyTuple_New (2);
8613 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8614 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8615 PyList_SetItem (list, i >> 1, item);
8622 free_strings (char **argv)
8626 for (argc = 0; argv[argc] != NULL; ++argc)
8632 py_guestfs_create (PyObject *self, PyObject *args)
8636 g = guestfs_create ();
8638 PyErr_SetString (PyExc_RuntimeError,
8639 \"guestfs.create: failed to allocate handle\");
8642 guestfs_set_error_handler (g, NULL, NULL);
8643 return put_handle (g);
8647 py_guestfs_close (PyObject *self, PyObject *args)
8652 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8654 g = get_handle (py_g);
8658 Py_INCREF (Py_None);
8664 let emit_put_list_function typ =
8665 pr "static PyObject *\n";
8666 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8668 pr " PyObject *list;\n";
8671 pr " list = PyList_New (%ss->len);\n" typ;
8672 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8673 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8674 pr " return list;\n";
8679 (* Structures, turned into Python dictionaries. *)
8682 pr "static PyObject *\n";
8683 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8685 pr " PyObject *dict;\n";
8687 pr " dict = PyDict_New ();\n";
8691 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8692 pr " PyString_FromString (%s->%s));\n"
8695 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8696 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8699 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8700 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8702 | name, (FBytes|FUInt64) ->
8703 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8704 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8707 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8708 pr " PyLong_FromLongLong (%s->%s));\n"
8711 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8712 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8715 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8716 pr " PyLong_FromLong (%s->%s));\n"
8718 | name, FOptPercent ->
8719 pr " if (%s->%s >= 0)\n" typ name;
8720 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8721 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8724 pr " Py_INCREF (Py_None);\n";
8725 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8728 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8729 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8731 pr " return dict;\n";
8737 (* Emit a put_TYPE_list function definition only if that function is used. *)
8740 | typ, (RStructListOnly | RStructAndList) ->
8741 (* generate the function for typ *)
8742 emit_put_list_function typ
8743 | typ, _ -> () (* empty *)
8744 ) (rstructs_used_by all_functions);
8746 (* Python wrapper functions. *)
8748 fun (name, style, _, _, _, _, _) ->
8749 pr "static PyObject *\n";
8750 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8753 pr " PyObject *py_g;\n";
8754 pr " guestfs_h *g;\n";
8755 pr " PyObject *py_r;\n";
8758 match fst style with
8759 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8760 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8761 | RConstString _ | RConstOptString _ ->
8762 pr " const char *r;\n"; "NULL"
8763 | RString _ -> pr " char *r;\n"; "NULL"
8764 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8765 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8766 | RStructList (_, typ) ->
8767 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8770 pr " size_t size;\n";
8775 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8776 pr " const char *%s;\n" n
8777 | OptString n -> pr " const char *%s;\n" n
8778 | StringList n | DeviceList n ->
8779 pr " PyObject *py_%s;\n" n;
8780 pr " char **%s;\n" n
8781 | Bool n -> pr " int %s;\n" n
8782 | Int n -> pr " int %s;\n" n
8783 | Int64 n -> pr " long long %s;\n" n
8788 (* Convert the parameters. *)
8789 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8792 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8793 | OptString _ -> pr "z"
8794 | StringList _ | DeviceList _ -> pr "O"
8795 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8797 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8798 * emulate C's int/long/long long in Python?
8801 pr ":guestfs_%s\",\n" name;
8805 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8806 | OptString n -> pr ", &%s" n
8807 | StringList n | DeviceList n -> pr ", &py_%s" n
8808 | Bool n -> pr ", &%s" n
8809 | Int n -> pr ", &%s" n
8810 | Int64 n -> pr ", &%s" n
8814 pr " return NULL;\n";
8816 pr " g = get_handle (py_g);\n";
8819 | Pathname _ | Device _ | Dev_or_Path _ | String _
8820 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8821 | StringList n | DeviceList n ->
8822 pr " %s = get_string_list (py_%s);\n" n n;
8823 pr " if (!%s) return NULL;\n" n
8828 pr " r = guestfs_%s " name;
8829 generate_c_call_args ~handle:"g" style;
8834 | Pathname _ | Device _ | Dev_or_Path _ | String _
8835 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8836 | StringList n | DeviceList n ->
8837 pr " free (%s);\n" n
8840 pr " if (r == %s) {\n" error_code;
8841 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8842 pr " return NULL;\n";
8846 (match fst style with
8848 pr " Py_INCREF (Py_None);\n";
8849 pr " py_r = Py_None;\n"
8851 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
8852 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
8853 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
8854 | RConstOptString _ ->
8856 pr " py_r = PyString_FromString (r);\n";
8858 pr " Py_INCREF (Py_None);\n";
8859 pr " py_r = Py_None;\n";
8862 pr " py_r = PyString_FromString (r);\n";
8865 pr " py_r = put_string_list (r);\n";
8866 pr " free_strings (r);\n"
8867 | RStruct (_, typ) ->
8868 pr " py_r = put_%s (r);\n" typ;
8869 pr " guestfs_free_%s (r);\n" typ
8870 | RStructList (_, typ) ->
8871 pr " py_r = put_%s_list (r);\n" typ;
8872 pr " guestfs_free_%s_list (r);\n" typ
8874 pr " py_r = put_table (r);\n";
8875 pr " free_strings (r);\n"
8877 pr " py_r = PyString_FromStringAndSize (r, size);\n";
8881 pr " return py_r;\n";
8886 (* Table of functions. *)
8887 pr "static PyMethodDef methods[] = {\n";
8888 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8889 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8891 fun (name, _, _, _, _, _, _) ->
8892 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8895 pr " { NULL, NULL, 0, NULL }\n";
8899 (* Init function. *)
8902 initlibguestfsmod (void)
8904 static int initialized = 0;
8906 if (initialized) return;
8907 Py_InitModule ((char *) \"libguestfsmod\", methods);
8912 (* Generate Python module. *)
8913 and generate_python_py () =
8914 generate_header HashStyle LGPLv2plus;
8917 u\"\"\"Python bindings for libguestfs
8920 g = guestfs.GuestFS ()
8921 g.add_drive (\"guest.img\")
8923 parts = g.list_partitions ()
8925 The guestfs module provides a Python binding to the libguestfs API
8926 for examining and modifying virtual machine disk images.
8928 Amongst the things this is good for: making batch configuration
8929 changes to guests, getting disk used/free statistics (see also:
8930 virt-df), migrating between virtualization systems (see also:
8931 virt-p2v), performing partial backups, performing partial guest
8932 clones, cloning guests and changing registry/UUID/hostname info, and
8935 Libguestfs uses Linux kernel and qemu code, and can access any type of
8936 guest filesystem that Linux and qemu can, including but not limited
8937 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8938 schemes, qcow, qcow2, vmdk.
8940 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8941 LVs, what filesystem is in each LV, etc.). It can also run commands
8942 in the context of the guest. Also you can access filesystems over
8945 Errors which happen while using the API are turned into Python
8946 RuntimeError exceptions.
8948 To create a guestfs handle you usually have to perform the following
8951 # Create the handle, call add_drive at least once, and possibly
8952 # several times if the guest has multiple block devices:
8953 g = guestfs.GuestFS ()
8954 g.add_drive (\"guest.img\")
8956 # Launch the qemu subprocess and wait for it to become ready:
8959 # Now you can issue commands, for example:
8964 import libguestfsmod
8967 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8969 def __init__ (self):
8970 \"\"\"Create a new libguestfs handle.\"\"\"
8971 self._o = libguestfsmod.create ()
8974 libguestfsmod.close (self._o)
8979 fun (name, style, _, flags, _, _, longdesc) ->
8981 generate_py_call_args ~handle:"self" (snd style);
8984 if not (List.mem NotInDocs flags) then (
8985 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8987 match fst style with
8988 | RErr | RInt _ | RInt64 _ | RBool _
8989 | RConstOptString _ | RConstString _
8990 | RString _ | RBufferOut _ -> doc
8992 doc ^ "\n\nThis function returns a list of strings."
8993 | RStruct (_, typ) ->
8994 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8995 | RStructList (_, typ) ->
8996 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
8998 doc ^ "\n\nThis function returns a dictionary." in
9000 if List.mem ProtocolLimitWarning flags then
9001 doc ^ "\n\n" ^ protocol_limit_warning
9004 if List.mem DangerWillRobinson flags then
9005 doc ^ "\n\n" ^ danger_will_robinson
9008 match deprecation_notice flags with
9010 | Some txt -> doc ^ "\n\n" ^ txt in
9011 let doc = pod2text ~width:60 name doc in
9012 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9013 let doc = String.concat "\n " doc in
9014 pr " u\"\"\"%s\"\"\"\n" doc;
9016 pr " return libguestfsmod.%s " name;
9017 generate_py_call_args ~handle:"self._o" (snd style);
9022 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9023 and generate_py_call_args ~handle args =
9025 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9028 (* Useful if you need the longdesc POD text as plain text. Returns a
9031 * Because this is very slow (the slowest part of autogeneration),
9032 * we memoize the results.
9034 and pod2text ~width name longdesc =
9035 let key = width, name, longdesc in
9036 try Hashtbl.find pod2text_memo key
9038 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9039 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9041 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9042 let chan = open_process_in cmd in
9043 let lines = ref [] in
9045 let line = input_line chan in
9046 if i = 1 then (* discard the first line of output *)
9049 let line = triml line in
9050 lines := line :: !lines;
9053 let lines = try loop 1 with End_of_file -> List.rev !lines in
9055 (match close_process_in chan with
9058 failwithf "pod2text: process exited with non-zero status (%d)" i
9059 | WSIGNALED i | WSTOPPED i ->
9060 failwithf "pod2text: process signalled or stopped by signal %d" i
9062 Hashtbl.add pod2text_memo key lines;
9063 pod2text_memo_updated ();
9066 (* Generate ruby bindings. *)
9067 and generate_ruby_c () =
9068 generate_header CStyle LGPLv2plus;
9076 #include \"guestfs.h\"
9078 #include \"extconf.h\"
9080 /* For Ruby < 1.9 */
9082 #define RARRAY_LEN(r) (RARRAY((r))->len)
9085 static VALUE m_guestfs; /* guestfs module */
9086 static VALUE c_guestfs; /* guestfs_h handle */
9087 static VALUE e_Error; /* used for all errors */
9089 static void ruby_guestfs_free (void *p)
9092 guestfs_close ((guestfs_h *) p);
9095 static VALUE ruby_guestfs_create (VALUE m)
9099 g = guestfs_create ();
9101 rb_raise (e_Error, \"failed to create guestfs handle\");
9103 /* Don't print error messages to stderr by default. */
9104 guestfs_set_error_handler (g, NULL, NULL);
9106 /* Wrap it, and make sure the close function is called when the
9109 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9112 static VALUE ruby_guestfs_close (VALUE gv)
9115 Data_Get_Struct (gv, guestfs_h, g);
9117 ruby_guestfs_free (g);
9118 DATA_PTR (gv) = NULL;
9126 fun (name, style, _, _, _, _, _) ->
9127 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9128 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9131 pr " guestfs_h *g;\n";
9132 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9134 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9140 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9141 pr " Check_Type (%sv, T_STRING);\n" n;
9142 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9144 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9145 pr " \"%s\", \"%s\");\n" n name
9147 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9148 | StringList n | DeviceList n ->
9149 pr " char **%s;\n" n;
9150 pr " Check_Type (%sv, T_ARRAY);\n" n;
9152 pr " int i, len;\n";
9153 pr " len = RARRAY_LEN (%sv);\n" n;
9154 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9156 pr " for (i = 0; i < len; ++i) {\n";
9157 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9158 pr " %s[i] = StringValueCStr (v);\n" n;
9160 pr " %s[len] = NULL;\n" n;
9163 pr " int %s = RTEST (%sv);\n" n n
9165 pr " int %s = NUM2INT (%sv);\n" n n
9167 pr " long long %s = NUM2LL (%sv);\n" n n
9172 match fst style with
9173 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9174 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9175 | RConstString _ | RConstOptString _ ->
9176 pr " const char *r;\n"; "NULL"
9177 | RString _ -> pr " char *r;\n"; "NULL"
9178 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9179 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9180 | RStructList (_, typ) ->
9181 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9184 pr " size_t size;\n";
9188 pr " r = guestfs_%s " name;
9189 generate_c_call_args ~handle:"g" style;
9194 | Pathname _ | Device _ | Dev_or_Path _ | String _
9195 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9196 | StringList n | DeviceList n ->
9197 pr " free (%s);\n" n
9200 pr " if (r == %s)\n" error_code;
9201 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9204 (match fst style with
9206 pr " return Qnil;\n"
9207 | RInt _ | RBool _ ->
9208 pr " return INT2NUM (r);\n"
9210 pr " return ULL2NUM (r);\n"
9212 pr " return rb_str_new2 (r);\n";
9213 | RConstOptString _ ->
9215 pr " return rb_str_new2 (r);\n";
9217 pr " return Qnil;\n";
9219 pr " VALUE rv = rb_str_new2 (r);\n";
9223 pr " int i, len = 0;\n";
9224 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9225 pr " VALUE rv = rb_ary_new2 (len);\n";
9226 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9227 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9228 pr " free (r[i]);\n";
9232 | RStruct (_, typ) ->
9233 let cols = cols_of_struct typ in
9234 generate_ruby_struct_code typ cols
9235 | RStructList (_, typ) ->
9236 let cols = cols_of_struct typ in
9237 generate_ruby_struct_list_code typ cols
9239 pr " VALUE rv = rb_hash_new ();\n";
9241 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9242 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9243 pr " free (r[i]);\n";
9244 pr " free (r[i+1]);\n";
9249 pr " VALUE rv = rb_str_new (r, size);\n";
9259 /* Initialize the module. */
9260 void Init__guestfs ()
9262 m_guestfs = rb_define_module (\"Guestfs\");
9263 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9264 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9266 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9267 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9270 (* Define the rest of the methods. *)
9272 fun (name, style, _, _, _, _, _) ->
9273 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9274 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9279 (* Ruby code to return a struct. *)
9280 and generate_ruby_struct_code typ cols =
9281 pr " VALUE rv = rb_hash_new ();\n";
9285 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9287 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9289 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9290 | name, (FBytes|FUInt64) ->
9291 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9293 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9295 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9297 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9298 | name, FOptPercent ->
9299 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9300 | name, FChar -> (* XXX wrong? *)
9301 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9303 pr " guestfs_free_%s (r);\n" typ;
9306 (* Ruby code to return a struct list. *)
9307 and generate_ruby_struct_list_code typ cols =
9308 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9310 pr " for (i = 0; i < r->len; ++i) {\n";
9311 pr " VALUE hv = rb_hash_new ();\n";
9315 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9317 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
9319 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9320 | name, (FBytes|FUInt64) ->
9321 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9323 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9325 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9327 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9328 | name, FOptPercent ->
9329 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9330 | name, FChar -> (* XXX wrong? *)
9331 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9333 pr " rb_ary_push (rv, hv);\n";
9335 pr " guestfs_free_%s_list (r);\n" typ;
9338 (* Generate Java bindings GuestFS.java file. *)
9339 and generate_java_java () =
9340 generate_header CStyle LGPLv2plus;
9343 package com.redhat.et.libguestfs;
9345 import java.util.HashMap;
9346 import com.redhat.et.libguestfs.LibGuestFSException;
9347 import com.redhat.et.libguestfs.PV;
9348 import com.redhat.et.libguestfs.VG;
9349 import com.redhat.et.libguestfs.LV;
9350 import com.redhat.et.libguestfs.Stat;
9351 import com.redhat.et.libguestfs.StatVFS;
9352 import com.redhat.et.libguestfs.IntBool;
9353 import com.redhat.et.libguestfs.Dirent;
9356 * The GuestFS object is a libguestfs handle.
9360 public class GuestFS {
9361 // Load the native code.
9363 System.loadLibrary (\"guestfs_jni\");
9367 * The native guestfs_h pointer.
9372 * Create a libguestfs handle.
9374 * @throws LibGuestFSException
9376 public GuestFS () throws LibGuestFSException
9380 private native long _create () throws LibGuestFSException;
9383 * Close a libguestfs handle.
9385 * You can also leave handles to be collected by the garbage
9386 * collector, but this method ensures that the resources used
9387 * by the handle are freed up immediately. If you call any
9388 * other methods after closing the handle, you will get an
9391 * @throws LibGuestFSException
9393 public void close () throws LibGuestFSException
9399 private native void _close (long g) throws LibGuestFSException;
9401 public void finalize () throws LibGuestFSException
9409 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9410 if not (List.mem NotInDocs flags); then (
9411 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9413 if List.mem ProtocolLimitWarning flags then
9414 doc ^ "\n\n" ^ protocol_limit_warning
9417 if List.mem DangerWillRobinson flags then
9418 doc ^ "\n\n" ^ danger_will_robinson
9421 match deprecation_notice flags with
9423 | Some txt -> doc ^ "\n\n" ^ txt in
9424 let doc = pod2text ~width:60 name doc in
9425 let doc = List.map ( (* RHBZ#501883 *)
9428 | nonempty -> nonempty
9430 let doc = String.concat "\n * " doc in
9433 pr " * %s\n" shortdesc;
9436 pr " * @throws LibGuestFSException\n";
9440 generate_java_prototype ~public:true ~semicolon:false name style;
9443 pr " if (g == 0)\n";
9444 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9447 if fst style <> RErr then pr "return ";
9449 generate_java_call_args ~handle:"g" (snd style);
9453 generate_java_prototype ~privat:true ~native:true name style;
9460 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9461 and generate_java_call_args ~handle args =
9463 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9466 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9467 ?(semicolon=true) name style =
9468 if privat then pr "private ";
9469 if public then pr "public ";
9470 if native then pr "native ";
9473 (match fst style with
9474 | RErr -> pr "void ";
9475 | RInt _ -> pr "int ";
9476 | RInt64 _ -> pr "long ";
9477 | RBool _ -> pr "boolean ";
9478 | RConstString _ | RConstOptString _ | RString _
9479 | RBufferOut _ -> pr "String ";
9480 | RStringList _ -> pr "String[] ";
9481 | RStruct (_, typ) ->
9482 let name = java_name_of_struct typ in
9484 | RStructList (_, typ) ->
9485 let name = java_name_of_struct typ in
9487 | RHashtable _ -> pr "HashMap<String,String> ";
9490 if native then pr "_%s " name else pr "%s " name;
9492 let needs_comma = ref false in
9501 if !needs_comma then pr ", ";
9502 needs_comma := true;
9506 | Device n | Dev_or_Path n
9512 | StringList n | DeviceList n ->
9523 pr " throws LibGuestFSException";
9524 if semicolon then pr ";"
9526 and generate_java_struct jtyp cols () =
9527 generate_header CStyle LGPLv2plus;
9530 package com.redhat.et.libguestfs;
9533 * Libguestfs %s structure.
9545 | name, FBuffer -> pr " public String %s;\n" name
9546 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9547 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9548 | name, FChar -> pr " public char %s;\n" name
9549 | name, FOptPercent ->
9550 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9551 pr " public float %s;\n" name
9556 and generate_java_c () =
9557 generate_header CStyle LGPLv2plus;
9564 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9565 #include \"guestfs.h\"
9567 /* Note that this function returns. The exception is not thrown
9568 * until after the wrapper function returns.
9571 throw_exception (JNIEnv *env, const char *msg)
9574 cl = (*env)->FindClass (env,
9575 \"com/redhat/et/libguestfs/LibGuestFSException\");
9576 (*env)->ThrowNew (env, cl, msg);
9579 JNIEXPORT jlong JNICALL
9580 Java_com_redhat_et_libguestfs_GuestFS__1create
9581 (JNIEnv *env, jobject obj)
9585 g = guestfs_create ();
9587 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9590 guestfs_set_error_handler (g, NULL, NULL);
9591 return (jlong) (long) g;
9594 JNIEXPORT void JNICALL
9595 Java_com_redhat_et_libguestfs_GuestFS__1close
9596 (JNIEnv *env, jobject obj, jlong jg)
9598 guestfs_h *g = (guestfs_h *) (long) jg;
9605 fun (name, style, _, _, _, _, _) ->
9607 (match fst style with
9608 | RErr -> pr "void ";
9609 | RInt _ -> pr "jint ";
9610 | RInt64 _ -> pr "jlong ";
9611 | RBool _ -> pr "jboolean ";
9612 | RConstString _ | RConstOptString _ | RString _
9613 | RBufferOut _ -> pr "jstring ";
9614 | RStruct _ | RHashtable _ ->
9616 | RStringList _ | RStructList _ ->
9620 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9621 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9623 pr " (JNIEnv *env, jobject obj, jlong jg";
9627 | Device n | Dev_or_Path n
9632 pr ", jstring j%s" n
9633 | StringList n | DeviceList n ->
9634 pr ", jobjectArray j%s" n
9636 pr ", jboolean j%s" n
9644 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9645 let error_code, no_ret =
9646 match fst style with
9647 | RErr -> pr " int r;\n"; "-1", ""
9649 | RInt _ -> pr " int r;\n"; "-1", "0"
9650 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9651 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9652 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9654 pr " jstring jr;\n";
9655 pr " char *r;\n"; "NULL", "NULL"
9657 pr " jobjectArray jr;\n";
9660 pr " jstring jstr;\n";
9661 pr " char **r;\n"; "NULL", "NULL"
9662 | RStruct (_, typ) ->
9663 pr " jobject jr;\n";
9665 pr " jfieldID fl;\n";
9666 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9667 | RStructList (_, typ) ->
9668 pr " jobjectArray jr;\n";
9670 pr " jfieldID fl;\n";
9671 pr " jobject jfl;\n";
9672 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9673 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9675 pr " jstring jr;\n";
9677 pr " size_t size;\n";
9682 | Device n | Dev_or_Path n
9687 pr " const char *%s;\n" n
9688 | StringList n | DeviceList n ->
9689 pr " int %s_len;\n" n;
9690 pr " const char **%s;\n" n
9695 pr " int64_t %s;\n" n
9699 (match fst style with
9700 | RStringList _ | RStructList _ -> true
9701 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9703 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9704 List.exists (function
9705 | StringList _ -> true
9706 | DeviceList _ -> true
9707 | _ -> false) (snd style) in
9713 (* Get the parameters. *)
9717 | Device n | Dev_or_Path n
9721 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9723 (* This is completely undocumented, but Java null becomes
9726 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9727 | StringList n | DeviceList n ->
9728 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9729 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9730 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9731 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9733 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9735 pr " %s[%s_len] = NULL;\n" n n;
9739 pr " %s = j%s;\n" n n
9742 (* Make the call. *)
9743 pr " r = guestfs_%s " name;
9744 generate_c_call_args ~handle:"g" style;
9747 (* Release the parameters. *)
9751 | Device n | Dev_or_Path n
9755 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9758 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9759 | StringList n | DeviceList n ->
9760 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9761 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9763 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9765 pr " free (%s);\n" n
9771 (* Check for errors. *)
9772 pr " if (r == %s) {\n" error_code;
9773 pr " throw_exception (env, guestfs_last_error (g));\n";
9774 pr " return %s;\n" no_ret;
9778 (match fst style with
9780 | RInt _ -> pr " return (jint) r;\n"
9781 | RBool _ -> pr " return (jboolean) r;\n"
9782 | RInt64 _ -> pr " return (jlong) r;\n"
9783 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9784 | RConstOptString _ ->
9785 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9787 pr " jr = (*env)->NewStringUTF (env, r);\n";
9791 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9792 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9793 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9794 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9795 pr " for (i = 0; i < r_len; ++i) {\n";
9796 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9797 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9798 pr " free (r[i]);\n";
9802 | RStruct (_, typ) ->
9803 let jtyp = java_name_of_struct typ in
9804 let cols = cols_of_struct typ in
9805 generate_java_struct_return typ jtyp cols
9806 | RStructList (_, typ) ->
9807 let jtyp = java_name_of_struct typ in
9808 let cols = cols_of_struct typ in
9809 generate_java_struct_list_return typ jtyp cols
9812 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9813 pr " return NULL;\n"
9815 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9824 and generate_java_struct_return typ jtyp cols =
9825 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9826 pr " jr = (*env)->AllocObject (env, cl);\n";
9830 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9831 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9834 pr " char s[33];\n";
9835 pr " memcpy (s, r->%s, 32);\n" name;
9837 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9838 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9842 pr " int len = r->%s_len;\n" name;
9843 pr " char s[len+1];\n";
9844 pr " memcpy (s, r->%s, len);\n" name;
9845 pr " s[len] = 0;\n";
9846 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9847 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9849 | name, (FBytes|FUInt64|FInt64) ->
9850 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9851 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9852 | name, (FUInt32|FInt32) ->
9853 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9854 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9855 | name, FOptPercent ->
9856 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9857 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9859 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9860 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9865 and generate_java_struct_list_return typ jtyp cols =
9866 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9867 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9868 pr " for (i = 0; i < r->len; ++i) {\n";
9869 pr " jfl = (*env)->AllocObject (env, cl);\n";
9873 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9874 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9877 pr " char s[33];\n";
9878 pr " memcpy (s, r->val[i].%s, 32);\n" name;
9880 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9881 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9885 pr " int len = r->val[i].%s_len;\n" name;
9886 pr " char s[len+1];\n";
9887 pr " memcpy (s, r->val[i].%s, len);\n" name;
9888 pr " s[len] = 0;\n";
9889 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9890 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9892 | name, (FBytes|FUInt64|FInt64) ->
9893 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9894 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9895 | name, (FUInt32|FInt32) ->
9896 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9897 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9898 | name, FOptPercent ->
9899 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9900 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9902 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9903 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9905 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9907 pr " guestfs_free_%s_list (r);\n" typ;
9910 and generate_java_makefile_inc () =
9911 generate_header HashStyle GPLv2plus;
9913 pr "java_built_sources = \\\n";
9916 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9918 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9920 and generate_haskell_hs () =
9921 generate_header HaskellStyle LGPLv2plus;
9923 (* XXX We only know how to generate partial FFI for Haskell
9924 * at the moment. Please help out!
9926 let can_generate style =
9930 | RInt64 _, _ -> true
9933 | RConstOptString _, _
9939 | RBufferOut _, _ -> false in
9942 {-# INCLUDE <guestfs.h> #-}
9943 {-# LANGUAGE ForeignFunctionInterface #-}
9948 (* List out the names of the actions we want to export. *)
9950 fun (name, style, _, _, _, _, _) ->
9951 if can_generate style then pr ",\n %s" name
9957 -- Unfortunately some symbols duplicate ones already present
9958 -- in Prelude. We don't know which, so we hard-code a list
9960 import Prelude hiding (truncate)
9964 import Foreign.C.Types
9966 import Control.Exception
9967 import Data.Typeable
9969 data GuestfsS = GuestfsS -- represents the opaque C struct
9970 type GuestfsP = Ptr GuestfsS -- guestfs_h *
9971 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9973 -- XXX define properly later XXX
9977 data IntBool = IntBool
9979 data StatVFS = StatVFS
9980 data Hashtable = Hashtable
9982 foreign import ccall unsafe \"guestfs_create\" c_create
9984 foreign import ccall unsafe \"&guestfs_close\" c_close
9985 :: FunPtr (GuestfsP -> IO ())
9986 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9987 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9989 create :: IO GuestfsH
9992 c_set_error_handler p nullPtr nullPtr
9993 h <- newForeignPtr c_close p
9996 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9997 :: GuestfsP -> IO CString
9999 -- last_error :: GuestfsH -> IO (Maybe String)
10000 -- last_error h = do
10001 -- str <- withForeignPtr h (\\p -> c_last_error p)
10002 -- maybePeek peekCString str
10004 last_error :: GuestfsH -> IO (String)
10006 str <- withForeignPtr h (\\p -> c_last_error p)
10007 if (str == nullPtr)
10008 then return \"no error\"
10009 else peekCString str
10013 (* Generate wrappers for each foreign function. *)
10015 fun (name, style, _, _, _, _, _) ->
10016 if can_generate style then (
10017 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10019 generate_haskell_prototype ~handle:"GuestfsP" style;
10023 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10025 pr "%s %s = do\n" name
10026 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10028 (* Convert pointer arguments using with* functions. *)
10033 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10034 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10035 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10036 | Bool _ | Int _ | Int64 _ -> ()
10038 (* Convert integer arguments. *)
10042 | Bool n -> sprintf "(fromBool %s)" n
10043 | Int n -> sprintf "(fromIntegral %s)" n
10044 | Int64 n -> sprintf "(fromIntegral %s)" n
10045 | FileIn n | FileOut n
10046 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10048 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10049 (String.concat " " ("p" :: args));
10050 (match fst style with
10051 | RErr | RInt _ | RInt64 _ | RBool _ ->
10052 pr " if (r == -1)\n";
10054 pr " err <- last_error h\n";
10056 | RConstString _ | RConstOptString _ | RString _
10057 | RStringList _ | RStruct _
10058 | RStructList _ | RHashtable _ | RBufferOut _ ->
10059 pr " if (r == nullPtr)\n";
10061 pr " err <- last_error h\n";
10064 (match fst style with
10066 pr " else return ()\n"
10068 pr " else return (fromIntegral r)\n"
10070 pr " else return (fromIntegral r)\n"
10072 pr " else return (toBool r)\n"
10074 | RConstOptString _
10081 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10087 and generate_haskell_prototype ~handle ?(hs = false) style =
10088 pr "%s -> " handle;
10089 let string = if hs then "String" else "CString" in
10090 let int = if hs then "Int" else "CInt" in
10091 let bool = if hs then "Bool" else "CInt" in
10092 let int64 = if hs then "Integer" else "Int64" in
10096 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10097 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10098 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10099 | Bool _ -> pr "%s" bool
10100 | Int _ -> pr "%s" int
10101 | Int64 _ -> pr "%s" int
10102 | FileIn _ -> pr "%s" string
10103 | FileOut _ -> pr "%s" string
10108 (match fst style with
10109 | RErr -> if not hs then pr "CInt"
10110 | RInt _ -> pr "%s" int
10111 | RInt64 _ -> pr "%s" int64
10112 | RBool _ -> pr "%s" bool
10113 | RConstString _ -> pr "%s" string
10114 | RConstOptString _ -> pr "Maybe %s" string
10115 | RString _ -> pr "%s" string
10116 | RStringList _ -> pr "[%s]" string
10117 | RStruct (_, typ) ->
10118 let name = java_name_of_struct typ in
10120 | RStructList (_, typ) ->
10121 let name = java_name_of_struct typ in
10123 | RHashtable _ -> pr "Hashtable"
10124 | RBufferOut _ -> pr "%s" string
10128 and generate_csharp () =
10129 generate_header CPlusPlusStyle LGPLv2plus;
10131 (* XXX Make this configurable by the C# assembly users. *)
10132 let library = "libguestfs.so.0" in
10135 // These C# bindings are highly experimental at present.
10137 // Firstly they only work on Linux (ie. Mono). In order to get them
10138 // to work on Windows (ie. .Net) you would need to port the library
10139 // itself to Windows first.
10141 // The second issue is that some calls are known to be incorrect and
10142 // can cause Mono to segfault. Particularly: calls which pass or
10143 // return string[], or return any structure value. This is because
10144 // we haven't worked out the correct way to do this from C#.
10146 // The third issue is that when compiling you get a lot of warnings.
10147 // We are not sure whether the warnings are important or not.
10149 // Fourthly we do not routinely build or test these bindings as part
10150 // of the make && make check cycle, which means that regressions might
10153 // Suggestions and patches are welcome.
10157 // gmcs Libguestfs.cs
10158 // mono Libguestfs.exe
10160 // (You'll probably want to add a Test class / static main function
10161 // otherwise this won't do anything useful).
10165 using System.Runtime.InteropServices;
10166 using System.Runtime.Serialization;
10167 using System.Collections;
10171 class Error : System.ApplicationException
10173 public Error (string message) : base (message) {}
10174 protected Error (SerializationInfo info, StreamingContext context) {}
10181 [DllImport (\"%s\")]
10182 static extern IntPtr guestfs_create ();
10186 _handle = guestfs_create ();
10187 if (_handle == IntPtr.Zero)
10188 throw new Error (\"could not create guestfs handle\");
10191 [DllImport (\"%s\")]
10192 static extern void guestfs_close (IntPtr h);
10196 guestfs_close (_handle);
10199 [DllImport (\"%s\")]
10200 static extern string guestfs_last_error (IntPtr h);
10202 " library library library;
10204 (* Generate C# structure bindings. We prefix struct names with
10205 * underscore because C# cannot have conflicting struct names and
10206 * method names (eg. "class stat" and "stat").
10210 pr " [StructLayout (LayoutKind.Sequential)]\n";
10211 pr " public class _%s {\n" typ;
10214 | name, FChar -> pr " char %s;\n" name
10215 | name, FString -> pr " string %s;\n" name
10217 pr " uint %s_len;\n" name;
10218 pr " string %s;\n" name
10220 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10221 pr " string %s;\n" name
10222 | name, FUInt32 -> pr " uint %s;\n" name
10223 | name, FInt32 -> pr " int %s;\n" name
10224 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10225 | name, FInt64 -> pr " long %s;\n" name
10226 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10232 (* Generate C# function bindings. *)
10234 fun (name, style, _, _, _, shortdesc, _) ->
10235 let rec csharp_return_type () =
10236 match fst style with
10238 | RBool n -> "bool"
10240 | RInt64 n -> "long"
10242 | RConstOptString n
10244 | RBufferOut n -> "string"
10245 | RStruct (_,n) -> "_" ^ n
10246 | RHashtable n -> "Hashtable"
10247 | RStringList n -> "string[]"
10248 | RStructList (_,n) -> sprintf "_%s[]" n
10250 and c_return_type () =
10251 match fst style with
10255 | RInt64 _ -> "long"
10257 | RConstOptString _
10259 | RBufferOut _ -> "string"
10260 | RStruct (_,n) -> "_" ^ n
10262 | RStringList _ -> "string[]"
10263 | RStructList (_,n) -> sprintf "_%s[]" n
10265 and c_error_comparison () =
10266 match fst style with
10270 | RInt64 _ -> "== -1"
10272 | RConstOptString _
10278 | RStructList (_,_) -> "== null"
10280 and generate_extern_prototype () =
10281 pr " static extern %s guestfs_%s (IntPtr h"
10282 (c_return_type ()) name;
10285 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10286 | FileIn n | FileOut n ->
10287 pr ", [In] string %s" n
10288 | StringList n | DeviceList n ->
10289 pr ", [In] string[] %s" n
10299 and generate_public_prototype () =
10300 pr " public %s %s (" (csharp_return_type ()) name;
10301 let comma = ref false in
10303 if !comma then pr ", ";
10308 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10309 | FileIn n | FileOut n ->
10310 next (); pr "string %s" n
10311 | StringList n | DeviceList n ->
10312 next (); pr "string[] %s" n
10314 next (); pr "bool %s" n
10316 next (); pr "int %s" n
10318 next (); pr "long %s" n
10322 and generate_call () =
10323 pr "guestfs_%s (_handle" name;
10324 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10328 pr " [DllImport (\"%s\")]\n" library;
10329 generate_extern_prototype ();
10331 pr " /// <summary>\n";
10332 pr " /// %s\n" shortdesc;
10333 pr " /// </summary>\n";
10334 generate_public_prototype ();
10336 pr " %s r;\n" (c_return_type ());
10339 pr " if (r %s)\n" (c_error_comparison ());
10340 pr " throw new Error (guestfs_last_error (_handle));\n";
10341 (match fst style with
10344 pr " return r != 0 ? true : false;\n"
10346 pr " Hashtable rr = new Hashtable ();\n";
10347 pr " for (int i = 0; i < r.Length; i += 2)\n";
10348 pr " rr.Add (r[i], r[i+1]);\n";
10350 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10351 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10357 ) all_functions_sorted;
10363 and generate_bindtests () =
10364 generate_header CStyle LGPLv2plus;
10368 #include <stdlib.h>
10369 #include <inttypes.h>
10370 #include <string.h>
10372 #include \"guestfs.h\"
10373 #include \"guestfs-internal.h\"
10374 #include \"guestfs-internal-actions.h\"
10375 #include \"guestfs_protocol.h\"
10377 #define error guestfs_error
10378 #define safe_calloc guestfs_safe_calloc
10379 #define safe_malloc guestfs_safe_malloc
10382 print_strings (char *const *argv)
10387 for (argc = 0; argv[argc] != NULL; ++argc) {
10388 if (argc > 0) printf (\", \");
10389 printf (\"\\\"%%s\\\"\", argv[argc]);
10394 /* The test0 function prints its parameters to stdout. */
10398 match test_functions with
10399 | [] -> assert false
10400 | test0 :: tests -> test0, tests in
10403 let (name, style, _, _, _, _, _) = test0 in
10404 generate_prototype ~extern:false ~semicolon:false ~newline:true
10405 ~handle:"g" ~prefix:"guestfs__" name style;
10410 | Device n | Dev_or_Path n
10413 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10414 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10415 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10416 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10417 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10418 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10420 pr " /* Java changes stdout line buffering so we need this: */\n";
10421 pr " fflush (stdout);\n";
10427 fun (name, style, _, _, _, _, _) ->
10428 if String.sub name (String.length name - 3) 3 <> "err" then (
10429 pr "/* Test normal return. */\n";
10430 generate_prototype ~extern:false ~semicolon:false ~newline:true
10431 ~handle:"g" ~prefix:"guestfs__" name style;
10433 (match fst style with
10438 pr " sscanf (val, \"%%d\", &r);\n";
10441 pr " int64_t r;\n";
10442 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10445 pr " return STREQ (val, \"true\");\n"
10447 | RConstOptString _ ->
10448 (* Can't return the input string here. Return a static
10449 * string so we ensure we get a segfault if the caller
10450 * tries to free it.
10452 pr " return \"static string\";\n"
10454 pr " return strdup (val);\n"
10456 pr " char **strs;\n";
10458 pr " sscanf (val, \"%%d\", &n);\n";
10459 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10460 pr " for (i = 0; i < n; ++i) {\n";
10461 pr " strs[i] = safe_malloc (g, 16);\n";
10462 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10464 pr " strs[n] = NULL;\n";
10465 pr " return strs;\n"
10466 | RStruct (_, typ) ->
10467 pr " struct guestfs_%s *r;\n" typ;
10468 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10470 | RStructList (_, typ) ->
10471 pr " struct guestfs_%s_list *r;\n" typ;
10472 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10473 pr " sscanf (val, \"%%d\", &r->len);\n";
10474 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10477 pr " char **strs;\n";
10479 pr " sscanf (val, \"%%d\", &n);\n";
10480 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10481 pr " for (i = 0; i < n; ++i) {\n";
10482 pr " strs[i*2] = safe_malloc (g, 16);\n";
10483 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10484 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10485 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10487 pr " strs[n*2] = NULL;\n";
10488 pr " return strs;\n"
10490 pr " return strdup (val);\n"
10495 pr "/* Test error return. */\n";
10496 generate_prototype ~extern:false ~semicolon:false ~newline:true
10497 ~handle:"g" ~prefix:"guestfs__" name style;
10499 pr " error (g, \"error\");\n";
10500 (match fst style with
10501 | RErr | RInt _ | RInt64 _ | RBool _ ->
10503 | RConstString _ | RConstOptString _
10504 | RString _ | RStringList _ | RStruct _
10508 pr " return NULL;\n"
10515 and generate_ocaml_bindtests () =
10516 generate_header OCamlStyle GPLv2plus;
10520 let g = Guestfs.create () in
10524 String.concat " " (
10527 | CallString s -> "\"" ^ s ^ "\""
10528 | CallOptString None -> "None"
10529 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10530 | CallStringList xs ->
10531 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10532 | CallInt i when i >= 0 -> string_of_int i
10533 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10534 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10535 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10536 | CallBool b -> string_of_bool b
10541 generate_lang_bindtests (
10542 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10545 pr "print_endline \"EOF\"\n"
10547 and generate_perl_bindtests () =
10548 pr "#!/usr/bin/perl -w\n";
10549 generate_header HashStyle GPLv2plus;
10556 my $g = Sys::Guestfs->new ();
10560 String.concat ", " (
10563 | CallString s -> "\"" ^ s ^ "\""
10564 | CallOptString None -> "undef"
10565 | CallOptString (Some s) -> sprintf "\"%s\"" s
10566 | CallStringList xs ->
10567 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10568 | CallInt i -> string_of_int i
10569 | CallInt64 i -> Int64.to_string i
10570 | CallBool b -> if b then "1" else "0"
10575 generate_lang_bindtests (
10576 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10579 pr "print \"EOF\\n\"\n"
10581 and generate_python_bindtests () =
10582 generate_header HashStyle GPLv2plus;
10587 g = guestfs.GuestFS ()
10591 String.concat ", " (
10594 | CallString s -> "\"" ^ s ^ "\""
10595 | CallOptString None -> "None"
10596 | CallOptString (Some s) -> sprintf "\"%s\"" s
10597 | CallStringList xs ->
10598 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10599 | CallInt i -> string_of_int i
10600 | CallInt64 i -> Int64.to_string i
10601 | CallBool b -> if b then "1" else "0"
10606 generate_lang_bindtests (
10607 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10610 pr "print \"EOF\"\n"
10612 and generate_ruby_bindtests () =
10613 generate_header HashStyle GPLv2plus;
10618 g = Guestfs::create()
10622 String.concat ", " (
10625 | CallString s -> "\"" ^ s ^ "\""
10626 | CallOptString None -> "nil"
10627 | CallOptString (Some s) -> sprintf "\"%s\"" s
10628 | CallStringList xs ->
10629 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10630 | CallInt i -> string_of_int i
10631 | CallInt64 i -> Int64.to_string i
10632 | CallBool b -> string_of_bool b
10637 generate_lang_bindtests (
10638 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10641 pr "print \"EOF\\n\"\n"
10643 and generate_java_bindtests () =
10644 generate_header CStyle GPLv2plus;
10647 import com.redhat.et.libguestfs.*;
10649 public class Bindtests {
10650 public static void main (String[] argv)
10653 GuestFS g = new GuestFS ();
10657 String.concat ", " (
10660 | CallString s -> "\"" ^ s ^ "\""
10661 | CallOptString None -> "null"
10662 | CallOptString (Some s) -> sprintf "\"%s\"" s
10663 | CallStringList xs ->
10665 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10666 | CallInt i -> string_of_int i
10667 | CallInt64 i -> Int64.to_string i
10668 | CallBool b -> string_of_bool b
10673 generate_lang_bindtests (
10674 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10678 System.out.println (\"EOF\");
10680 catch (Exception exn) {
10681 System.err.println (exn);
10688 and generate_haskell_bindtests () =
10689 generate_header HaskellStyle GPLv2plus;
10692 module Bindtests where
10693 import qualified Guestfs
10696 g <- Guestfs.create
10700 String.concat " " (
10703 | CallString s -> "\"" ^ s ^ "\""
10704 | CallOptString None -> "Nothing"
10705 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10706 | CallStringList xs ->
10707 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10708 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10709 | CallInt i -> string_of_int i
10710 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10711 | CallInt64 i -> Int64.to_string i
10712 | CallBool true -> "True"
10713 | CallBool false -> "False"
10718 generate_lang_bindtests (
10719 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10722 pr " putStrLn \"EOF\"\n"
10724 (* Language-independent bindings tests - we do it this way to
10725 * ensure there is parity in testing bindings across all languages.
10727 and generate_lang_bindtests call =
10728 call "test0" [CallString "abc"; CallOptString (Some "def");
10729 CallStringList []; CallBool false;
10730 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10731 call "test0" [CallString "abc"; CallOptString None;
10732 CallStringList []; CallBool false;
10733 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10734 call "test0" [CallString ""; CallOptString (Some "def");
10735 CallStringList []; CallBool false;
10736 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10737 call "test0" [CallString ""; CallOptString (Some "");
10738 CallStringList []; CallBool false;
10739 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10740 call "test0" [CallString "abc"; CallOptString (Some "def");
10741 CallStringList ["1"]; CallBool false;
10742 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10743 call "test0" [CallString "abc"; CallOptString (Some "def");
10744 CallStringList ["1"; "2"]; CallBool false;
10745 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10746 call "test0" [CallString "abc"; CallOptString (Some "def");
10747 CallStringList ["1"]; CallBool true;
10748 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10749 call "test0" [CallString "abc"; CallOptString (Some "def");
10750 CallStringList ["1"]; CallBool false;
10751 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10752 call "test0" [CallString "abc"; CallOptString (Some "def");
10753 CallStringList ["1"]; CallBool false;
10754 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10755 call "test0" [CallString "abc"; CallOptString (Some "def");
10756 CallStringList ["1"]; CallBool false;
10757 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10758 call "test0" [CallString "abc"; CallOptString (Some "def");
10759 CallStringList ["1"]; CallBool false;
10760 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10761 call "test0" [CallString "abc"; CallOptString (Some "def");
10762 CallStringList ["1"]; CallBool false;
10763 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10764 call "test0" [CallString "abc"; CallOptString (Some "def");
10765 CallStringList ["1"]; CallBool false;
10766 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10768 (* XXX Add here tests of the return and error functions. *)
10770 (* Code to generator bindings for virt-inspector. Currently only
10771 * implemented for OCaml code (for virt-p2v 2.0).
10773 let rng_input = "inspector/virt-inspector.rng"
10775 (* Read the input file and parse it into internal structures. This is
10776 * by no means a complete RELAX NG parser, but is just enough to be
10777 * able to parse the specific input file.
10780 | Element of string * rng list (* <element name=name/> *)
10781 | Attribute of string * rng list (* <attribute name=name/> *)
10782 | Interleave of rng list (* <interleave/> *)
10783 | ZeroOrMore of rng (* <zeroOrMore/> *)
10784 | OneOrMore of rng (* <oneOrMore/> *)
10785 | Optional of rng (* <optional/> *)
10786 | Choice of string list (* <choice><value/>*</choice> *)
10787 | Value of string (* <value>str</value> *)
10788 | Text (* <text/> *)
10790 let rec string_of_rng = function
10791 | Element (name, xs) ->
10792 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10793 | Attribute (name, xs) ->
10794 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10795 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10796 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10797 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10798 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10799 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10800 | Value value -> "Value \"" ^ value ^ "\""
10803 and string_of_rng_list xs =
10804 String.concat ", " (List.map string_of_rng xs)
10806 let rec parse_rng ?defines context = function
10808 | Xml.Element ("element", ["name", name], children) :: rest ->
10809 Element (name, parse_rng ?defines context children)
10810 :: parse_rng ?defines context rest
10811 | Xml.Element ("attribute", ["name", name], children) :: rest ->
10812 Attribute (name, parse_rng ?defines context children)
10813 :: parse_rng ?defines context rest
10814 | Xml.Element ("interleave", [], children) :: rest ->
10815 Interleave (parse_rng ?defines context children)
10816 :: parse_rng ?defines context rest
10817 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10818 let rng = parse_rng ?defines context [child] in
10820 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10822 failwithf "%s: <zeroOrMore> contains more than one child element"
10825 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10826 let rng = parse_rng ?defines context [child] in
10828 | [child] -> OneOrMore child :: parse_rng ?defines context rest
10830 failwithf "%s: <oneOrMore> contains more than one child element"
10833 | Xml.Element ("optional", [], [child]) :: rest ->
10834 let rng = parse_rng ?defines context [child] in
10836 | [child] -> Optional child :: parse_rng ?defines context rest
10838 failwithf "%s: <optional> contains more than one child element"
10841 | Xml.Element ("choice", [], children) :: rest ->
10842 let values = List.map (
10843 function Xml.Element ("value", [], [Xml.PCData value]) -> value
10845 failwithf "%s: can't handle anything except <value> in <choice>"
10849 :: parse_rng ?defines context rest
10850 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10851 Value value :: parse_rng ?defines context rest
10852 | Xml.Element ("text", [], []) :: rest ->
10853 Text :: parse_rng ?defines context rest
10854 | Xml.Element ("ref", ["name", name], []) :: rest ->
10855 (* Look up the reference. Because of limitations in this parser,
10856 * we can't handle arbitrarily nested <ref> yet. You can only
10857 * use <ref> from inside <start>.
10859 (match defines with
10861 failwithf "%s: contains <ref>, but no refs are defined yet" context
10863 let rng = StringMap.find name map in
10864 rng @ parse_rng ?defines context rest
10867 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10870 let xml = Xml.parse_file rng_input in
10872 | Xml.Element ("grammar", _,
10873 Xml.Element ("start", _, gram) :: defines) ->
10874 (* The <define/> elements are referenced in the <start> section,
10875 * so build a map of those first.
10877 let defines = List.fold_left (
10879 function Xml.Element ("define", ["name", name], defn) ->
10880 StringMap.add name defn map
10882 failwithf "%s: expected <define name=name/>" rng_input
10883 ) StringMap.empty defines in
10884 let defines = StringMap.mapi parse_rng defines in
10886 (* Parse the <start> clause, passing the defines. *)
10887 parse_rng ~defines "<start>" gram
10889 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10892 let name_of_field = function
10893 | Element (name, _) | Attribute (name, _)
10894 | ZeroOrMore (Element (name, _))
10895 | OneOrMore (Element (name, _))
10896 | Optional (Element (name, _)) -> name
10897 | Optional (Attribute (name, _)) -> name
10898 | Text -> (* an unnamed field in an element *)
10901 failwithf "name_of_field failed at: %s" (string_of_rng rng)
10903 (* At the moment this function only generates OCaml types. However we
10904 * should parameterize it later so it can generate types/structs in a
10905 * variety of languages.
10907 let generate_types xs =
10908 (* A simple type is one that can be printed out directly, eg.
10909 * "string option". A complex type is one which has a name and has
10910 * to be defined via another toplevel definition, eg. a struct.
10912 * generate_type generates code for either simple or complex types.
10913 * In the simple case, it returns the string ("string option"). In
10914 * the complex case, it returns the name ("mountpoint"). In the
10915 * complex case it has to print out the definition before returning,
10916 * so it should only be called when we are at the beginning of a
10917 * new line (BOL context).
10919 let rec generate_type = function
10920 | Text -> (* string *)
10922 | Choice values -> (* [`val1|`val2|...] *)
10923 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10924 | ZeroOrMore rng -> (* <rng> list *)
10925 let t, is_simple = generate_type rng in
10926 t ^ " list (* 0 or more *)", is_simple
10927 | OneOrMore rng -> (* <rng> list *)
10928 let t, is_simple = generate_type rng in
10929 t ^ " list (* 1 or more *)", is_simple
10930 (* virt-inspector hack: bool *)
10931 | Optional (Attribute (name, [Value "1"])) ->
10933 | Optional rng -> (* <rng> list *)
10934 let t, is_simple = generate_type rng in
10935 t ^ " option", is_simple
10936 (* type name = { fields ... } *)
10937 | Element (name, fields) when is_attrs_interleave fields ->
10938 generate_type_struct name (get_attrs_interleave fields)
10939 | Element (name, [field]) (* type name = field *)
10940 | Attribute (name, [field]) ->
10941 let t, is_simple = generate_type field in
10942 if is_simple then (t, true)
10944 pr "type %s = %s\n" name t;
10947 | Element (name, fields) -> (* type name = { fields ... } *)
10948 generate_type_struct name fields
10950 failwithf "generate_type failed at: %s" (string_of_rng rng)
10952 and is_attrs_interleave = function
10953 | [Interleave _] -> true
10954 | Attribute _ :: fields -> is_attrs_interleave fields
10955 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10958 and get_attrs_interleave = function
10959 | [Interleave fields] -> fields
10960 | ((Attribute _) as field) :: fields
10961 | ((Optional (Attribute _)) as field) :: fields ->
10962 field :: get_attrs_interleave fields
10963 | _ -> assert false
10965 and generate_types xs =
10966 List.iter (fun x -> ignore (generate_type x)) xs
10968 and generate_type_struct name fields =
10969 (* Calculate the types of the fields first. We have to do this
10970 * before printing anything so we are still in BOL context.
10972 let types = List.map fst (List.map generate_type fields) in
10974 (* Special case of a struct containing just a string and another
10975 * field. Turn it into an assoc list.
10978 | ["string"; other] ->
10979 let fname1, fname2 =
10981 | [f1; f2] -> name_of_field f1, name_of_field f2
10982 | _ -> assert false in
10983 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10987 pr "type %s = {\n" name;
10989 fun (field, ftype) ->
10990 let fname = name_of_field field in
10991 pr " %s_%s : %s;\n" name fname ftype
10992 ) (List.combine fields types);
10994 (* Return the name of this type, and
10995 * false because it's not a simple type.
11002 let generate_parsers xs =
11003 (* As for generate_type above, generate_parser makes a parser for
11004 * some type, and returns the name of the parser it has generated.
11005 * Because it (may) need to print something, it should always be
11006 * called in BOL context.
11008 let rec generate_parser = function
11009 | Text -> (* string *)
11010 "string_child_or_empty"
11011 | Choice values -> (* [`val1|`val2|...] *)
11012 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11014 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11015 | ZeroOrMore rng -> (* <rng> list *)
11016 let pa = generate_parser rng in
11017 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11018 | OneOrMore rng -> (* <rng> list *)
11019 let pa = generate_parser rng in
11020 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11021 (* virt-inspector hack: bool *)
11022 | Optional (Attribute (name, [Value "1"])) ->
11023 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11024 | Optional rng -> (* <rng> list *)
11025 let pa = generate_parser rng in
11026 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11027 (* type name = { fields ... } *)
11028 | Element (name, fields) when is_attrs_interleave fields ->
11029 generate_parser_struct name (get_attrs_interleave fields)
11030 | Element (name, [field]) -> (* type name = field *)
11031 let pa = generate_parser field in
11032 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11033 pr "let %s =\n" parser_name;
11035 pr "let parse_%s = %s\n" name parser_name;
11037 | Attribute (name, [field]) ->
11038 let pa = generate_parser field in
11039 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11040 pr "let %s =\n" parser_name;
11042 pr "let parse_%s = %s\n" name parser_name;
11044 | Element (name, fields) -> (* type name = { fields ... } *)
11045 generate_parser_struct name ([], fields)
11047 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11049 and is_attrs_interleave = function
11050 | [Interleave _] -> true
11051 | Attribute _ :: fields -> is_attrs_interleave fields
11052 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11055 and get_attrs_interleave = function
11056 | [Interleave fields] -> [], fields
11057 | ((Attribute _) as field) :: fields
11058 | ((Optional (Attribute _)) as field) :: fields ->
11059 let attrs, interleaves = get_attrs_interleave fields in
11060 (field :: attrs), interleaves
11061 | _ -> assert false
11063 and generate_parsers xs =
11064 List.iter (fun x -> ignore (generate_parser x)) xs
11066 and generate_parser_struct name (attrs, interleaves) =
11067 (* Generate parsers for the fields first. We have to do this
11068 * before printing anything so we are still in BOL context.
11070 let fields = attrs @ interleaves in
11071 let pas = List.map generate_parser fields in
11073 (* Generate an intermediate tuple from all the fields first.
11074 * If the type is just a string + another field, then we will
11075 * return this directly, otherwise it is turned into a record.
11077 * RELAX NG note: This code treats <interleave> and plain lists of
11078 * fields the same. In other words, it doesn't bother enforcing
11079 * any ordering of fields in the XML.
11081 pr "let parse_%s x =\n" name;
11082 pr " let t = (\n ";
11083 let comma = ref false in
11086 if !comma then pr ",\n ";
11089 | Optional (Attribute (fname, [field])), pa ->
11091 | Optional (Element (fname, [field])), pa ->
11092 pr "%s (optional_child %S x)" pa fname
11093 | Attribute (fname, [Text]), _ ->
11094 pr "attribute %S x" fname
11095 | (ZeroOrMore _ | OneOrMore _), pa ->
11100 let fname = name_of_field field in
11101 pr "%s (child %S x)" pa fname
11102 ) (List.combine fields pas);
11106 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11110 pr " (Obj.magic t : %s)\n" name
11114 | (Optional (Attribute (fname, [field])), pa) ->
11115 pr " %s_%s =\n" name fname;
11117 | (Optional (Element (fname, [field])), pa) ->
11118 pr " %s_%s =\n" name fname;
11119 pr " (let x = optional_child %S x in\n" fname;
11122 let fname = name_of_field field in
11123 pr " %s_%s =\n" name fname;
11124 pr " (let x = child %S x in\n" fname;
11126 ) (List.combine fields pas);
11130 sprintf "parse_%s" name
11133 generate_parsers xs
11135 (* Generate ocaml/guestfs_inspector.mli. *)
11136 let generate_ocaml_inspector_mli () =
11137 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11140 (** This is an OCaml language binding to the external [virt-inspector]
11143 For more information, please read the man page [virt-inspector(1)].
11148 generate_types grammar;
11149 pr "(** The nested information returned from the {!inspect} function. *)\n";
11153 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11154 (** To inspect a libvirt domain called [name], pass a singleton
11155 list: [inspect [name]]. When using libvirt only, you may
11156 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11158 To inspect a disk image or images, pass a list of the filenames
11159 of the disk images: [inspect filenames]
11161 This function inspects the given guest or disk images and
11162 returns a list of operating system(s) found and a large amount
11163 of information about them. In the vast majority of cases,
11164 a virtual machine only contains a single operating system.
11166 If the optional [~xml] parameter is given, then this function
11167 skips running the external virt-inspector program and just
11168 parses the given XML directly (which is expected to be XML
11169 produced from a previous run of virt-inspector). The list of
11170 names and connect URI are ignored in this case.
11172 This function can throw a wide variety of exceptions, for example
11173 if the external virt-inspector program cannot be found, or if
11174 it doesn't generate valid XML.
11178 (* Generate ocaml/guestfs_inspector.ml. *)
11179 let generate_ocaml_inspector_ml () =
11180 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11185 generate_types grammar;
11189 (* Misc functions which are used by the parser code below. *)
11190 let first_child = function
11191 | Xml.Element (_, _, c::_) -> c
11192 | Xml.Element (name, _, []) ->
11193 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11194 | Xml.PCData str ->
11195 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11197 let string_child_or_empty = function
11198 | Xml.Element (_, _, [Xml.PCData s]) -> s
11199 | Xml.Element (_, _, []) -> \"\"
11200 | Xml.Element (x, _, _) ->
11201 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11203 | Xml.PCData str ->
11204 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11206 let optional_child name xml =
11207 let children = Xml.children xml in
11209 Some (List.find (function
11210 | Xml.Element (n, _, _) when n = name -> true
11211 | _ -> false) children)
11215 let child name xml =
11216 match optional_child name xml with
11219 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11221 let attribute name xml =
11222 try Xml.attrib xml name
11223 with Xml.No_attribute _ ->
11224 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11228 generate_parsers grammar;
11232 (* Run external virt-inspector, then use parser to parse the XML. *)
11233 let inspect ?connect ?xml names =
11237 if names = [] then invalid_arg \"inspect: no names given\";
11238 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11239 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11241 let cmd = List.map Filename.quote cmd in
11242 let cmd = String.concat \" \" cmd in
11243 let chan = open_process_in cmd in
11244 let xml = Xml.parse_in chan in
11245 (match close_process_in chan with
11247 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11248 | WSIGNALED i | WSTOPPED i ->
11249 failwith (\"external virt-inspector command died or stopped on sig \" ^
11254 Xml.parse_string doc in
11255 parse_operatingsystems xml
11258 (* This is used to generate the src/MAX_PROC_NR file which
11259 * contains the maximum procedure number, a surrogate for the
11260 * ABI version number. See src/Makefile.am for the details.
11262 and generate_max_proc_nr () =
11263 let proc_nrs = List.map (
11264 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11265 ) daemon_functions in
11267 let max_proc_nr = List.fold_left max 0 proc_nrs in
11269 pr "%d\n" max_proc_nr
11271 let output_to filename k =
11272 let filename_new = filename ^ ".new" in
11273 chan := open_out filename_new;
11276 chan := Pervasives.stdout;
11278 (* Is the new file different from the current file? *)
11279 if Sys.file_exists filename && files_equal filename filename_new then
11280 unlink filename_new (* same, so skip it *)
11282 (* different, overwrite old one *)
11283 (try chmod filename 0o644 with Unix_error _ -> ());
11284 rename filename_new filename;
11285 chmod filename 0o444;
11286 printf "written %s\n%!" filename;
11289 let perror msg = function
11290 | Unix_error (err, _, _) ->
11291 eprintf "%s: %s\n" msg (error_message err)
11293 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11295 (* Main program. *)
11298 try openfile "HACKING" [O_RDWR] 0
11300 | Unix_error (ENOENT, _, _) ->
11302 You are probably running this from the wrong directory.
11303 Run it from the top source directory using the command
11308 perror "open: HACKING" exn;
11311 (* Acquire a lock so parallel builds won't try to run the generator
11312 * twice at the same time. Subsequent builds will wait for the first
11313 * one to finish. Note the lock is released implicitly when the
11316 (try lockf lock_fd F_LOCK 1
11318 perror "lock: HACKING" exn;
11321 check_functions ();
11323 output_to "src/guestfs_protocol.x" generate_xdr;
11324 output_to "src/guestfs-structs.h" generate_structs_h;
11325 output_to "src/guestfs-actions.h" generate_actions_h;
11326 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11327 output_to "src/guestfs-actions.c" generate_client_actions;
11328 output_to "src/guestfs-bindtests.c" generate_bindtests;
11329 output_to "src/guestfs-structs.pod" generate_structs_pod;
11330 output_to "src/guestfs-actions.pod" generate_actions_pod;
11331 output_to "src/guestfs-availability.pod" generate_availability_pod;
11332 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11333 output_to "src/libguestfs.syms" generate_linker_script;
11334 output_to "daemon/actions.h" generate_daemon_actions_h;
11335 output_to "daemon/stubs.c" generate_daemon_actions;
11336 output_to "daemon/names.c" generate_daemon_names;
11337 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11338 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11339 output_to "capitests/tests.c" generate_tests;
11340 output_to "fish/cmds.c" generate_fish_cmds;
11341 output_to "fish/completion.c" generate_fish_completion;
11342 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11343 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11344 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11345 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11346 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11347 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11348 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11349 output_to "perl/Guestfs.xs" generate_perl_xs;
11350 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11351 output_to "perl/bindtests.pl" generate_perl_bindtests;
11352 output_to "python/guestfs-py.c" generate_python_c;
11353 output_to "python/guestfs.py" generate_python_py;
11354 output_to "python/bindtests.py" generate_python_bindtests;
11355 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11356 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11357 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11361 let cols = cols_of_struct typ in
11362 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11363 output_to filename (generate_java_struct jtyp cols);
11366 output_to "java/Makefile.inc" generate_java_makefile_inc;
11367 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11368 output_to "java/Bindtests.java" generate_java_bindtests;
11369 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11370 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11371 output_to "csharp/Libguestfs.cs" generate_csharp;
11373 (* Always generate this file last, and unconditionally. It's used
11374 * by the Makefile to know when we must re-run the generator.
11376 let chan = open_out "src/stamp-generator" in
11377 fprintf chan "1\n";
11380 printf "generated %d lines of code\n" !lines