3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | FishOutput of fish_output_t (* how to display output in guestfish *)
186 | NotInFish (* do not export via guestfish *)
187 | NotInDocs (* do not add this function to documentation *)
188 | DeprecatedBy of string (* function is deprecated, use .. instead *)
189 | Optional of string (* function is part of an optional group *)
192 | FishOutputOctal (* for int return, print in octal *)
193 | FishOutputHexadecimal (* for int return, print in hex *)
195 (* You can supply zero or as many tests as you want per API call.
197 * Note that the test environment has 3 block devices, of size 500MB,
198 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199 * a fourth ISO block device with some known files on it (/dev/sdd).
201 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202 * Number of cylinders was 63 for IDE emulated disks with precisely
203 * the same size. How exactly this is calculated is a mystery.
205 * The ISO block device (/dev/sdd) comes from images/test.iso.
207 * To be able to run the tests in a reasonable amount of time,
208 * the virtual machine and block devices are reused between tests.
209 * So don't try testing kill_subprocess :-x
211 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
213 * Don't assume anything about the previous contents of the block
214 * devices. Use 'Init*' to create some initial scenarios.
216 * You can add a prerequisite clause to any individual test. This
217 * is a run-time check, which, if it fails, causes the test to be
218 * skipped. Useful if testing a command which might not work on
219 * all variations of libguestfs builds. A test that has prerequisite
220 * of 'Always' is run unconditionally.
222 * In addition, packagers can skip individual tests by setting the
223 * environment variables: eg:
224 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
225 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
227 type tests = (test_init * test_prereq * test) list
229 (* Run the command sequence and just expect nothing to fail. *)
232 (* Run the command sequence and expect the output of the final
233 * command to be the string.
235 | TestOutput of seq * string
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of strings.
240 | TestOutputList of seq * string list
242 (* Run the command sequence and expect the output of the final
243 * command to be the list of block devices (could be either
244 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245 * character of each string).
247 | TestOutputListOfDevices of seq * string list
249 (* Run the command sequence and expect the output of the final
250 * command to be the integer.
252 | TestOutputInt of seq * int
254 (* Run the command sequence and expect the output of the final
255 * command to be <op> <int>, eg. ">=", "1".
257 | TestOutputIntOp of seq * string * int
259 (* Run the command sequence and expect the output of the final
260 * command to be a true value (!= 0 or != NULL).
262 | TestOutputTrue of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a false value (== 0 or == NULL, but not an error).
267 | TestOutputFalse of seq
269 (* Run the command sequence and expect the output of the final
270 * command to be a list of the given length (but don't care about
273 | TestOutputLength of seq * int
275 (* Run the command sequence and expect the output of the final
276 * command to be a buffer (RBufferOut), ie. string + size.
278 | TestOutputBuffer of seq * string
280 (* Run the command sequence and expect the output of the final
281 * command to be a structure.
283 | TestOutputStruct of seq * test_field_compare list
285 (* Run the command sequence and expect the final command (only)
288 | TestLastFail of seq
290 and test_field_compare =
291 | CompareWithInt of string * int
292 | CompareWithIntOp of string * string * int
293 | CompareWithString of string * string
294 | CompareFieldsIntEq of string * string
295 | CompareFieldsStrEq of string * string
297 (* Test prerequisites. *)
299 (* Test always runs. *)
302 (* Test is currently disabled - eg. it fails, or it tests some
303 * unimplemented feature.
307 (* 'string' is some C code (a function body) that should return
308 * true or false. The test will run if the code returns true.
312 (* As for 'If' but the test runs _unless_ the code returns true. *)
315 (* Some initial scenarios for testing. *)
317 (* Do nothing, block devices could contain random stuff including
318 * LVM PVs, and some filesystems might be mounted. This is usually
323 (* Block devices are empty and no filesystems are mounted. *)
326 (* /dev/sda contains a single partition /dev/sda1, with random
327 * content. /dev/sdb and /dev/sdc may have random content.
332 (* /dev/sda contains a single partition /dev/sda1, which is formatted
333 * as ext2, empty [except for lost+found] and mounted on /.
334 * /dev/sdb and /dev/sdc may have random content.
340 * /dev/sda1 (is a PV):
341 * /dev/VG/LV (size 8MB):
342 * formatted as ext2, empty [except for lost+found], mounted on /
343 * /dev/sdb and /dev/sdc may have random content.
347 (* /dev/sdd (the ISO, see images/ directory in source)
352 (* Sequence of commands for testing. *)
354 and cmd = string list
356 (* Note about long descriptions: When referring to another
357 * action, use the format C<guestfs_other> (ie. the full name of
358 * the C function). This will be replaced as appropriate in other
361 * Apart from that, long descriptions are just perldoc paragraphs.
364 (* Generate a random UUID (used in tests). *)
366 let chan = open_process_in "uuidgen" in
367 let uuid = input_line chan in
368 (match close_process_in chan with
371 failwith "uuidgen: process exited with non-zero status"
372 | WSIGNALED _ | WSTOPPED _ ->
373 failwith "uuidgen: process signalled or stopped by signal"
377 (* These test functions are used in the language binding tests. *)
379 let test_all_args = [
382 StringList "strlist";
390 let test_all_rets = [
391 (* except for RErr, which is tested thoroughly elsewhere *)
392 "test0rint", RInt "valout";
393 "test0rint64", RInt64 "valout";
394 "test0rbool", RBool "valout";
395 "test0rconststring", RConstString "valout";
396 "test0rconstoptstring", RConstOptString "valout";
397 "test0rstring", RString "valout";
398 "test0rstringlist", RStringList "valout";
399 "test0rstruct", RStruct ("valout", "lvm_pv");
400 "test0rstructlist", RStructList ("valout", "lvm_pv");
401 "test0rhashtable", RHashtable "valout";
404 let test_functions = [
405 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407 "internal test function - do not use",
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
413 It echos the contents of each parameter to stdout.
415 You probably don't want to call this function.");
419 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421 "internal test function - do not use",
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
427 It converts string C<val> to the return type.
429 You probably don't want to call this function.");
430 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432 "internal test function - do not use",
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
438 This function always returns an error.
440 You probably don't want to call this function.")]
444 (* non_daemon_functions are any functions which don't get processed
445 * in the daemon, eg. functions for setting and getting local
446 * configuration values.
449 let non_daemon_functions = test_functions @ [
450 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
452 "launch the qemu subprocess",
454 Internally libguestfs is implemented by running a virtual machine
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
460 ("wait_ready", (RErr, []), -1, [NotInFish],
462 "wait until the qemu subprocess launches (no op)",
464 This function is a no op.
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete. However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
475 ("kill_subprocess", (RErr, []), -1, [],
477 "kill the qemu subprocess",
479 This kills the qemu subprocess. You should never need to call this.");
481 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483 "add an image to examine or modify",
485 This function adds a virtual machine disk image C<filename> to the
486 guest. The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
490 You don't necessarily need to be root when using libguestfs. However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>. In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
507 Note that this call checks for the existence of C<filename>. This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
510 the general C<guestfs_config> call instead.");
512 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514 "add a CD-ROM disk image to examine",
516 This function adds a virtual CD-ROM disk image to the guest.
518 This is equivalent to the qemu parameter C<-cdrom filename>.
526 This call checks for the existence of C<filename>. This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
529 the general C<guestfs_config> call instead.
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
539 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541 "add a drive in snapshot mode (read-only)",
543 This adds a drive in snapshot mode, making it effectively
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed. We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>. In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
560 C<readonly=on> is only added where qemu supports this option.
562 Note that this call checks for the existence of C<filename>. This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
565 the general C<guestfs_config> call instead.");
567 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569 "add qemu parameters",
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>. Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
576 The first character of C<param> string must be a C<-> (dash).
578 C<value> can be NULL.");
580 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
582 "set the qemu binary",
584 Set the qemu binary that we will use.
586 The default is chosen when the library was compiled by the
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
594 Note that you should call this function as early as possible
595 after creating the handle. This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results. Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
602 ("get_qemu", (RConstString "qemu", []), -1, [],
603 [InitNone, Always, TestRun (
605 "get the qemu binary",
607 Return the current qemu binary.
609 This is always non-NULL. If it wasn't set already, then this will
610 return the default qemu binary name.");
612 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
614 "set the search path",
616 Set the path that libguestfs searches for kernel and initrd.img.
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
621 Setting C<path> to C<NULL> restores the default path.");
623 ("get_path", (RConstString "path", []), -1, [],
624 [InitNone, Always, TestRun (
626 "get the search path",
628 Return the current search path.
630 This is always non-NULL. If it wasn't set already, then this will
631 return the default path.");
633 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635 "add options to kernel command line",
637 This function is used to add additional options to the
638 guest kernel command line.
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
646 ("get_append", (RConstOptString "append", []), -1, [],
647 (* This cannot be tested with the current framework. The
648 * function can return NULL in normal operations, which the
649 * test framework interprets as an error.
652 "get the additional kernel options",
654 Return the additional kernel options which are added to the
655 guest kernel command line.
657 If C<NULL> then no options are added.");
659 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
663 If C<autosync> is true, this enables autosync. Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
671 ("get_autosync", (RBool "autosync", []), -1, [],
672 [InitNone, Always, TestRun (
673 [["get_autosync"]])],
676 Get the autosync flag.");
678 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687 ("get_verbose", (RBool "verbose", []), -1, [],
691 This returns the verbose messages flag.");
693 ("is_ready", (RBool "ready", []), -1, [],
694 [InitNone, Always, TestOutputTrue (
696 "is ready to accept commands",
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
701 For more information on states, see L<guestfs(3)>.");
703 ("is_config", (RBool "config", []), -1, [],
704 [InitNone, Always, TestOutputFalse (
706 "is in configuration state",
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
711 For more information on states, see L<guestfs(3)>.");
713 ("is_launching", (RBool "launching", []), -1, [],
714 [InitNone, Always, TestOutputFalse (
715 [["is_launching"]])],
716 "is launching subprocess",
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
721 For more information on states, see L<guestfs(3)>.");
723 ("is_busy", (RBool "busy", []), -1, [],
724 [InitNone, Always, TestOutputFalse (
726 "is busy processing a command",
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
731 For more information on states, see L<guestfs(3)>.");
733 ("get_state", (RInt "state", []), -1, [],
735 "get the current state",
737 This returns the current state as an opaque integer. This is
738 only useful for printing debug and internal error messages.
740 For more information on states, see L<guestfs(3)>.");
742 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743 [InitNone, Always, TestOutputInt (
744 [["set_memsize"; "500"];
745 ["get_memsize"]], 500)],
746 "set memory allocated to the qemu subprocess",
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess. This only has any effect if called before
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
759 ("get_memsize", (RInt "memsize", []), -1, [],
760 [InitNone, Always, TestOutputIntOp (
761 [["get_memsize"]], ">=", 256)],
762 "get memory allocated to the qemu subprocess",
764 This gets the memory size in megabytes allocated to the
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
774 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775 [InitNone, Always, TestOutputIntOp (
776 [["get_pid"]], ">=", 1)],
777 "get PID of qemu subprocess",
779 Return the process ID of the qemu subprocess. If there is no
780 qemu subprocess, then this will return an error.
782 This is an internal call used for debugging and testing.");
784 ("version", (RStruct ("version", "version"), []), -1, [],
785 [InitNone, Always, TestOutputStruct (
786 [["version"]], [CompareWithInt ("major", 1)])],
787 "get the library version number",
789 Return the libguestfs version number that the program is linked
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against. You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
797 This call was added in version C<1.0.58>. In previous
798 versions of libguestfs there was no way to get the version
799 number. From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
802 The call returns a structure with four elements. The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet. The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
811 I<Note:> Don't use this call to test for availability
812 of features. Distro backports makes this unreliable. Use
813 C<guestfs_available> instead.");
815 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816 [InitNone, Always, TestOutputTrue (
817 [["set_selinux"; "true"];
819 "set SELinux enabled or disabled at appliance boot",
821 This sets the selinux flag that is passed to the appliance
822 at boot time. The default is C<selinux=0> (disabled).
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
830 ("get_selinux", (RBool "selinux", []), -1, [],
832 "get SELinux enabled flag",
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
840 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841 [InitNone, Always, TestOutputFalse (
842 [["set_trace"; "false"];
844 "enable or disable command traces",
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish. In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
860 ("get_trace", (RBool "trace", []), -1, [],
862 "get command trace enabled flag",
864 Return the command trace flag.");
866 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867 [InitNone, Always, TestOutputFalse (
868 [["set_direct"; "false"];
870 "enable or disable direct appliance mode",
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
880 You probably don't want to use this unless you know what you
883 The default is disabled.");
885 ("get_direct", (RBool "direct", []), -1, [],
887 "get direct appliance mode flag",
889 Return the direct appliance mode flag.");
891 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892 [InitNone, Always, TestOutputTrue (
893 [["set_recovery_proc"; "true"];
894 ["get_recovery_proc"]])],
895 "enable or disable the recovery process",
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process. The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself). In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
911 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
913 "get recovery process enabled flag",
915 Return the recovery process enabled flag.");
917 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919 "add a drive specifying the QEMU block emulation to use",
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
924 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
926 "add a drive read-only specifying the QEMU block emulation to use",
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
933 (* daemon_functions are any functions which cause some action
934 * to take place in the daemon.
937 let daemon_functions = [
938 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939 [InitEmpty, Always, TestOutput (
940 [["part_disk"; "/dev/sda"; "mbr"];
941 ["mkfs"; "ext2"; "/dev/sda1"];
942 ["mount"; "/dev/sda1"; "/"];
943 ["write_file"; "/new"; "new file contents"; "0"];
944 ["cat"; "/new"]], "new file contents")],
945 "mount a guest disk at a position in the filesystem",
947 Mount a guest disk at a position in the filesystem. Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest. If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
953 The rules are the same as for L<mount(2)>: A filesystem must
954 first be mounted on C</> before others can be mounted. Other
955 filesystems can only be mounted on directories which already
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly. This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability. Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
971 ("sync", (RErr, []), 2, [],
972 [ InitEmpty, Always, TestRun [["sync"]]],
973 "sync disks, writes are flushed through to the disk image",
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
981 ("touch", (RErr, [Pathname "path"]), 3, [],
982 [InitBasicFS, Always, TestOutputTrue (
984 ["exists"; "/new"]])],
985 "update file timestamps or create a new file",
987 Touch acts like the L<touch(1)> command. It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
991 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992 [InitISOFS, Always, TestOutput (
993 [["cat"; "/known-2"]], "abcdef\n")],
994 "list the contents of a file",
996 Return the contents of the file named C<path>.
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string). For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1003 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004 [], (* XXX Tricky to test because it depends on the exact format
1005 * of the 'ls -l' command, which changes between F10 and F11.
1007 "list the files in a directory (long format)",
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1012 This command is mostly useful for interactive sessions. It
1013 is I<not> intended that you try to parse the output string.");
1015 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016 [InitBasicFS, Always, TestOutputList (
1018 ["touch"; "/newer"];
1019 ["touch"; "/newest"];
1020 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021 "list the files in a directory",
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd). The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1027 This command is mostly useful for interactive sessions. Programs
1028 should probably use C<guestfs_readdir> instead.");
1030 ("list_devices", (RStringList "devices", []), 7, [],
1031 [InitEmpty, Always, TestOutputListOfDevices (
1032 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033 "list the block devices",
1035 List all the block devices.
1037 The full block device names are returned, eg. C</dev/sda>");
1039 ("list_partitions", (RStringList "partitions", []), 8, [],
1040 [InitBasicFS, Always, TestOutputListOfDevices (
1041 [["list_partitions"]], ["/dev/sda1"]);
1042 InitEmpty, Always, TestOutputListOfDevices (
1043 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045 "list the partitions",
1047 List all the partitions detected on all block devices.
1049 The full partition device names are returned, eg. C</dev/sda1>
1051 This does not return logical volumes. For that you will need to
1052 call C<guestfs_lvs>.");
1054 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056 [["pvs"]], ["/dev/sda1"]);
1057 InitEmpty, Always, TestOutputListOfDevices (
1058 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059 ["pvcreate"; "/dev/sda1"];
1060 ["pvcreate"; "/dev/sda2"];
1061 ["pvcreate"; "/dev/sda3"];
1062 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063 "list the LVM physical volumes (PVs)",
1065 List all the physical volumes detected. This is the equivalent
1066 of the L<pvs(8)> command.
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1071 See also C<guestfs_pvs_full>.");
1073 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074 [InitBasicFSonLVM, Always, TestOutputList (
1076 InitEmpty, Always, TestOutputList (
1077 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078 ["pvcreate"; "/dev/sda1"];
1079 ["pvcreate"; "/dev/sda2"];
1080 ["pvcreate"; "/dev/sda3"];
1081 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082 ["vgcreate"; "VG2"; "/dev/sda3"];
1083 ["vgs"]], ["VG1"; "VG2"])],
1084 "list the LVM volume groups (VGs)",
1086 List all the volumes groups detected. This is the equivalent
1087 of the L<vgs(8)> command.
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1092 See also C<guestfs_vgs_full>.");
1094 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095 [InitBasicFSonLVM, Always, TestOutputList (
1096 [["lvs"]], ["/dev/VG/LV"]);
1097 InitEmpty, Always, TestOutputList (
1098 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099 ["pvcreate"; "/dev/sda1"];
1100 ["pvcreate"; "/dev/sda2"];
1101 ["pvcreate"; "/dev/sda3"];
1102 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103 ["vgcreate"; "VG2"; "/dev/sda3"];
1104 ["lvcreate"; "LV1"; "VG1"; "50"];
1105 ["lvcreate"; "LV2"; "VG1"; "50"];
1106 ["lvcreate"; "LV3"; "VG2"; "50"];
1107 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108 "list the LVM logical volumes (LVs)",
1110 List all the logical volumes detected. This is the equivalent
1111 of the L<lvs(8)> command.
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1116 See also C<guestfs_lvs_full>.");
1118 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119 [], (* XXX how to test? *)
1120 "list the LVM physical volumes (PVs)",
1122 List all the physical volumes detected. This is the equivalent
1123 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1125 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM volume groups (VGs)",
1129 List all the volumes groups detected. This is the equivalent
1130 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1132 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133 [], (* XXX how to test? *)
1134 "list the LVM logical volumes (LVs)",
1136 List all the logical volumes detected. This is the equivalent
1137 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1139 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140 [InitISOFS, Always, TestOutputList (
1141 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142 InitISOFS, Always, TestOutputList (
1143 [["read_lines"; "/empty"]], [])],
1144 "read file as lines",
1146 Return the contents of the file named C<path>.
1148 The file contents are returned as a list of lines. Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line). For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1156 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157 [], (* XXX Augeas code needs tests. *)
1158 "create a new Augeas handle",
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1164 You must call this before using any other C<guestfs_aug_*>
1167 C<root> is the filesystem root. C<root> must not be NULL,
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1176 =item C<AUG_SAVE_BACKUP> = 1
1178 Keep the original file with a C<.augsave> extension.
1180 =item C<AUG_SAVE_NEWFILE> = 2
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1185 =item C<AUG_TYPE_CHECK> = 4
1187 Typecheck lenses (can be expensive).
1189 =item C<AUG_NO_STDINC> = 8
1191 Do not use standard load path for modules.
1193 =item C<AUG_SAVE_NOOP> = 16
1195 Make save a no-op, just record what would have been changed.
1197 =item C<AUG_NO_LOAD> = 32
1199 Do not load the tree in C<guestfs_aug_init>.
1203 To close the handle, you can call C<guestfs_aug_close>.
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1207 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208 [], (* XXX Augeas code needs tests. *)
1209 "close the current Augeas handle",
1211 Close the current Augeas handle and free up any resources
1212 used by it. After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1216 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217 [], (* XXX Augeas code needs tests. *)
1218 "define an Augeas variable",
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1227 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228 [], (* XXX Augeas code needs tests. *)
1229 "define an Augeas node",
1231 Defines a variable C<name> whose value is the result of
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1242 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "look up the value of an Augeas path",
1246 Look up the value associated with C<path>. If C<path>
1247 matches exactly one node, the C<value> is returned.");
1249 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250 [], (* XXX Augeas code needs tests. *)
1251 "set Augeas path to value",
1253 Set the value associated with C<path> to C<val>.
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL. Due to an oversight in the libguestfs API
1257 you cannot do that with this call. Instead you must use the
1258 C<guestfs_aug_clear> call.");
1260 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261 [], (* XXX Augeas code needs tests. *)
1262 "insert a sibling Augeas node",
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1272 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273 [], (* XXX Augeas code needs tests. *)
1274 "remove an Augeas path",
1276 Remove C<path> and all of its children.
1278 On success this returns the number of entries which were removed.");
1280 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1284 Move the node C<src> to C<dest>. C<src> must match exactly
1285 one node. C<dest> is overwritten if it exists.");
1287 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1289 "return Augeas nodes which match augpath",
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1295 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296 [], (* XXX Augeas code needs tests. *)
1297 "write all pending Augeas changes to disk",
1299 This writes all pending changes to disk.
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1304 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305 [], (* XXX Augeas code needs tests. *)
1306 "load files into the tree",
1308 Load files into the tree.
1310 See C<aug_load> in the Augeas documentation for the full gory
1313 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314 [], (* XXX Augeas code needs tests. *)
1315 "list Augeas nodes under augpath",
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1320 ("rm", (RErr, [Pathname "path"]), 29, [],
1321 [InitBasicFS, Always, TestRun
1324 InitBasicFS, Always, TestLastFail
1326 InitBasicFS, Always, TestLastFail
1331 Remove the single file C<path>.");
1333 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334 [InitBasicFS, Always, TestRun
1337 InitBasicFS, Always, TestLastFail
1338 [["rmdir"; "/new"]];
1339 InitBasicFS, Always, TestLastFail
1341 ["rmdir"; "/new"]]],
1342 "remove a directory",
1344 Remove the single directory C<path>.");
1346 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347 [InitBasicFS, Always, TestOutputFalse
1349 ["mkdir"; "/new/foo"];
1350 ["touch"; "/new/foo/bar"];
1352 ["exists"; "/new"]]],
1353 "remove a file or directory recursively",
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory. This is like the C<rm -rf> shell
1359 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360 [InitBasicFS, Always, TestOutputTrue
1362 ["is_dir"; "/new"]];
1363 InitBasicFS, Always, TestLastFail
1364 [["mkdir"; "/new/foo/bar"]]],
1365 "create a directory",
1367 Create a directory named C<path>.");
1369 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370 [InitBasicFS, Always, TestOutputTrue
1371 [["mkdir_p"; "/new/foo/bar"];
1372 ["is_dir"; "/new/foo/bar"]];
1373 InitBasicFS, Always, TestOutputTrue
1374 [["mkdir_p"; "/new/foo/bar"];
1375 ["is_dir"; "/new/foo"]];
1376 InitBasicFS, Always, TestOutputTrue
1377 [["mkdir_p"; "/new/foo/bar"];
1378 ["is_dir"; "/new"]];
1379 (* Regression tests for RHBZ#503133: *)
1380 InitBasicFS, Always, TestRun
1382 ["mkdir_p"; "/new"]];
1383 InitBasicFS, Always, TestLastFail
1385 ["mkdir_p"; "/new"]]],
1386 "create a directory and parents",
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary. This is like the C<mkdir -p> shell command.");
1391 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392 [], (* XXX Need stat command to test *)
1395 Change the mode (permissions) of C<path> to C<mode>. Only
1396 numeric modes are supported.
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1402 The mode actually set is affected by the umask.");
1404 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405 [], (* XXX Need stat command to test *)
1406 "change file owner and group",
1408 Change the file owner to C<owner> and group to C<group>.
1410 Only numeric uid and gid are supported. If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1414 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415 [InitISOFS, Always, TestOutputTrue (
1416 [["exists"; "/empty"]]);
1417 InitISOFS, Always, TestOutputTrue (
1418 [["exists"; "/directory"]])],
1419 "test if file or directory exists",
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1426 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427 [InitISOFS, Always, TestOutputTrue (
1428 [["is_file"; "/known-1"]]);
1429 InitISOFS, Always, TestOutputFalse (
1430 [["is_file"; "/directory"]])],
1431 "test if file exists",
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name. Note that it returns false for
1435 other objects like directories.
1437 See also C<guestfs_stat>.");
1439 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440 [InitISOFS, Always, TestOutputFalse (
1441 [["is_dir"; "/known-3"]]);
1442 InitISOFS, Always, TestOutputTrue (
1443 [["is_dir"; "/directory"]])],
1444 "test if file exists",
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name. Note that it returns false for
1448 other objects like files.
1450 See also C<guestfs_stat>.");
1452 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453 [InitEmpty, Always, TestOutputListOfDevices (
1454 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455 ["pvcreate"; "/dev/sda1"];
1456 ["pvcreate"; "/dev/sda2"];
1457 ["pvcreate"; "/dev/sda3"];
1458 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459 "create an LVM physical volume",
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1465 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466 [InitEmpty, Always, TestOutputList (
1467 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468 ["pvcreate"; "/dev/sda1"];
1469 ["pvcreate"; "/dev/sda2"];
1470 ["pvcreate"; "/dev/sda3"];
1471 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472 ["vgcreate"; "VG2"; "/dev/sda3"];
1473 ["vgs"]], ["VG1"; "VG2"])],
1474 "create an LVM volume group",
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1479 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480 [InitEmpty, Always, TestOutputList (
1481 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482 ["pvcreate"; "/dev/sda1"];
1483 ["pvcreate"; "/dev/sda2"];
1484 ["pvcreate"; "/dev/sda3"];
1485 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486 ["vgcreate"; "VG2"; "/dev/sda3"];
1487 ["lvcreate"; "LV1"; "VG1"; "50"];
1488 ["lvcreate"; "LV2"; "VG1"; "50"];
1489 ["lvcreate"; "LV3"; "VG2"; "50"];
1490 ["lvcreate"; "LV4"; "VG2"; "50"];
1491 ["lvcreate"; "LV5"; "VG2"; "50"];
1493 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495 "create an LVM logical volume",
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1500 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501 [InitEmpty, Always, TestOutput (
1502 [["part_disk"; "/dev/sda"; "mbr"];
1503 ["mkfs"; "ext2"; "/dev/sda1"];
1504 ["mount_options"; ""; "/dev/sda1"; "/"];
1505 ["write_file"; "/new"; "new file contents"; "0"];
1506 ["cat"; "/new"]], "new file contents")],
1507 "make a filesystem",
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume). The filesystem type is C<fstype>, for
1513 ("sfdisk", (RErr, [Device "device";
1514 Int "cyls"; Int "heads"; Int "sectors";
1515 StringList "lines"]), 43, [DangerWillRobinson],
1517 "create partitions on a block device",
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1522 C<device> should be a block device, for example C</dev/sda>.
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted. Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1532 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1533 information refer to the L<sfdisk(8)> manpage.
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1542 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543 [InitBasicFS, Always, TestOutput (
1544 [["write_file"; "/new"; "new file contents"; "0"];
1545 ["cat"; "/new"]], "new file contents");
1546 InitBasicFS, Always, TestOutput (
1547 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548 ["cat"; "/new"]], "\nnew file contents\n");
1549 InitBasicFS, Always, TestOutput (
1550 [["write_file"; "/new"; "\n\n"; "0"];
1551 ["cat"; "/new"]], "\n\n");
1552 InitBasicFS, Always, TestOutput (
1553 [["write_file"; "/new"; ""; "0"];
1554 ["cat"; "/new"]], "");
1555 InitBasicFS, Always, TestOutput (
1556 [["write_file"; "/new"; "\n\n\n"; "0"];
1557 ["cat"; "/new"]], "\n\n\n");
1558 InitBasicFS, Always, TestOutput (
1559 [["write_file"; "/new"; "\n"; "0"];
1560 ["cat"; "/new"]], "\n")],
1563 This call creates a file called C<path>. The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version. In the meantime
1574 use C<guestfs_upload>.");
1576 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577 [InitEmpty, Always, TestOutputListOfDevices (
1578 [["part_disk"; "/dev/sda"; "mbr"];
1579 ["mkfs"; "ext2"; "/dev/sda1"];
1580 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 ["mounts"]], ["/dev/sda1"]);
1582 InitEmpty, Always, TestOutputList (
1583 [["part_disk"; "/dev/sda"; "mbr"];
1584 ["mkfs"; "ext2"; "/dev/sda1"];
1585 ["mount_options"; ""; "/dev/sda1"; "/"];
1588 "unmount a filesystem",
1590 This unmounts the given filesystem. The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1594 ("mounts", (RStringList "devices", []), 46, [],
1595 [InitBasicFS, Always, TestOutputListOfDevices (
1596 [["mounts"]], ["/dev/sda1"])],
1597 "show mounted filesystems",
1599 This returns the list of currently mounted filesystems. It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1602 Some internal mounts are not shown.
1604 See also: C<guestfs_mountpoints>");
1606 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607 [InitBasicFS, Always, TestOutputList (
1610 (* check that umount_all can unmount nested mounts correctly: *)
1611 InitEmpty, Always, TestOutputList (
1612 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613 ["mkfs"; "ext2"; "/dev/sda1"];
1614 ["mkfs"; "ext2"; "/dev/sda2"];
1615 ["mkfs"; "ext2"; "/dev/sda3"];
1616 ["mount_options"; ""; "/dev/sda1"; "/"];
1618 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619 ["mkdir"; "/mp1/mp2"];
1620 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621 ["mkdir"; "/mp1/mp2/mp3"];
1624 "unmount all filesystems",
1626 This unmounts all mounted filesystems.
1628 Some internal mounts are not unmounted by this call.");
1630 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1632 "remove all LVM LVs, VGs and PVs",
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1637 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638 [InitISOFS, Always, TestOutput (
1639 [["file"; "/empty"]], "empty");
1640 InitISOFS, Always, TestOutput (
1641 [["file"; "/known-1"]], "ASCII text");
1642 InitISOFS, Always, TestLastFail (
1643 [["file"; "/notexists"]])],
1644 "determine file type",
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file. This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1650 This call will also transparently look inside various types
1653 The exact command which runs is C<file -zbsL path>. Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1657 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658 [InitBasicFS, Always, TestOutput (
1659 [["upload"; "test-command"; "/test-command"];
1660 ["chmod"; "0o755"; "/test-command"];
1661 ["command"; "/test-command 1"]], "Result1");
1662 InitBasicFS, Always, TestOutput (
1663 [["upload"; "test-command"; "/test-command"];
1664 ["chmod"; "0o755"; "/test-command"];
1665 ["command"; "/test-command 2"]], "Result2\n");
1666 InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 3"]], "\nResult3");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 4"]], "\nResult4\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 5"]], "\nResult5\n\n");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682 InitBasicFS, Always, TestOutput (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command 7"]], "");
1686 InitBasicFS, Always, TestOutput (
1687 [["upload"; "test-command"; "/test-command"];
1688 ["chmod"; "0o755"; "/test-command"];
1689 ["command"; "/test-command 8"]], "\n");
1690 InitBasicFS, Always, TestOutput (
1691 [["upload"; "test-command"; "/test-command"];
1692 ["chmod"; "0o755"; "/test-command"];
1693 ["command"; "/test-command 9"]], "\n\n");
1694 InitBasicFS, Always, TestOutput (
1695 [["upload"; "test-command"; "/test-command"];
1696 ["chmod"; "0o755"; "/test-command"];
1697 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698 InitBasicFS, Always, TestOutput (
1699 [["upload"; "test-command"; "/test-command"];
1700 ["chmod"; "0o755"; "/test-command"];
1701 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702 InitBasicFS, Always, TestLastFail (
1703 [["upload"; "test-command"; "/test-command"];
1704 ["chmod"; "0o755"; "/test-command"];
1705 ["command"; "/test-command"]])],
1706 "run a command from the guest filesystem",
1708 This call runs a command from the guest filesystem. The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters. The list must be
1716 non-empty (ie. must contain a program name). Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1720 The return value is anything printed to I<stdout> by
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message. The error message
1725 string is the content of I<stderr> from the command.
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>. If you require a program from
1729 another location, you should provide the full path in the
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places. It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1738 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739 [InitBasicFS, Always, TestOutputList (
1740 [["upload"; "test-command"; "/test-command"];
1741 ["chmod"; "0o755"; "/test-command"];
1742 ["command_lines"; "/test-command 1"]], ["Result1"]);
1743 InitBasicFS, Always, TestOutputList (
1744 [["upload"; "test-command"; "/test-command"];
1745 ["chmod"; "0o755"; "/test-command"];
1746 ["command_lines"; "/test-command 2"]], ["Result2"]);
1747 InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763 InitBasicFS, Always, TestOutputList (
1764 [["upload"; "test-command"; "/test-command"];
1765 ["chmod"; "0o755"; "/test-command"];
1766 ["command_lines"; "/test-command 7"]], []);
1767 InitBasicFS, Always, TestOutputList (
1768 [["upload"; "test-command"; "/test-command"];
1769 ["chmod"; "0o755"; "/test-command"];
1770 ["command_lines"; "/test-command 8"]], [""]);
1771 InitBasicFS, Always, TestOutputList (
1772 [["upload"; "test-command"; "/test-command"];
1773 ["chmod"; "0o755"; "/test-command"];
1774 ["command_lines"; "/test-command 9"]], ["";""]);
1775 InitBasicFS, Always, TestOutputList (
1776 [["upload"; "test-command"; "/test-command"];
1777 ["chmod"; "0o755"; "/test-command"];
1778 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779 InitBasicFS, Always, TestOutputList (
1780 [["upload"; "test-command"; "/test-command"];
1781 ["chmod"; "0o755"; "/test-command"];
1782 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783 "run a command, returning lines",
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1788 See also: C<guestfs_sh_lines>");
1790 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791 [InitISOFS, Always, TestOutputStruct (
1792 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793 "get file information",
1795 Returns file information for the given C<path>.
1797 This is the same as the C<stat(2)> system call.");
1799 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800 [InitISOFS, Always, TestOutputStruct (
1801 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802 "get file information for a symbolic link",
1804 Returns file information for the given C<path>.
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1810 This is the same as the C<lstat(2)> system call.");
1812 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813 [InitISOFS, Always, TestOutputStruct (
1814 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815 "get file system statistics",
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1821 This is the same as the C<statvfs(2)> system call.");
1823 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1825 "get ext2/ext3/ext4 superblock details",
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1830 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1831 manpage for more details. The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1835 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836 [InitEmpty, Always, TestOutputTrue (
1837 [["blockdev_setro"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "set block device to read-only",
1841 Sets the block device named C<device> to read-only.
1843 This uses the L<blockdev(8)> command.");
1845 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846 [InitEmpty, Always, TestOutputFalse (
1847 [["blockdev_setrw"; "/dev/sda"];
1848 ["blockdev_getro"; "/dev/sda"]])],
1849 "set block device to read-write",
1851 Sets the block device named C<device> to read-write.
1853 This uses the L<blockdev(8)> command.");
1855 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856 [InitEmpty, Always, TestOutputTrue (
1857 [["blockdev_setro"; "/dev/sda"];
1858 ["blockdev_getro"; "/dev/sda"]])],
1859 "is block device set to read-only",
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1864 This uses the L<blockdev(8)> command.");
1866 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867 [InitEmpty, Always, TestOutputInt (
1868 [["blockdev_getss"; "/dev/sda"]], 512)],
1869 "get sectorsize of block device",
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1877 This uses the L<blockdev(8)> command.");
1879 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880 [InitEmpty, Always, TestOutputInt (
1881 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882 "get blocksize of block device",
1884 This returns the block size of a device.
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1889 This uses the L<blockdev(8)> command.");
1891 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1893 "set blocksize of block device",
1895 This sets the block size of a device.
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1900 This uses the L<blockdev(8)> command.");
1902 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903 [InitEmpty, Always, TestOutputInt (
1904 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905 "get total size of device in 512-byte sectors",
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1914 This uses the L<blockdev(8)> command.");
1916 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917 [InitEmpty, Always, TestOutputInt (
1918 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919 "get total size of device in bytes",
1921 This returns the size of the device in bytes.
1923 See also C<guestfs_blockdev_getsz>.
1925 This uses the L<blockdev(8)> command.");
1927 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928 [InitEmpty, Always, TestRun
1929 [["blockdev_flushbufs"; "/dev/sda"]]],
1930 "flush device buffers",
1932 This tells the kernel to flush internal buffers associated
1935 This uses the L<blockdev(8)> command.");
1937 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938 [InitEmpty, Always, TestRun
1939 [["blockdev_rereadpt"; "/dev/sda"]]],
1940 "reread partition table",
1942 Reread the partition table on C<device>.
1944 This uses the L<blockdev(8)> command.");
1946 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947 [InitBasicFS, Always, TestOutput (
1948 (* Pick a file from cwd which isn't likely to change. *)
1949 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950 ["checksum"; "md5"; "/COPYING.LIB"]],
1951 Digest.to_hex (Digest.file "COPYING.LIB"))],
1952 "upload a file from the local machine",
1954 Upload local file C<filename> to C<remotefilename> on the
1957 C<filename> can also be a named pipe.
1959 See also C<guestfs_download>.");
1961 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962 [InitBasicFS, Always, TestOutput (
1963 (* Pick a file from cwd which isn't likely to change. *)
1964 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966 ["upload"; "testdownload.tmp"; "/upload"];
1967 ["checksum"; "md5"; "/upload"]],
1968 Digest.to_hex (Digest.file "COPYING.LIB"))],
1969 "download a file to the local machine",
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1974 C<filename> can also be a named pipe.
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1978 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979 [InitISOFS, Always, TestOutput (
1980 [["checksum"; "crc"; "/known-3"]], "2891671662");
1981 InitISOFS, Always, TestLastFail (
1982 [["checksum"; "crc"; "/notexists"]]);
1983 InitISOFS, Always, TestOutput (
1984 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985 InitISOFS, Always, TestOutput (
1986 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987 InitISOFS, Always, TestOutput (
1988 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989 InitISOFS, Always, TestOutput (
1990 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991 InitISOFS, Always, TestOutput (
1992 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993 InitISOFS, Always, TestOutput (
1994 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1995 (* Test for RHBZ#579608, absolute symbolic links. *)
1996 InitISOFS, Always, TestOutput (
1997 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1998 "compute MD5, SHAx or CRC checksum of file",
2000 This call computes the MD5, SHAx or CRC checksum of the
2003 The type of checksum to compute is given by the C<csumtype>
2004 parameter which must have one of the following values:
2010 Compute the cyclic redundancy check (CRC) specified by POSIX
2011 for the C<cksum> command.
2015 Compute the MD5 hash (using the C<md5sum> program).
2019 Compute the SHA1 hash (using the C<sha1sum> program).
2023 Compute the SHA224 hash (using the C<sha224sum> program).
2027 Compute the SHA256 hash (using the C<sha256sum> program).
2031 Compute the SHA384 hash (using the C<sha384sum> program).
2035 Compute the SHA512 hash (using the C<sha512sum> program).
2039 The checksum is returned as a printable string.
2041 To get the checksum for a device, use C<guestfs_checksum_device>.
2043 To get the checksums for many files, use C<guestfs_checksums_out>.");
2045 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2046 [InitBasicFS, Always, TestOutput (
2047 [["tar_in"; "../images/helloworld.tar"; "/"];
2048 ["cat"; "/hello"]], "hello\n")],
2049 "unpack tarfile to directory",
2051 This command uploads and unpacks local file C<tarfile> (an
2052 I<uncompressed> tar file) into C<directory>.
2054 To upload a compressed tarball, use C<guestfs_tgz_in>
2055 or C<guestfs_txz_in>.");
2057 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2059 "pack directory into tarfile",
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarfile>.
2064 To download a compressed tarball, use C<guestfs_tgz_out>
2065 or C<guestfs_txz_out>.");
2067 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2068 [InitBasicFS, Always, TestOutput (
2069 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2070 ["cat"; "/hello"]], "hello\n")],
2071 "unpack compressed tarball to directory",
2073 This command uploads and unpacks local file C<tarball> (a
2074 I<gzip compressed> tar file) into C<directory>.
2076 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2078 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2080 "pack directory into compressed tarball",
2082 This command packs the contents of C<directory> and downloads
2083 it to local file C<tarball>.
2085 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2087 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2088 [InitBasicFS, Always, TestLastFail (
2090 ["mount_ro"; "/dev/sda1"; "/"];
2091 ["touch"; "/new"]]);
2092 InitBasicFS, Always, TestOutput (
2093 [["write_file"; "/new"; "data"; "0"];
2095 ["mount_ro"; "/dev/sda1"; "/"];
2096 ["cat"; "/new"]], "data")],
2097 "mount a guest disk, read-only",
2099 This is the same as the C<guestfs_mount> command, but it
2100 mounts the filesystem with the read-only (I<-o ro>) flag.");
2102 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2104 "mount a guest disk with mount options",
2106 This is the same as the C<guestfs_mount> command, but it
2107 allows you to set the mount options as for the
2108 L<mount(8)> I<-o> flag.
2110 If the C<options> parameter is an empty string, then
2111 no options are passed (all options default to whatever
2112 the filesystem uses).");
2114 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2116 "mount a guest disk with mount options and vfstype",
2118 This is the same as the C<guestfs_mount> command, but it
2119 allows you to set both the mount options and the vfstype
2120 as for the L<mount(8)> I<-o> and I<-t> flags.");
2122 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2124 "debugging and internals",
2126 The C<guestfs_debug> command exposes some internals of
2127 C<guestfsd> (the guestfs daemon) that runs inside the
2130 There is no comprehensive help for this command. You have
2131 to look at the file C<daemon/debug.c> in the libguestfs source
2132 to find out what you can do.");
2134 ("lvremove", (RErr, [Device "device"]), 77, [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"];
2141 ["lvremove"; "/dev/VG/LV1"];
2142 ["lvs"]], ["/dev/VG/LV2"]);
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"];
2149 ["lvremove"; "/dev/VG"];
2151 InitEmpty, Always, TestOutputList (
2152 [["part_disk"; "/dev/sda"; "mbr"];
2153 ["pvcreate"; "/dev/sda1"];
2154 ["vgcreate"; "VG"; "/dev/sda1"];
2155 ["lvcreate"; "LV1"; "VG"; "50"];
2156 ["lvcreate"; "LV2"; "VG"; "50"];
2157 ["lvremove"; "/dev/VG"];
2159 "remove an LVM logical volume",
2161 Remove an LVM logical volume C<device>, where C<device> is
2162 the path to the LV, such as C</dev/VG/LV>.
2164 You can also remove all LVs in a volume group by specifying
2165 the VG name, C</dev/VG>.");
2167 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2168 [InitEmpty, Always, TestOutputList (
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"];
2176 InitEmpty, Always, TestOutputList (
2177 [["part_disk"; "/dev/sda"; "mbr"];
2178 ["pvcreate"; "/dev/sda1"];
2179 ["vgcreate"; "VG"; "/dev/sda1"];
2180 ["lvcreate"; "LV1"; "VG"; "50"];
2181 ["lvcreate"; "LV2"; "VG"; "50"];
2184 "remove an LVM volume group",
2186 Remove an LVM volume group C<vgname>, (for example C<VG>).
2188 This also forcibly removes all logical volumes in the volume
2191 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2192 [InitEmpty, Always, TestOutputListOfDevices (
2193 [["part_disk"; "/dev/sda"; "mbr"];
2194 ["pvcreate"; "/dev/sda1"];
2195 ["vgcreate"; "VG"; "/dev/sda1"];
2196 ["lvcreate"; "LV1"; "VG"; "50"];
2197 ["lvcreate"; "LV2"; "VG"; "50"];
2199 ["pvremove"; "/dev/sda1"];
2201 InitEmpty, Always, TestOutputListOfDevices (
2202 [["part_disk"; "/dev/sda"; "mbr"];
2203 ["pvcreate"; "/dev/sda1"];
2204 ["vgcreate"; "VG"; "/dev/sda1"];
2205 ["lvcreate"; "LV1"; "VG"; "50"];
2206 ["lvcreate"; "LV2"; "VG"; "50"];
2208 ["pvremove"; "/dev/sda1"];
2210 InitEmpty, Always, TestOutputListOfDevices (
2211 [["part_disk"; "/dev/sda"; "mbr"];
2212 ["pvcreate"; "/dev/sda1"];
2213 ["vgcreate"; "VG"; "/dev/sda1"];
2214 ["lvcreate"; "LV1"; "VG"; "50"];
2215 ["lvcreate"; "LV2"; "VG"; "50"];
2217 ["pvremove"; "/dev/sda1"];
2219 "remove an LVM physical volume",
2221 This wipes a physical volume C<device> so that LVM will no longer
2224 The implementation uses the C<pvremove> command which refuses to
2225 wipe physical volumes that contain any volume groups, so you have
2226 to remove those first.");
2228 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2229 [InitBasicFS, Always, TestOutput (
2230 [["set_e2label"; "/dev/sda1"; "testlabel"];
2231 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2232 "set the ext2/3/4 filesystem label",
2234 This sets the ext2/3/4 filesystem label of the filesystem on
2235 C<device> to C<label>. Filesystem labels are limited to
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2239 to return the existing label on a filesystem.");
2241 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2243 "get the ext2/3/4 filesystem label",
2245 This returns the ext2/3/4 filesystem label of the filesystem on
2248 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2249 (let uuid = uuidgen () in
2250 [InitBasicFS, Always, TestOutput (
2251 [["set_e2uuid"; "/dev/sda1"; uuid];
2252 ["get_e2uuid"; "/dev/sda1"]], uuid);
2253 InitBasicFS, Always, TestOutput (
2254 [["set_e2uuid"; "/dev/sda1"; "clear"];
2255 ["get_e2uuid"; "/dev/sda1"]], "");
2256 (* We can't predict what UUIDs will be, so just check the commands run. *)
2257 InitBasicFS, Always, TestRun (
2258 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2259 InitBasicFS, Always, TestRun (
2260 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2261 "set the ext2/3/4 filesystem UUID",
2263 This sets the ext2/3/4 filesystem UUID of the filesystem on
2264 C<device> to C<uuid>. The format of the UUID and alternatives
2265 such as C<clear>, C<random> and C<time> are described in the
2266 L<tune2fs(8)> manpage.
2268 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2269 to return the existing UUID of a filesystem.");
2271 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2273 "get the ext2/3/4 filesystem UUID",
2275 This returns the ext2/3/4 filesystem UUID of the filesystem on
2278 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2279 [InitBasicFS, Always, TestOutputInt (
2280 [["umount"; "/dev/sda1"];
2281 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2282 InitBasicFS, Always, TestOutputInt (
2283 [["umount"; "/dev/sda1"];
2284 ["zero"; "/dev/sda1"];
2285 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2286 "run the filesystem checker",
2288 This runs the filesystem checker (fsck) on C<device> which
2289 should have filesystem type C<fstype>.
2291 The returned integer is the status. See L<fsck(8)> for the
2292 list of status codes from C<fsck>.
2300 Multiple status codes can be summed together.
2304 A non-zero return code can mean \"success\", for example if
2305 errors have been corrected on the filesystem.
2309 Checking or repairing NTFS volumes is not supported
2314 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2316 ("zero", (RErr, [Device "device"]), 85, [],
2317 [InitBasicFS, Always, TestOutput (
2318 [["umount"; "/dev/sda1"];
2319 ["zero"; "/dev/sda1"];
2320 ["file"; "/dev/sda1"]], "data")],
2321 "write zeroes to the device",
2323 This command writes zeroes over the first few blocks of C<device>.
2325 How many blocks are zeroed isn't specified (but it's I<not> enough
2326 to securely wipe the device). It should be sufficient to remove
2327 any partition tables, filesystem superblocks and so on.
2329 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2331 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2332 (* Test disabled because grub-install incompatible with virtio-blk driver.
2333 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2335 [InitBasicFS, Disabled, TestOutputTrue (
2336 [["grub_install"; "/"; "/dev/sda1"];
2337 ["is_dir"; "/boot"]])],
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.");
2343 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344 [InitBasicFS, Always, TestOutput (
2345 [["write_file"; "/old"; "file content"; "0"];
2346 ["cp"; "/old"; "/new"];
2347 ["cat"; "/new"]], "file content");
2348 InitBasicFS, Always, TestOutputTrue (
2349 [["write_file"; "/old"; "file content"; "0"];
2350 ["cp"; "/old"; "/new"];
2351 ["is_file"; "/old"]]);
2352 InitBasicFS, Always, TestOutput (
2353 [["write_file"; "/old"; "file content"; "0"];
2355 ["cp"; "/old"; "/dir/new"];
2356 ["cat"; "/dir/new"]], "file content")],
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2362 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363 [InitBasicFS, Always, TestOutput (
2364 [["mkdir"; "/olddir"];
2365 ["mkdir"; "/newdir"];
2366 ["write_file"; "/olddir/file"; "file content"; "0"];
2367 ["cp_a"; "/olddir"; "/newdir"];
2368 ["cat"; "/newdir/olddir/file"]], "file content")],
2369 "copy a file or directory recursively",
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2374 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375 [InitBasicFS, Always, TestOutput (
2376 [["write_file"; "/old"; "file content"; "0"];
2377 ["mv"; "/old"; "/new"];
2378 ["cat"; "/new"]], "file content");
2379 InitBasicFS, Always, TestOutputFalse (
2380 [["write_file"; "/old"; "file content"; "0"];
2381 ["mv"; "/old"; "/new"];
2382 ["is_file"; "/old"]])],
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2388 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389 [InitEmpty, Always, TestRun (
2390 [["drop_caches"; "3"]])],
2391 "drop kernel page cache, dentries and inodes",
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches. The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2398 Setting C<whattodrop> to 3 should drop everything.
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2403 ("dmesg", (RString "kmsgs", []), 91, [],
2404 [InitEmpty, Always, TestRun (
2406 "return kernel messages",
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel. This is sometimes useful for extended
2410 debugging of problems.
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2417 ("ping_daemon", (RErr, []), 92, [],
2418 [InitEmpty, Always, TestRun (
2419 [["ping_daemon"]])],
2420 "ping the guest daemon",
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess. Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2427 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428 [InitBasicFS, Always, TestOutputTrue (
2429 [["write_file"; "/file1"; "contents of a file"; "0"];
2430 ["cp"; "/file1"; "/file2"];
2431 ["equal"; "/file1"; "/file2"]]);
2432 InitBasicFS, Always, TestOutputFalse (
2433 [["write_file"; "/file1"; "contents of a file"; "0"];
2434 ["write_file"; "/file2"; "contents of another file"; "0"];
2435 ["equal"; "/file1"; "/file2"]]);
2436 InitBasicFS, Always, TestLastFail (
2437 [["equal"; "/file1"; "/file2"]])],
2438 "test if two files have equal contents",
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2443 The external L<cmp(1)> program is used for the comparison.");
2445 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446 [InitISOFS, Always, TestOutputList (
2447 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448 InitISOFS, Always, TestOutputList (
2449 [["strings"; "/empty"]], [])],
2450 "print the printable strings in a file",
2452 This runs the L<strings(1)> command on a file and returns
2453 the list of printable strings found.");
2455 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2456 [InitISOFS, Always, TestOutputList (
2457 [["strings_e"; "b"; "/known-5"]], []);
2458 InitBasicFS, Disabled, TestOutputList (
2459 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2460 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2461 "print the printable strings in a file",
2463 This is like the C<guestfs_strings> command, but allows you to
2464 specify the encoding.
2466 See the L<strings(1)> manpage for the full list of encodings.
2468 Commonly useful encodings are C<l> (lower case L) which will
2469 show strings inside Windows/x86 files.
2471 The returned strings are transcoded to UTF-8.");
2473 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2474 [InitISOFS, Always, TestOutput (
2475 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2476 (* Test for RHBZ#501888c2 regression which caused large hexdump
2477 * commands to segfault.
2479 InitISOFS, Always, TestRun (
2480 [["hexdump"; "/100krandom"]]);
2481 (* Test for RHBZ#579608, absolute symbolic links. *)
2482 InitISOFS, Always, TestRun (
2483 [["hexdump"; "/abssymlink"]])],
2484 "dump a file in hexadecimal",
2486 This runs C<hexdump -C> on the given C<path>. The result is
2487 the human-readable, canonical hex dump of the file.");
2489 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2490 [InitNone, Always, TestOutput (
2491 [["part_disk"; "/dev/sda"; "mbr"];
2492 ["mkfs"; "ext3"; "/dev/sda1"];
2493 ["mount_options"; ""; "/dev/sda1"; "/"];
2494 ["write_file"; "/new"; "test file"; "0"];
2495 ["umount"; "/dev/sda1"];
2496 ["zerofree"; "/dev/sda1"];
2497 ["mount_options"; ""; "/dev/sda1"; "/"];
2498 ["cat"; "/new"]], "test file")],
2499 "zero unused inodes and disk blocks on ext2/3 filesystem",
2501 This runs the I<zerofree> program on C<device>. This program
2502 claims to zero unused inodes and disk blocks on an ext2/3
2503 filesystem, thus making it possible to compress the filesystem
2506 You should B<not> run this program if the filesystem is
2509 It is possible that using this program can damage the filesystem
2510 or data on the filesystem.");
2512 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2514 "resize an LVM physical volume",
2516 This resizes (expands or shrinks) an existing LVM physical
2517 volume to match the new size of the underlying device.");
2519 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2520 Int "cyls"; Int "heads"; Int "sectors";
2521 String "line"]), 99, [DangerWillRobinson],
2523 "modify a single partition on a block device",
2525 This runs L<sfdisk(8)> option to modify just the single
2526 partition C<n> (note: C<n> counts from 1).
2528 For other parameters, see C<guestfs_sfdisk>. You should usually
2529 pass C<0> for the cyls/heads/sectors parameters.
2531 See also: C<guestfs_part_add>");
2533 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2535 "display the partition table",
2537 This displays the partition table on C<device>, in the
2538 human-readable output of the L<sfdisk(8)> command. It is
2539 not intended to be parsed.
2541 See also: C<guestfs_part_list>");
2543 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2545 "display the kernel geometry",
2547 This displays the kernel's idea of the geometry of C<device>.
2549 The result is in human-readable format, and not designed to
2552 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2554 "display the disk geometry from the partition table",
2556 This displays the disk geometry of C<device> read from the
2557 partition table. Especially in the case where the underlying
2558 block device has been resized, this can be different from the
2559 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2561 The result is in human-readable format, and not designed to
2564 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2566 "activate or deactivate all volume groups",
2568 This command activates or (if C<activate> is false) deactivates
2569 all logical volumes in all volume groups.
2570 If activated, then they are made known to the
2571 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2572 then those devices disappear.
2574 This command is the same as running C<vgchange -a y|n>");
2576 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2578 "activate or deactivate some volume groups",
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in the listed volume groups C<volgroups>.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2584 then those devices disappear.
2586 This command is the same as running C<vgchange -a y|n volgroups...>
2588 Note that if C<volgroups> is an empty list then B<all> volume groups
2589 are activated or deactivated.");
2591 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2592 [InitNone, Always, TestOutput (
2593 [["part_disk"; "/dev/sda"; "mbr"];
2594 ["pvcreate"; "/dev/sda1"];
2595 ["vgcreate"; "VG"; "/dev/sda1"];
2596 ["lvcreate"; "LV"; "VG"; "10"];
2597 ["mkfs"; "ext2"; "/dev/VG/LV"];
2598 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2599 ["write_file"; "/new"; "test content"; "0"];
2601 ["lvresize"; "/dev/VG/LV"; "20"];
2602 ["e2fsck_f"; "/dev/VG/LV"];
2603 ["resize2fs"; "/dev/VG/LV"];
2604 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2605 ["cat"; "/new"]], "test content");
2606 InitNone, Always, TestRun (
2607 (* Make an LV smaller to test RHBZ#587484. *)
2608 [["part_disk"; "/dev/sda"; "mbr"];
2609 ["pvcreate"; "/dev/sda1"];
2610 ["vgcreate"; "VG"; "/dev/sda1"];
2611 ["lvcreate"; "LV"; "VG"; "20"];
2612 ["lvresize"; "/dev/VG/LV"; "10"]])],
2613 "resize an LVM logical volume",
2615 This resizes (expands or shrinks) an existing LVM logical
2616 volume to C<mbytes>. When reducing, data in the reduced part
2619 ("resize2fs", (RErr, [Device "device"]), 106, [],
2620 [], (* lvresize tests this *)
2621 "resize an ext2/ext3 filesystem",
2623 This resizes an ext2 or ext3 filesystem to match the size of
2624 the underlying device.
2626 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2627 on the C<device> before calling this command. For unknown reasons
2628 C<resize2fs> sometimes gives an error about this and sometimes not.
2629 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2630 calling this function.");
2632 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2633 [InitBasicFS, Always, TestOutputList (
2634 [["find"; "/"]], ["lost+found"]);
2635 InitBasicFS, Always, TestOutputList (
2639 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2640 InitBasicFS, Always, TestOutputList (
2641 [["mkdir_p"; "/a/b/c"];
2642 ["touch"; "/a/b/c/d"];
2643 ["find"; "/a/b/"]], ["c"; "c/d"])],
2644 "find all files and directories",
2646 This command lists out all files and directories, recursively,
2647 starting at C<directory>. It is essentially equivalent to
2648 running the shell command C<find directory -print> but some
2649 post-processing happens on the output, described below.
2651 This returns a list of strings I<without any prefix>. Thus
2652 if the directory structure was:
2658 then the returned list from C<guestfs_find> C</tmp> would be
2666 If C<directory> is not a directory, then this command returns
2669 The returned list is sorted.
2671 See also C<guestfs_find0>.");
2673 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2674 [], (* lvresize tests this *)
2675 "check an ext2/ext3 filesystem",
2677 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2678 filesystem checker on C<device>, noninteractively (C<-p>),
2679 even if the filesystem appears to be clean (C<-f>).
2681 This command is only needed because of C<guestfs_resize2fs>
2682 (q.v.). Normally you should use C<guestfs_fsck>.");
2684 ("sleep", (RErr, [Int "secs"]), 109, [],
2685 [InitNone, Always, TestRun (
2687 "sleep for some seconds",
2689 Sleep for C<secs> seconds.");
2691 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2692 [InitNone, Always, TestOutputInt (
2693 [["part_disk"; "/dev/sda"; "mbr"];
2694 ["mkfs"; "ntfs"; "/dev/sda1"];
2695 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2696 InitNone, Always, TestOutputInt (
2697 [["part_disk"; "/dev/sda"; "mbr"];
2698 ["mkfs"; "ext2"; "/dev/sda1"];
2699 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2700 "probe NTFS volume",
2702 This command runs the L<ntfs-3g.probe(8)> command which probes
2703 an NTFS C<device> for mountability. (Not all NTFS volumes can
2704 be mounted read-write, and some cannot be mounted at all).
2706 C<rw> is a boolean flag. Set it to true if you want to test
2707 if the volume can be mounted read-write. Set it to false if
2708 you want to test if the volume can be mounted read-only.
2710 The return value is an integer which C<0> if the operation
2711 would succeed, or some non-zero value documented in the
2712 L<ntfs-3g.probe(8)> manual page.");
2714 ("sh", (RString "output", [String "command"]), 111, [],
2715 [], (* XXX needs tests *)
2716 "run a command via the shell",
2718 This call runs a command from the guest filesystem via the
2721 This is like C<guestfs_command>, but passes the command to:
2723 /bin/sh -c \"command\"
2725 Depending on the guest's shell, this usually results in
2726 wildcards being expanded, shell expressions being interpolated
2729 All the provisos about C<guestfs_command> apply to this call.");
2731 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2732 [], (* XXX needs tests *)
2733 "run a command via the shell returning lines",
2735 This is the same as C<guestfs_sh>, but splits the result
2736 into a list of lines.
2738 See also: C<guestfs_command_lines>");
2740 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2741 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2742 * code in stubs.c, since all valid glob patterns must start with "/".
2743 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2745 [InitBasicFS, Always, TestOutputList (
2746 [["mkdir_p"; "/a/b/c"];
2747 ["touch"; "/a/b/c/d"];
2748 ["touch"; "/a/b/c/e"];
2749 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2750 InitBasicFS, Always, TestOutputList (
2751 [["mkdir_p"; "/a/b/c"];
2752 ["touch"; "/a/b/c/d"];
2753 ["touch"; "/a/b/c/e"];
2754 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2755 InitBasicFS, Always, TestOutputList (
2756 [["mkdir_p"; "/a/b/c"];
2757 ["touch"; "/a/b/c/d"];
2758 ["touch"; "/a/b/c/e"];
2759 ["glob_expand"; "/a/*/x/*"]], [])],
2760 "expand a wildcard path",
2762 This command searches for all the pathnames matching
2763 C<pattern> according to the wildcard expansion rules
2766 If no paths match, then this returns an empty list
2767 (note: not an error).
2769 It is just a wrapper around the C L<glob(3)> function
2770 with flags C<GLOB_MARK|GLOB_BRACE>.
2771 See that manual page for more details.");
2773 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2774 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2775 [["scrub_device"; "/dev/sdc"]])],
2776 "scrub (securely wipe) a device",
2778 This command writes patterns over C<device> to make data retrieval
2781 It is an interface to the L<scrub(1)> program. See that
2782 manual page for more details.");
2784 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2785 [InitBasicFS, Always, TestRun (
2786 [["write_file"; "/file"; "content"; "0"];
2787 ["scrub_file"; "/file"]])],
2788 "scrub (securely wipe) a file",
2790 This command writes patterns over a file to make data retrieval
2793 The file is I<removed> after scrubbing.
2795 It is an interface to the L<scrub(1)> program. See that
2796 manual page for more details.");
2798 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2799 [], (* XXX needs testing *)
2800 "scrub (securely wipe) free space",
2802 This command creates the directory C<dir> and then fills it
2803 with files until the filesystem is full, and scrubs the files
2804 as for C<guestfs_scrub_file>, and deletes them.
2805 The intention is to scrub any free space on the partition
2808 It is an interface to the L<scrub(1)> program. See that
2809 manual page for more details.");
2811 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2812 [InitBasicFS, Always, TestRun (
2814 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2815 "create a temporary directory",
2817 This command creates a temporary directory. The
2818 C<template> parameter should be a full pathname for the
2819 temporary directory name with the final six characters being
2822 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2823 the second one being suitable for Windows filesystems.
2825 The name of the temporary directory that was created
2828 The temporary directory is created with mode 0700
2829 and is owned by root.
2831 The caller is responsible for deleting the temporary
2832 directory and its contents after use.
2834 See also: L<mkdtemp(3)>");
2836 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2837 [InitISOFS, Always, TestOutputInt (
2838 [["wc_l"; "/10klines"]], 10000)],
2839 "count lines in a file",
2841 This command counts the lines in a file, using the
2842 C<wc -l> external command.");
2844 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2845 [InitISOFS, Always, TestOutputInt (
2846 [["wc_w"; "/10klines"]], 10000)],
2847 "count words in a file",
2849 This command counts the words in a file, using the
2850 C<wc -w> external command.");
2852 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2853 [InitISOFS, Always, TestOutputInt (
2854 [["wc_c"; "/100kallspaces"]], 102400)],
2855 "count characters in a file",
2857 This command counts the characters in a file, using the
2858 C<wc -c> external command.");
2860 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2861 [InitISOFS, Always, TestOutputList (
2862 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2863 "return first 10 lines of a file",
2865 This command returns up to the first 10 lines of a file as
2866 a list of strings.");
2868 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2869 [InitISOFS, Always, TestOutputList (
2870 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2871 InitISOFS, Always, TestOutputList (
2872 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2873 InitISOFS, Always, TestOutputList (
2874 [["head_n"; "0"; "/10klines"]], [])],
2875 "return first N lines of a file",
2877 If the parameter C<nrlines> is a positive number, this returns the first
2878 C<nrlines> lines of the file C<path>.
2880 If the parameter C<nrlines> is a negative number, this returns lines
2881 from the file C<path>, excluding the last C<nrlines> lines.
2883 If the parameter C<nrlines> is zero, this returns an empty list.");
2885 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2886 [InitISOFS, Always, TestOutputList (
2887 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2888 "return last 10 lines of a file",
2890 This command returns up to the last 10 lines of a file as
2891 a list of strings.");
2893 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2894 [InitISOFS, Always, TestOutputList (
2895 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2896 InitISOFS, Always, TestOutputList (
2897 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2898 InitISOFS, Always, TestOutputList (
2899 [["tail_n"; "0"; "/10klines"]], [])],
2900 "return last N lines of a file",
2902 If the parameter C<nrlines> is a positive number, this returns the last
2903 C<nrlines> lines of the file C<path>.
2905 If the parameter C<nrlines> is a negative number, this returns lines
2906 from the file C<path>, starting with the C<-nrlines>th line.
2908 If the parameter C<nrlines> is zero, this returns an empty list.");
2910 ("df", (RString "output", []), 125, [],
2911 [], (* XXX Tricky to test because it depends on the exact format
2912 * of the 'df' command and other imponderables.
2914 "report file system disk space usage",
2916 This command runs the C<df> command to report disk space used.
2918 This command is mostly useful for interactive sessions. It
2919 is I<not> intended that you try to parse the output string.
2920 Use C<statvfs> from programs.");
2922 ("df_h", (RString "output", []), 126, [],
2923 [], (* XXX Tricky to test because it depends on the exact format
2924 * of the 'df' command and other imponderables.
2926 "report file system disk space usage (human readable)",
2928 This command runs the C<df -h> command to report disk space used
2929 in human-readable format.
2931 This command is mostly useful for interactive sessions. It
2932 is I<not> intended that you try to parse the output string.
2933 Use C<statvfs> from programs.");
2935 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2936 [InitISOFS, Always, TestOutputInt (
2937 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2938 "estimate file space usage",
2940 This command runs the C<du -s> command to estimate file space
2943 C<path> can be a file or a directory. If C<path> is a directory
2944 then the estimate includes the contents of the directory and all
2945 subdirectories (recursively).
2947 The result is the estimated size in I<kilobytes>
2948 (ie. units of 1024 bytes).");
2950 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2951 [InitISOFS, Always, TestOutputList (
2952 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2953 "list files in an initrd",
2955 This command lists out files contained in an initrd.
2957 The files are listed without any initial C</> character. The
2958 files are listed in the order they appear (not necessarily
2959 alphabetical). Directory names are listed as separate items.
2961 Old Linux kernels (2.4 and earlier) used a compressed ext2
2962 filesystem as initrd. We I<only> support the newer initramfs
2963 format (compressed cpio files).");
2965 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2967 "mount a file using the loop device",
2969 This command lets you mount C<file> (a filesystem image
2970 in a file) on a mount point. It is entirely equivalent to
2971 the command C<mount -o loop file mountpoint>.");
2973 ("mkswap", (RErr, [Device "device"]), 130, [],
2974 [InitEmpty, Always, TestRun (
2975 [["part_disk"; "/dev/sda"; "mbr"];
2976 ["mkswap"; "/dev/sda1"]])],
2977 "create a swap partition",
2979 Create a swap partition on C<device>.");
2981 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2982 [InitEmpty, Always, TestRun (
2983 [["part_disk"; "/dev/sda"; "mbr"];
2984 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2985 "create a swap partition with a label",
2987 Create a swap partition on C<device> with label C<label>.
2989 Note that you cannot attach a swap label to a block device
2990 (eg. C</dev/sda>), just to a partition. This appears to be
2991 a limitation of the kernel or swap tools.");
2993 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2994 (let uuid = uuidgen () in
2995 [InitEmpty, Always, TestRun (
2996 [["part_disk"; "/dev/sda"; "mbr"];
2997 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2998 "create a swap partition with an explicit UUID",
3000 Create a swap partition on C<device> with UUID C<uuid>.");
3002 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3003 [InitBasicFS, Always, TestOutputStruct (
3004 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3005 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3006 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3007 InitBasicFS, Always, TestOutputStruct (
3008 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3009 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3010 "make block, character or FIFO devices",
3012 This call creates block or character special devices, or
3013 named pipes (FIFOs).
3015 The C<mode> parameter should be the mode, using the standard
3016 constants. C<devmajor> and C<devminor> are the
3017 device major and minor numbers, only used when creating block
3018 and character special devices.
3020 Note that, just like L<mknod(2)>, the mode must be bitwise
3021 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3022 just creates a regular file). These constants are
3023 available in the standard Linux header files, or you can use
3024 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3025 which are wrappers around this command which bitwise OR
3026 in the appropriate constant for you.
3028 The mode actually set is affected by the umask.");
3030 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3031 [InitBasicFS, Always, TestOutputStruct (
3032 [["mkfifo"; "0o777"; "/node"];
3033 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3034 "make FIFO (named pipe)",
3036 This call creates a FIFO (named pipe) called C<path> with
3037 mode C<mode>. It is just a convenient wrapper around
3040 The mode actually set is affected by the umask.");
3042 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3043 [InitBasicFS, Always, TestOutputStruct (
3044 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3045 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3046 "make block device node",
3048 This call creates a block device node called C<path> with
3049 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3050 It is just a convenient wrapper around C<guestfs_mknod>.
3052 The mode actually set is affected by the umask.");
3054 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3055 [InitBasicFS, Always, TestOutputStruct (
3056 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3057 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3058 "make char device node",
3060 This call creates a char device node called C<path> with
3061 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3062 It is just a convenient wrapper around C<guestfs_mknod>.
3064 The mode actually set is affected by the umask.");
3066 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3067 [InitEmpty, Always, TestOutputInt (
3068 [["umask"; "0o22"]], 0o22)],
3069 "set file mode creation mask (umask)",
3071 This function sets the mask used for creating new files and
3072 device nodes to C<mask & 0777>.
3074 Typical umask values would be C<022> which creates new files
3075 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3076 C<002> which creates new files with permissions like
3077 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3079 The default umask is C<022>. This is important because it
3080 means that directories and device nodes will be created with
3081 C<0644> or C<0755> mode even if you specify C<0777>.
3083 See also C<guestfs_get_umask>,
3084 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3086 This call returns the previous umask.");
3088 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3090 "read directories entries",
3092 This returns the list of directory entries in directory C<dir>.
3094 All entries in the directory are returned, including C<.> and
3095 C<..>. The entries are I<not> sorted, but returned in the same
3096 order as the underlying filesystem.
3098 Also this call returns basic file type information about each
3099 file. The C<ftyp> field will contain one of the following characters:
3137 The L<readdir(3)> returned a C<d_type> field with an
3142 This function is primarily intended for use by programs. To
3143 get a simple list of names, use C<guestfs_ls>. To get a printable
3144 directory for human consumption, use C<guestfs_ll>.");
3146 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3148 "create partitions on a block device",
3150 This is a simplified interface to the C<guestfs_sfdisk>
3151 command, where partition sizes are specified in megabytes
3152 only (rounded to the nearest cylinder) and you don't need
3153 to specify the cyls, heads and sectors parameters which
3154 were rarely if ever used anyway.
3156 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3157 and C<guestfs_part_disk>");
3159 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3161 "determine file type inside a compressed file",
3163 This command runs C<file> after first decompressing C<path>
3166 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3168 Since 1.0.63, use C<guestfs_file> instead which can now
3169 process compressed files.");
3171 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3173 "list extended attributes of a file or directory",
3175 This call lists the extended attributes of the file or directory
3178 At the system call level, this is a combination of the
3179 L<listxattr(2)> and L<getxattr(2)> calls.
3181 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3183 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3185 "list extended attributes of a file or directory",
3187 This is the same as C<guestfs_getxattrs>, but if C<path>
3188 is a symbolic link, then it returns the extended attributes
3189 of the link itself.");
3191 ("setxattr", (RErr, [String "xattr";
3192 String "val"; Int "vallen"; (* will be BufferIn *)
3193 Pathname "path"]), 143, [Optional "linuxxattrs"],
3195 "set extended attribute of a file or directory",
3197 This call sets the extended attribute named C<xattr>
3198 of the file C<path> to the value C<val> (of length C<vallen>).
3199 The value is arbitrary 8 bit data.
3201 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3203 ("lsetxattr", (RErr, [String "xattr";
3204 String "val"; Int "vallen"; (* will be BufferIn *)
3205 Pathname "path"]), 144, [Optional "linuxxattrs"],
3207 "set extended attribute of a file or directory",
3209 This is the same as C<guestfs_setxattr>, but if C<path>
3210 is a symbolic link, then it sets an extended attribute
3211 of the link itself.");
3213 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3215 "remove extended attribute of a file or directory",
3217 This call removes the extended attribute named C<xattr>
3218 of the file C<path>.
3220 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3222 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3224 "remove extended attribute of a file or directory",
3226 This is the same as C<guestfs_removexattr>, but if C<path>
3227 is a symbolic link, then it removes an extended attribute
3228 of the link itself.");
3230 ("mountpoints", (RHashtable "mps", []), 147, [],
3234 This call is similar to C<guestfs_mounts>. That call returns
3235 a list of devices. This one returns a hash table (map) of
3236 device name to directory where the device is mounted.");
3238 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3239 (* This is a special case: while you would expect a parameter
3240 * of type "Pathname", that doesn't work, because it implies
3241 * NEED_ROOT in the generated calling code in stubs.c, and
3242 * this function cannot use NEED_ROOT.
3245 "create a mountpoint",
3247 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3248 specialized calls that can be used to create extra mountpoints
3249 before mounting the first filesystem.
3251 These calls are I<only> necessary in some very limited circumstances,
3252 mainly the case where you want to mount a mix of unrelated and/or
3253 read-only filesystems together.
3255 For example, live CDs often contain a \"Russian doll\" nest of
3256 filesystems, an ISO outer layer, with a squashfs image inside, with
3257 an ext2/3 image inside that. You can unpack this as follows
3260 add-ro Fedora-11-i686-Live.iso
3263 mkmountpoint /squash
3266 mount-loop /cd/LiveOS/squashfs.img /squash
3267 mount-loop /squash/LiveOS/ext3fs.img /ext3
3269 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3271 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3273 "remove a mountpoint",
3275 This calls removes a mountpoint that was previously created
3276 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3277 for full details.");
3279 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3280 [InitISOFS, Always, TestOutputBuffer (
3281 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3284 This calls returns the contents of the file C<path> as a
3287 Unlike C<guestfs_cat>, this function can correctly
3288 handle files that contain embedded ASCII NUL characters.
3289 However unlike C<guestfs_download>, this function is limited
3290 in the total size of file that can be handled.");
3292 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3293 [InitISOFS, Always, TestOutputList (
3294 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3295 InitISOFS, Always, TestOutputList (
3296 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3297 "return lines matching a pattern",
3299 This calls the external C<grep> program and returns the
3302 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3303 [InitISOFS, Always, TestOutputList (
3304 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3305 "return lines matching a pattern",
3307 This calls the external C<egrep> program and returns the
3310 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3311 [InitISOFS, Always, TestOutputList (
3312 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3313 "return lines matching a pattern",
3315 This calls the external C<fgrep> program and returns the
3318 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3319 [InitISOFS, Always, TestOutputList (
3320 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3321 "return lines matching a pattern",
3323 This calls the external C<grep -i> program and returns the
3326 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3327 [InitISOFS, Always, TestOutputList (
3328 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3329 "return lines matching a pattern",
3331 This calls the external C<egrep -i> program and returns the
3334 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3335 [InitISOFS, Always, TestOutputList (
3336 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3337 "return lines matching a pattern",
3339 This calls the external C<fgrep -i> program and returns the
3342 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3343 [InitISOFS, Always, TestOutputList (
3344 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3345 "return lines matching a pattern",
3347 This calls the external C<zgrep> program and returns the
3350 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3351 [InitISOFS, Always, TestOutputList (
3352 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3353 "return lines matching a pattern",
3355 This calls the external C<zegrep> program and returns the
3358 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3359 [InitISOFS, Always, TestOutputList (
3360 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3361 "return lines matching a pattern",
3363 This calls the external C<zfgrep> program and returns the
3366 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3367 [InitISOFS, Always, TestOutputList (
3368 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3369 "return lines matching a pattern",
3371 This calls the external C<zgrep -i> program and returns the
3374 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3375 [InitISOFS, Always, TestOutputList (
3376 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3377 "return lines matching a pattern",
3379 This calls the external C<zegrep -i> program and returns the
3382 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3383 [InitISOFS, Always, TestOutputList (
3384 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3385 "return lines matching a pattern",
3387 This calls the external C<zfgrep -i> program and returns the
3390 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3391 [InitISOFS, Always, TestOutput (
3392 [["realpath"; "/../directory"]], "/directory")],
3393 "canonicalized absolute pathname",
3395 Return the canonicalized absolute pathname of C<path>. The
3396 returned path has no C<.>, C<..> or symbolic link path elements.");
3398 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3399 [InitBasicFS, Always, TestOutputStruct (
3402 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3403 "create a hard link",
3405 This command creates a hard link using the C<ln> command.");
3407 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3408 [InitBasicFS, Always, TestOutputStruct (
3411 ["ln_f"; "/a"; "/b"];
3412 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3413 "create a hard link",
3415 This command creates a hard link using the C<ln -f> command.
3416 The C<-f> option removes the link (C<linkname>) if it exists already.");
3418 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3419 [InitBasicFS, Always, TestOutputStruct (
3421 ["ln_s"; "a"; "/b"];
3422 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3423 "create a symbolic link",
3425 This command creates a symbolic link using the C<ln -s> command.");
3427 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3428 [InitBasicFS, Always, TestOutput (
3429 [["mkdir_p"; "/a/b"];
3430 ["touch"; "/a/b/c"];
3431 ["ln_sf"; "../d"; "/a/b/c"];
3432 ["readlink"; "/a/b/c"]], "../d")],
3433 "create a symbolic link",
3435 This command creates a symbolic link using the C<ln -sf> command,
3436 The C<-f> option removes the link (C<linkname>) if it exists already.");
3438 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3439 [] (* XXX tested above *),
3440 "read the target of a symbolic link",
3442 This command reads the target of a symbolic link.");
3444 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3445 [InitBasicFS, Always, TestOutputStruct (
3446 [["fallocate"; "/a"; "1000000"];
3447 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3448 "preallocate a file in the guest filesystem",
3450 This command preallocates a file (containing zero bytes) named
3451 C<path> of size C<len> bytes. If the file exists already, it
3454 Do not confuse this with the guestfish-specific
3455 C<alloc> command which allocates a file in the host and
3456 attaches it as a device.");
3458 ("swapon_device", (RErr, [Device "device"]), 170, [],
3459 [InitPartition, Always, TestRun (
3460 [["mkswap"; "/dev/sda1"];
3461 ["swapon_device"; "/dev/sda1"];
3462 ["swapoff_device"; "/dev/sda1"]])],
3463 "enable swap on device",
3465 This command enables the libguestfs appliance to use the
3466 swap device or partition named C<device>. The increased
3467 memory is made available for all commands, for example
3468 those run using C<guestfs_command> or C<guestfs_sh>.
3470 Note that you should not swap to existing guest swap
3471 partitions unless you know what you are doing. They may
3472 contain hibernation information, or other information that
3473 the guest doesn't want you to trash. You also risk leaking
3474 information about the host to the guest this way. Instead,
3475 attach a new host device to the guest and swap on that.");
3477 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3478 [], (* XXX tested by swapon_device *)
3479 "disable swap on device",
3481 This command disables the libguestfs appliance swap
3482 device or partition named C<device>.
3483 See C<guestfs_swapon_device>.");
3485 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3486 [InitBasicFS, Always, TestRun (
3487 [["fallocate"; "/swap"; "8388608"];
3488 ["mkswap_file"; "/swap"];
3489 ["swapon_file"; "/swap"];
3490 ["swapoff_file"; "/swap"]])],
3491 "enable swap on file",
3493 This command enables swap to a file.
3494 See C<guestfs_swapon_device> for other notes.");
3496 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3497 [], (* XXX tested by swapon_file *)
3498 "disable swap on file",
3500 This command disables the libguestfs appliance swap on file.");
3502 ("swapon_label", (RErr, [String "label"]), 174, [],
3503 [InitEmpty, Always, TestRun (
3504 [["part_disk"; "/dev/sdb"; "mbr"];
3505 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3506 ["swapon_label"; "swapit"];
3507 ["swapoff_label"; "swapit"];
3508 ["zero"; "/dev/sdb"];
3509 ["blockdev_rereadpt"; "/dev/sdb"]])],
3510 "enable swap on labeled swap partition",
3512 This command enables swap to a labeled swap partition.
3513 See C<guestfs_swapon_device> for other notes.");
3515 ("swapoff_label", (RErr, [String "label"]), 175, [],
3516 [], (* XXX tested by swapon_label *)
3517 "disable swap on labeled swap partition",
3519 This command disables the libguestfs appliance swap on
3520 labeled swap partition.");
3522 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3523 (let uuid = uuidgen () in
3524 [InitEmpty, Always, TestRun (
3525 [["mkswap_U"; uuid; "/dev/sdb"];
3526 ["swapon_uuid"; uuid];
3527 ["swapoff_uuid"; uuid]])]),
3528 "enable swap on swap partition by UUID",
3530 This command enables swap to a swap partition with the given UUID.
3531 See C<guestfs_swapon_device> for other notes.");
3533 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3534 [], (* XXX tested by swapon_uuid *)
3535 "disable swap on swap partition by UUID",
3537 This command disables the libguestfs appliance swap partition
3538 with the given UUID.");
3540 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3541 [InitBasicFS, Always, TestRun (
3542 [["fallocate"; "/swap"; "8388608"];
3543 ["mkswap_file"; "/swap"]])],
3544 "create a swap file",
3548 This command just writes a swap file signature to an existing
3549 file. To create the file itself, use something like C<guestfs_fallocate>.");
3551 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3552 [InitISOFS, Always, TestRun (
3553 [["inotify_init"; "0"]])],
3554 "create an inotify handle",
3556 This command creates a new inotify handle.
3557 The inotify subsystem can be used to notify events which happen to
3558 objects in the guest filesystem.
3560 C<maxevents> is the maximum number of events which will be
3561 queued up between calls to C<guestfs_inotify_read> or
3562 C<guestfs_inotify_files>.
3563 If this is passed as C<0>, then the kernel (or previously set)
3564 default is used. For Linux 2.6.29 the default was 16384 events.
3565 Beyond this limit, the kernel throws away events, but records
3566 the fact that it threw them away by setting a flag
3567 C<IN_Q_OVERFLOW> in the returned structure list (see
3568 C<guestfs_inotify_read>).
3570 Before any events are generated, you have to add some
3571 watches to the internal watch list. See:
3572 C<guestfs_inotify_add_watch>,
3573 C<guestfs_inotify_rm_watch> and
3574 C<guestfs_inotify_watch_all>.
3576 Queued up events should be read periodically by calling
3577 C<guestfs_inotify_read>
3578 (or C<guestfs_inotify_files> which is just a helpful
3579 wrapper around C<guestfs_inotify_read>). If you don't
3580 read the events out often enough then you risk the internal
3583 The handle should be closed after use by calling
3584 C<guestfs_inotify_close>. This also removes any
3585 watches automatically.
3587 See also L<inotify(7)> for an overview of the inotify interface
3588 as exposed by the Linux kernel, which is roughly what we expose
3589 via libguestfs. Note that there is one global inotify handle
3590 per libguestfs instance.");
3592 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3593 [InitBasicFS, Always, TestOutputList (
3594 [["inotify_init"; "0"];
3595 ["inotify_add_watch"; "/"; "1073741823"];
3598 ["inotify_files"]], ["a"; "b"])],
3599 "add an inotify watch",
3601 Watch C<path> for the events listed in C<mask>.
3603 Note that if C<path> is a directory then events within that
3604 directory are watched, but this does I<not> happen recursively
3605 (in subdirectories).
3607 Note for non-C or non-Linux callers: the inotify events are
3608 defined by the Linux kernel ABI and are listed in
3609 C</usr/include/sys/inotify.h>.");
3611 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3613 "remove an inotify watch",
3615 Remove a previously defined inotify watch.
3616 See C<guestfs_inotify_add_watch>.");
3618 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3620 "return list of inotify events",
3622 Return the complete queue of events that have happened
3623 since the previous read call.
3625 If no events have happened, this returns an empty list.
3627 I<Note>: In order to make sure that all events have been
3628 read, you must call this function repeatedly until it
3629 returns an empty list. The reason is that the call will
3630 read events up to the maximum appliance-to-host message
3631 size and leave remaining events in the queue.");
3633 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3635 "return list of watched files that had events",
3637 This function is a helpful wrapper around C<guestfs_inotify_read>
3638 which just returns a list of pathnames of objects that were
3639 touched. The returned pathnames are sorted and deduplicated.");
3641 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3643 "close the inotify handle",
3645 This closes the inotify handle which was previously
3646 opened by inotify_init. It removes all watches, throws
3647 away any pending events, and deallocates all resources.");
3649 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3651 "set SELinux security context",
3653 This sets the SELinux security context of the daemon
3654 to the string C<context>.
3656 See the documentation about SELINUX in L<guestfs(3)>.");
3658 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3660 "get SELinux security context",
3662 This gets the SELinux security context of the daemon.
3664 See the documentation about SELINUX in L<guestfs(3)>,
3665 and C<guestfs_setcon>");
3667 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3668 [InitEmpty, Always, TestOutput (
3669 [["part_disk"; "/dev/sda"; "mbr"];
3670 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3671 ["mount_options"; ""; "/dev/sda1"; "/"];
3672 ["write_file"; "/new"; "new file contents"; "0"];
3673 ["cat"; "/new"]], "new file contents")],
3674 "make a filesystem with block size",
3676 This call is similar to C<guestfs_mkfs>, but it allows you to
3677 control the block size of the resulting filesystem. Supported
3678 block sizes depend on the filesystem type, but typically they
3679 are C<1024>, C<2048> or C<4096> only.");
3681 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3682 [InitEmpty, Always, TestOutput (
3683 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3684 ["mke2journal"; "4096"; "/dev/sda1"];
3685 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3686 ["mount_options"; ""; "/dev/sda2"; "/"];
3687 ["write_file"; "/new"; "new file contents"; "0"];
3688 ["cat"; "/new"]], "new file contents")],
3689 "make ext2/3/4 external journal",
3691 This creates an ext2 external journal on C<device>. It is equivalent
3694 mke2fs -O journal_dev -b blocksize device");
3696 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3697 [InitEmpty, Always, TestOutput (
3698 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3699 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3700 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3701 ["mount_options"; ""; "/dev/sda2"; "/"];
3702 ["write_file"; "/new"; "new file contents"; "0"];
3703 ["cat"; "/new"]], "new file contents")],
3704 "make ext2/3/4 external journal with label",
3706 This creates an ext2 external journal on C<device> with label C<label>.");
3708 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3709 (let uuid = uuidgen () in
3710 [InitEmpty, Always, TestOutput (
3711 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3712 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3713 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3714 ["mount_options"; ""; "/dev/sda2"; "/"];
3715 ["write_file"; "/new"; "new file contents"; "0"];
3716 ["cat"; "/new"]], "new file contents")]),
3717 "make ext2/3/4 external journal with UUID",
3719 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3721 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3723 "make ext2/3/4 filesystem with external journal",
3725 This creates an ext2/3/4 filesystem on C<device> with
3726 an external journal on C<journal>. It is equivalent
3729 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3731 See also C<guestfs_mke2journal>.");
3733 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3735 "make ext2/3/4 filesystem with external journal",
3737 This creates an ext2/3/4 filesystem on C<device> with
3738 an external journal on the journal labeled C<label>.
3740 See also C<guestfs_mke2journal_L>.");
3742 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3744 "make ext2/3/4 filesystem with external journal",
3746 This creates an ext2/3/4 filesystem on C<device> with
3747 an external journal on the journal with UUID C<uuid>.
3749 See also C<guestfs_mke2journal_U>.");
3751 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3752 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3753 "load a kernel module",
3755 This loads a kernel module in the appliance.
3757 The kernel module must have been whitelisted when libguestfs
3758 was built (see C<appliance/kmod.whitelist.in> in the source).");
3760 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3761 [InitNone, Always, TestOutput (
3762 [["echo_daemon"; "This is a test"]], "This is a test"
3764 "echo arguments back to the client",
3766 This command concatenate the list of C<words> passed with single spaces between
3767 them and returns the resulting string.
3769 You can use this command to test the connection through to the daemon.
3771 See also C<guestfs_ping_daemon>.");
3773 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3774 [], (* There is a regression test for this. *)
3775 "find all files and directories, returning NUL-separated list",
3777 This command lists out all files and directories, recursively,
3778 starting at C<directory>, placing the resulting list in the
3779 external file called C<files>.
3781 This command works the same way as C<guestfs_find> with the
3782 following exceptions:
3788 The resulting list is written to an external file.
3792 Items (filenames) in the result are separated
3793 by C<\\0> characters. See L<find(1)> option I<-print0>.
3797 This command is not limited in the number of names that it
3802 The result list is not sorted.
3806 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3807 [InitISOFS, Always, TestOutput (
3808 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3809 InitISOFS, Always, TestOutput (
3810 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3811 InitISOFS, Always, TestOutput (
3812 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3813 InitISOFS, Always, TestLastFail (
3814 [["case_sensitive_path"; "/Known-1/"]]);
3815 InitBasicFS, Always, TestOutput (
3817 ["mkdir"; "/a/bbb"];
3818 ["touch"; "/a/bbb/c"];
3819 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3820 InitBasicFS, Always, TestOutput (
3822 ["mkdir"; "/a/bbb"];
3823 ["touch"; "/a/bbb/c"];
3824 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3825 InitBasicFS, Always, TestLastFail (
3827 ["mkdir"; "/a/bbb"];
3828 ["touch"; "/a/bbb/c"];
3829 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3830 "return true path on case-insensitive filesystem",
3832 This can be used to resolve case insensitive paths on
3833 a filesystem which is case sensitive. The use case is
3834 to resolve paths which you have read from Windows configuration
3835 files or the Windows Registry, to the true path.
3837 The command handles a peculiarity of the Linux ntfs-3g
3838 filesystem driver (and probably others), which is that although
3839 the underlying filesystem is case-insensitive, the driver
3840 exports the filesystem to Linux as case-sensitive.
3842 One consequence of this is that special directories such
3843 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3844 (or other things) depending on the precise details of how
3845 they were created. In Windows itself this would not be
3848 Bug or feature? You decide:
3849 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3851 This function resolves the true case of each element in the
3852 path and returns the case-sensitive path.
3854 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3855 might return C<\"/WINDOWS/system32\"> (the exact return value
3856 would depend on details of how the directories were originally
3857 created under Windows).
3860 This function does not handle drive names, backslashes etc.
3862 See also C<guestfs_realpath>.");
3864 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3865 [InitBasicFS, Always, TestOutput (
3866 [["vfs_type"; "/dev/sda1"]], "ext2")],
3867 "get the Linux VFS type corresponding to a mounted device",
3869 This command gets the block device type corresponding to
3870 a mounted device called C<device>.
3872 Usually the result is the name of the Linux VFS module that
3873 is used to mount this device (probably determined automatically
3874 if you used the C<guestfs_mount> call).");
3876 ("truncate", (RErr, [Pathname "path"]), 199, [],
3877 [InitBasicFS, Always, TestOutputStruct (
3878 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3879 ["truncate"; "/test"];
3880 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3881 "truncate a file to zero size",
3883 This command truncates C<path> to a zero-length file. The
3884 file must exist already.");
3886 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3887 [InitBasicFS, Always, TestOutputStruct (
3888 [["touch"; "/test"];
3889 ["truncate_size"; "/test"; "1000"];
3890 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3891 "truncate a file to a particular size",
3893 This command truncates C<path> to size C<size> bytes. The file
3894 must exist already. If the file is smaller than C<size> then
3895 the file is extended to the required size with null bytes.");
3897 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3898 [InitBasicFS, Always, TestOutputStruct (
3899 [["touch"; "/test"];
3900 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3901 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3902 "set timestamp of a file with nanosecond precision",
3904 This command sets the timestamps of a file with nanosecond
3907 C<atsecs, atnsecs> are the last access time (atime) in secs and
3908 nanoseconds from the epoch.
3910 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3911 secs and nanoseconds from the epoch.
3913 If the C<*nsecs> field contains the special value C<-1> then
3914 the corresponding timestamp is set to the current time. (The
3915 C<*secs> field is ignored in this case).
3917 If the C<*nsecs> field contains the special value C<-2> then
3918 the corresponding timestamp is left unchanged. (The
3919 C<*secs> field is ignored in this case).");
3921 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3922 [InitBasicFS, Always, TestOutputStruct (
3923 [["mkdir_mode"; "/test"; "0o111"];
3924 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3925 "create a directory with a particular mode",
3927 This command creates a directory, setting the initial permissions
3928 of the directory to C<mode>.
3930 For common Linux filesystems, the actual mode which is set will
3931 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3932 interpret the mode in other ways.
3934 See also C<guestfs_mkdir>, C<guestfs_umask>");
3936 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3938 "change file owner and group",
3940 Change the file owner to C<owner> and group to C<group>.
3941 This is like C<guestfs_chown> but if C<path> is a symlink then
3942 the link itself is changed, not the target.
3944 Only numeric uid and gid are supported. If you want to use
3945 names, you will need to locate and parse the password file
3946 yourself (Augeas support makes this relatively easy).");
3948 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3950 "lstat on multiple files",
3952 This call allows you to perform the C<guestfs_lstat> operation
3953 on multiple files, where all files are in the directory C<path>.
3954 C<names> is the list of files from this directory.
3956 On return you get a list of stat structs, with a one-to-one
3957 correspondence to the C<names> list. If any name did not exist
3958 or could not be lstat'd, then the C<ino> field of that structure
3961 This call is intended for programs that want to efficiently
3962 list a directory contents without making many round-trips.
3963 See also C<guestfs_lxattrlist> for a similarly efficient call
3964 for getting extended attributes. Very long directory listings
3965 might cause the protocol message size to be exceeded, causing
3966 this call to fail. The caller must split up such requests
3967 into smaller groups of names.");
3969 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3971 "lgetxattr on multiple files",
3973 This call allows you to get the extended attributes
3974 of multiple files, where all files are in the directory C<path>.
3975 C<names> is the list of files from this directory.
3977 On return you get a flat list of xattr structs which must be
3978 interpreted sequentially. The first xattr struct always has a zero-length
3979 C<attrname>. C<attrval> in this struct is zero-length
3980 to indicate there was an error doing C<lgetxattr> for this
3981 file, I<or> is a C string which is a decimal number
3982 (the number of following attributes for this file, which could
3983 be C<\"0\">). Then after the first xattr struct are the
3984 zero or more attributes for the first named file.
3985 This repeats for the second and subsequent files.
3987 This call is intended for programs that want to efficiently
3988 list a directory contents without making many round-trips.
3989 See also C<guestfs_lstatlist> for a similarly efficient call
3990 for getting standard stats. Very long directory listings
3991 might cause the protocol message size to be exceeded, causing
3992 this call to fail. The caller must split up such requests
3993 into smaller groups of names.");
3995 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3997 "readlink on multiple files",
3999 This call allows you to do a C<readlink> operation
4000 on multiple files, where all files are in the directory C<path>.
4001 C<names> is the list of files from this directory.
4003 On return you get a list of strings, with a one-to-one
4004 correspondence to the C<names> list. Each string is the
4005 value of the symbol link.
4007 If the C<readlink(2)> operation fails on any name, then
4008 the corresponding result string is the empty string C<\"\">.
4009 However the whole operation is completed even if there
4010 were C<readlink(2)> errors, and so you can call this
4011 function with names where you don't know if they are
4012 symbolic links already (albeit slightly less efficient).
4014 This call is intended for programs that want to efficiently
4015 list a directory contents without making many round-trips.
4016 Very long directory listings might cause the protocol
4017 message size to be exceeded, causing
4018 this call to fail. The caller must split up such requests
4019 into smaller groups of names.");
4021 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4022 [InitISOFS, Always, TestOutputBuffer (
4023 [["pread"; "/known-4"; "1"; "3"]], "\n");
4024 InitISOFS, Always, TestOutputBuffer (
4025 [["pread"; "/empty"; "0"; "100"]], "")],
4026 "read part of a file",
4028 This command lets you read part of a file. It reads C<count>
4029 bytes of the file, starting at C<offset>, from file C<path>.
4031 This may read fewer bytes than requested. For further details
4032 see the L<pread(2)> system call.");
4034 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4035 [InitEmpty, Always, TestRun (
4036 [["part_init"; "/dev/sda"; "gpt"]])],
4037 "create an empty partition table",
4039 This creates an empty partition table on C<device> of one of the
4040 partition types listed below. Usually C<parttype> should be
4041 either C<msdos> or C<gpt> (for large disks).
4043 Initially there are no partitions. Following this, you should
4044 call C<guestfs_part_add> for each partition required.
4046 Possible values for C<parttype> are:
4050 =item B<efi> | B<gpt>
4052 Intel EFI / GPT partition table.
4054 This is recommended for >= 2 TB partitions that will be accessed
4055 from Linux and Intel-based Mac OS X. It also has limited backwards
4056 compatibility with the C<mbr> format.
4058 =item B<mbr> | B<msdos>
4060 The standard PC \"Master Boot Record\" (MBR) format used
4061 by MS-DOS and Windows. This partition type will B<only> work
4062 for device sizes up to 2 TB. For large disks we recommend
4067 Other partition table types that may work but are not
4076 =item B<amiga> | B<rdb>
4078 Amiga \"Rigid Disk Block\" format.
4086 DASD, used on IBM mainframes.
4094 Old Mac partition format. Modern Macs use C<gpt>.
4098 NEC PC-98 format, common in Japan apparently.
4106 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4107 [InitEmpty, Always, TestRun (
4108 [["part_init"; "/dev/sda"; "mbr"];
4109 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4110 InitEmpty, Always, TestRun (
4111 [["part_init"; "/dev/sda"; "gpt"];
4112 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4113 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4114 InitEmpty, Always, TestRun (
4115 [["part_init"; "/dev/sda"; "mbr"];
4116 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4117 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4118 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4119 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4120 "add a partition to the device",
4122 This command adds a partition to C<device>. If there is no partition
4123 table on the device, call C<guestfs_part_init> first.
4125 The C<prlogex> parameter is the type of partition. Normally you
4126 should pass C<p> or C<primary> here, but MBR partition tables also
4127 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4130 C<startsect> and C<endsect> are the start and end of the partition
4131 in I<sectors>. C<endsect> may be negative, which means it counts
4132 backwards from the end of the disk (C<-1> is the last sector).
4134 Creating a partition which covers the whole disk is not so easy.
4135 Use C<guestfs_part_disk> to do that.");
4137 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4138 [InitEmpty, Always, TestRun (
4139 [["part_disk"; "/dev/sda"; "mbr"]]);
4140 InitEmpty, Always, TestRun (
4141 [["part_disk"; "/dev/sda"; "gpt"]])],
4142 "partition whole disk with a single primary partition",
4144 This command is simply a combination of C<guestfs_part_init>
4145 followed by C<guestfs_part_add> to create a single primary partition
4146 covering the whole disk.
4148 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4149 but other possible values are described in C<guestfs_part_init>.");
4151 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4152 [InitEmpty, Always, TestRun (
4153 [["part_disk"; "/dev/sda"; "mbr"];
4154 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4155 "make a partition bootable",
4157 This sets the bootable flag on partition numbered C<partnum> on
4158 device C<device>. Note that partitions are numbered from 1.
4160 The bootable flag is used by some operating systems (notably
4161 Windows) to determine which partition to boot from. It is by
4162 no means universally recognized.");
4164 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4165 [InitEmpty, Always, TestRun (
4166 [["part_disk"; "/dev/sda"; "gpt"];
4167 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4168 "set partition name",
4170 This sets the partition name on partition numbered C<partnum> on
4171 device C<device>. Note that partitions are numbered from 1.
4173 The partition name can only be set on certain types of partition
4174 table. This works on C<gpt> but not on C<mbr> partitions.");
4176 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4177 [], (* XXX Add a regression test for this. *)
4178 "list partitions on a device",
4180 This command parses the partition table on C<device> and
4181 returns the list of partitions found.
4183 The fields in the returned structure are:
4189 Partition number, counting from 1.
4193 Start of the partition I<in bytes>. To get sectors you have to
4194 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4198 End of the partition in bytes.
4202 Size of the partition in bytes.
4206 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4207 [InitEmpty, Always, TestOutput (
4208 [["part_disk"; "/dev/sda"; "gpt"];
4209 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4210 "get the partition table type",
4212 This command examines the partition table on C<device> and
4213 returns the partition table type (format) being used.
4215 Common return values include: C<msdos> (a DOS/Windows style MBR
4216 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4217 values are possible, although unusual. See C<guestfs_part_init>
4220 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4221 [InitBasicFS, Always, TestOutputBuffer (
4222 [["fill"; "0x63"; "10"; "/test"];
4223 ["read_file"; "/test"]], "cccccccccc")],
4224 "fill a file with octets",
4226 This command creates a new file called C<path>. The initial
4227 content of the file is C<len> octets of C<c>, where C<c>
4228 must be a number in the range C<[0..255]>.
4230 To fill a file with zero bytes (sparsely), it is
4231 much more efficient to use C<guestfs_truncate_size>.");
4233 ("available", (RErr, [StringList "groups"]), 216, [],
4234 [InitNone, Always, TestRun [["available"; ""]]],
4235 "test availability of some parts of the API",
4237 This command is used to check the availability of some
4238 groups of functionality in the appliance, which not all builds of
4239 the libguestfs appliance will be able to provide.
4241 The libguestfs groups, and the functions that those
4242 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4244 The argument C<groups> is a list of group names, eg:
4245 C<[\"inotify\", \"augeas\"]> would check for the availability of
4246 the Linux inotify functions and Augeas (configuration file
4249 The command returns no error if I<all> requested groups are available.
4251 It fails with an error if one or more of the requested
4252 groups is unavailable in the appliance.
4254 If an unknown group name is included in the
4255 list of groups then an error is always returned.
4263 You must call C<guestfs_launch> before calling this function.
4265 The reason is because we don't know what groups are
4266 supported by the appliance/daemon until it is running and can
4271 If a group of functions is available, this does not necessarily
4272 mean that they will work. You still have to check for errors
4273 when calling individual API functions even if they are
4278 It is usually the job of distro packagers to build
4279 complete functionality into the libguestfs appliance.
4280 Upstream libguestfs, if built from source with all
4281 requirements satisfied, will support everything.
4285 This call was added in version C<1.0.80>. In previous
4286 versions of libguestfs all you could do would be to speculatively
4287 execute a command to find out if the daemon implemented it.
4288 See also C<guestfs_version>.
4292 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4293 [InitBasicFS, Always, TestOutputBuffer (
4294 [["write_file"; "/src"; "hello, world"; "0"];
4295 ["dd"; "/src"; "/dest"];
4296 ["read_file"; "/dest"]], "hello, world")],
4297 "copy from source to destination using dd",
4299 This command copies from one source device or file C<src>
4300 to another destination device or file C<dest>. Normally you
4301 would use this to copy to or from a device or partition, for
4302 example to duplicate a filesystem.
4304 If the destination is a device, it must be as large or larger
4305 than the source file or device, otherwise the copy will fail.
4306 This command cannot do partial copies (see C<guestfs_copy_size>).");
4308 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4309 [InitBasicFS, Always, TestOutputInt (
4310 [["write_file"; "/file"; "hello, world"; "0"];
4311 ["filesize"; "/file"]], 12)],
4312 "return the size of the file in bytes",
4314 This command returns the size of C<file> in bytes.
4316 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4317 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4318 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4320 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4321 [InitBasicFSonLVM, Always, TestOutputList (
4322 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4323 ["lvs"]], ["/dev/VG/LV2"])],
4324 "rename an LVM logical volume",
4326 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4328 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4329 [InitBasicFSonLVM, Always, TestOutputList (
4331 ["vg_activate"; "false"; "VG"];
4332 ["vgrename"; "VG"; "VG2"];
4333 ["vg_activate"; "true"; "VG2"];
4334 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4335 ["vgs"]], ["VG2"])],
4336 "rename an LVM volume group",
4338 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4340 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4341 [InitISOFS, Always, TestOutputBuffer (
4342 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4343 "list the contents of a single file in an initrd",
4345 This command unpacks the file C<filename> from the initrd file
4346 called C<initrdpath>. The filename must be given I<without> the
4347 initial C</> character.
4349 For example, in guestfish you could use the following command
4350 to examine the boot script (usually called C</init>)
4351 contained in a Linux initrd or initramfs image:
4353 initrd-cat /boot/initrd-<version>.img init
4355 See also C<guestfs_initrd_list>.");
4357 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4359 "get the UUID of a physical volume",
4361 This command returns the UUID of the LVM PV C<device>.");
4363 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4365 "get the UUID of a volume group",
4367 This command returns the UUID of the LVM VG named C<vgname>.");
4369 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4371 "get the UUID of a logical volume",
4373 This command returns the UUID of the LVM LV C<device>.");
4375 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4377 "get the PV UUIDs containing the volume group",
4379 Given a VG called C<vgname>, this returns the UUIDs of all
4380 the physical volumes that this volume group resides on.
4382 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4383 calls to associate physical volumes and volume groups.
4385 See also C<guestfs_vglvuuids>.");
4387 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4389 "get the LV UUIDs of all LVs in the volume group",
4391 Given a VG called C<vgname>, this returns the UUIDs of all
4392 the logical volumes created in this volume group.
4394 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4395 calls to associate logical volumes and volume groups.
4397 See also C<guestfs_vgpvuuids>.");
4399 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4400 [InitBasicFS, Always, TestOutputBuffer (
4401 [["write_file"; "/src"; "hello, world"; "0"];
4402 ["copy_size"; "/src"; "/dest"; "5"];
4403 ["read_file"; "/dest"]], "hello")],
4404 "copy size bytes from source to destination using dd",
4406 This command copies exactly C<size> bytes from one source device
4407 or file C<src> to another destination device or file C<dest>.
4409 Note this will fail if the source is too short or if the destination
4410 is not large enough.");
4412 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4413 [InitBasicFSonLVM, Always, TestRun (
4414 [["zero_device"; "/dev/VG/LV"]])],
4415 "write zeroes to an entire device",
4417 This command writes zeroes over the entire C<device>. Compare
4418 with C<guestfs_zero> which just zeroes the first few blocks of
4421 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4422 [InitBasicFS, Always, TestOutput (
4423 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4424 ["cat"; "/hello"]], "hello\n")],
4425 "unpack compressed tarball to directory",
4427 This command uploads and unpacks local file C<tarball> (an
4428 I<xz compressed> tar file) into C<directory>.");
4430 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4432 "pack directory into compressed tarball",
4434 This command packs the contents of C<directory> and downloads
4435 it to local file C<tarball> (as an xz compressed tar archive).");
4437 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4439 "resize an NTFS filesystem",
4441 This command resizes an NTFS filesystem, expanding or
4442 shrinking it to the size of the underlying device.
4443 See also L<ntfsresize(8)>.");
4445 ("vgscan", (RErr, []), 232, [],
4446 [InitEmpty, Always, TestRun (
4448 "rescan for LVM physical volumes, volume groups and logical volumes",
4450 This rescans all block devices and rebuilds the list of LVM
4451 physical volumes, volume groups and logical volumes.");
4453 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4454 [InitEmpty, Always, TestRun (
4455 [["part_init"; "/dev/sda"; "mbr"];
4456 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4457 ["part_del"; "/dev/sda"; "1"]])],
4458 "delete a partition",
4460 This command deletes the partition numbered C<partnum> on C<device>.
4462 Note that in the case of MBR partitioning, deleting an
4463 extended partition also deletes any logical partitions
4466 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4467 [InitEmpty, Always, TestOutputTrue (
4468 [["part_init"; "/dev/sda"; "mbr"];
4469 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4470 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4471 ["part_get_bootable"; "/dev/sda"; "1"]])],
4472 "return true if a partition is bootable",
4474 This command returns true if the partition C<partnum> on
4475 C<device> has the bootable flag set.
4477 See also C<guestfs_part_set_bootable>.");
4479 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4480 [InitEmpty, Always, TestOutputInt (
4481 [["part_init"; "/dev/sda"; "mbr"];
4482 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4483 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4484 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4485 "get the MBR type byte (ID byte) from a partition",
4487 Returns the MBR type byte (also known as the ID byte) from
4488 the numbered partition C<partnum>.
4490 Note that only MBR (old DOS-style) partitions have type bytes.
4491 You will get undefined results for other partition table
4492 types (see C<guestfs_part_get_parttype>).");
4494 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4495 [], (* tested by part_get_mbr_id *)
4496 "set the MBR type byte (ID byte) of a partition",
4498 Sets the MBR type byte (also known as the ID byte) of
4499 the numbered partition C<partnum> to C<idbyte>. Note
4500 that the type bytes quoted in most documentation are
4501 in fact hexadecimal numbers, but usually documented
4502 without any leading \"0x\" which might be confusing.
4504 Note that only MBR (old DOS-style) partitions have type bytes.
4505 You will get undefined results for other partition table
4506 types (see C<guestfs_part_get_parttype>).");
4508 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4509 [InitISOFS, Always, TestOutput (
4510 [["checksum_device"; "md5"; "/dev/sdd"]],
4511 (Digest.to_hex (Digest.file "images/test.iso")))],
4512 "compute MD5, SHAx or CRC checksum of the contents of a device",
4514 This call computes the MD5, SHAx or CRC checksum of the
4515 contents of the device named C<device>. For the types of
4516 checksums supported see the C<guestfs_checksum> command.");
4518 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4519 [InitNone, Always, TestRun (
4520 [["part_disk"; "/dev/sda"; "mbr"];
4521 ["pvcreate"; "/dev/sda1"];
4522 ["vgcreate"; "VG"; "/dev/sda1"];
4523 ["lvcreate"; "LV"; "VG"; "10"];
4524 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4525 "expand an LV to fill free space",
4527 This expands an existing logical volume C<lv> so that it fills
4528 C<pc>% of the remaining free space in the volume group. Commonly
4529 you would call this with pc = 100 which expands the logical volume
4530 as much as possible, using all remaining free space in the volume
4533 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4534 [], (* XXX Augeas code needs tests. *)
4535 "clear Augeas path",
4537 Set the value associated with C<path> to C<NULL>. This
4538 is the same as the L<augtool(1)> C<clear> command.");
4540 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4541 [InitEmpty, Always, TestOutputInt (
4542 [["get_umask"]], 0o22)],
4543 "get the current umask",
4545 Return the current umask. By default the umask is C<022>
4546 unless it has been set by calling C<guestfs_umask>.");
4548 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4550 "upload a file to the appliance (internal use only)",
4552 The C<guestfs_debug_upload> command uploads a file to
4553 the libguestfs appliance.
4555 There is no comprehensive help for this command. You have
4556 to look at the file C<daemon/debug.c> in the libguestfs source
4557 to find out what it is for.");
4559 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4560 [InitBasicFS, Always, TestOutput (
4561 [["base64_in"; "../images/hello.b64"; "/hello"];
4562 ["cat"; "/hello"]], "hello\n")],
4563 "upload base64-encoded data to file",
4565 This command uploads base64-encoded data from C<base64file>
4568 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4570 "download file and encode as base64",
4572 This command downloads the contents of C<filename>, writing
4573 it out to local file C<base64file> encoded as base64.");
4575 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4577 "compute MD5, SHAx or CRC checksum of files in a directory",
4579 This command computes the checksums of all regular files in
4580 C<directory> and then emits a list of those checksums to
4581 the local output file C<sumsfile>.
4583 This can be used for verifying the integrity of a virtual
4584 machine. However to be properly secure you should pay
4585 attention to the output of the checksum command (it uses
4586 the ones from GNU coreutils). In particular when the
4587 filename is not printable, coreutils uses a special
4588 backslash syntax. For more information, see the GNU
4589 coreutils info file.");
4593 let all_functions = non_daemon_functions @ daemon_functions
4595 (* In some places we want the functions to be displayed sorted
4596 * alphabetically, so this is useful:
4598 let all_functions_sorted =
4599 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4600 compare n1 n2) all_functions
4602 (* Field types for structures. *)
4604 | FChar (* C 'char' (really, a 7 bit byte). *)
4605 | FString (* nul-terminated ASCII string, NOT NULL. *)
4606 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4611 | FBytes (* Any int measure that counts bytes. *)
4612 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4613 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4615 (* Because we generate extra parsing code for LVM command line tools,
4616 * we have to pull out the LVM columns separately here.
4626 "pv_attr", FString (* XXX *);
4627 "pv_pe_count", FInt64;
4628 "pv_pe_alloc_count", FInt64;
4631 "pv_mda_count", FInt64;
4632 "pv_mda_free", FBytes;
4633 (* Not in Fedora 10:
4634 "pv_mda_size", FBytes;
4641 "vg_attr", FString (* XXX *);
4644 "vg_sysid", FString;
4645 "vg_extent_size", FBytes;
4646 "vg_extent_count", FInt64;
4647 "vg_free_count", FInt64;
4652 "snap_count", FInt64;
4655 "vg_mda_count", FInt64;
4656 "vg_mda_free", FBytes;
4657 (* Not in Fedora 10:
4658 "vg_mda_size", FBytes;
4664 "lv_attr", FString (* XXX *);
4667 "lv_kernel_major", FInt64;
4668 "lv_kernel_minor", FInt64;
4670 "seg_count", FInt64;
4672 "snap_percent", FOptPercent;
4673 "copy_percent", FOptPercent;
4676 "mirror_log", FString;
4680 (* Names and fields in all structures (in RStruct and RStructList)
4684 (* The old RIntBool return type, only ever used for aug_defnode. Do
4685 * not use this struct in any new code.
4688 "i", FInt32; (* for historical compatibility *)
4689 "b", FInt32; (* for historical compatibility *)
4692 (* LVM PVs, VGs, LVs. *)
4693 "lvm_pv", lvm_pv_cols;
4694 "lvm_vg", lvm_vg_cols;
4695 "lvm_lv", lvm_lv_cols;
4697 (* Column names and types from stat structures.
4698 * NB. Can't use things like 'st_atime' because glibc header files
4699 * define some of these as macros. Ugh.
4730 (* Column names in dirent structure. *)
4733 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4738 (* Version numbers. *)
4746 (* Extended attribute. *)
4748 "attrname", FString;
4752 (* Inotify events. *)
4756 "in_cookie", FUInt32;
4760 (* Partition table entry. *)
4763 "part_start", FBytes;
4765 "part_size", FBytes;
4767 ] (* end of structs *)
4769 (* Ugh, Java has to be different ..
4770 * These names are also used by the Haskell bindings.
4772 let java_structs = [
4773 "int_bool", "IntBool";
4778 "statvfs", "StatVFS";
4780 "version", "Version";
4782 "inotify_event", "INotifyEvent";
4783 "partition", "Partition";
4786 (* What structs are actually returned. *)
4787 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4789 (* Returns a list of RStruct/RStructList structs that are returned
4790 * by any function. Each element of returned list is a pair:
4792 * (structname, RStructOnly)
4793 * == there exists function which returns RStruct (_, structname)
4794 * (structname, RStructListOnly)
4795 * == there exists function which returns RStructList (_, structname)
4796 * (structname, RStructAndList)
4797 * == there are functions returning both RStruct (_, structname)
4798 * and RStructList (_, structname)
4800 let rstructs_used_by functions =
4801 (* ||| is a "logical OR" for rstructs_used_t *)
4805 | _, RStructAndList -> RStructAndList
4806 | RStructOnly, RStructListOnly
4807 | RStructListOnly, RStructOnly -> RStructAndList
4808 | RStructOnly, RStructOnly -> RStructOnly
4809 | RStructListOnly, RStructListOnly -> RStructListOnly
4812 let h = Hashtbl.create 13 in
4814 (* if elem->oldv exists, update entry using ||| operator,
4815 * else just add elem->newv to the hash
4817 let update elem newv =
4818 try let oldv = Hashtbl.find h elem in
4819 Hashtbl.replace h elem (newv ||| oldv)
4820 with Not_found -> Hashtbl.add h elem newv
4824 fun (_, style, _, _, _, _, _) ->
4825 match fst style with
4826 | RStruct (_, structname) -> update structname RStructOnly
4827 | RStructList (_, structname) -> update structname RStructListOnly
4831 (* return key->values as a list of (key,value) *)
4832 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4834 (* Used for testing language bindings. *)
4836 | CallString of string
4837 | CallOptString of string option
4838 | CallStringList of string list
4840 | CallInt64 of int64
4843 (* Used to memoize the result of pod2text. *)
4844 let pod2text_memo_filename = "src/.pod2text.data"
4845 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4847 let chan = open_in pod2text_memo_filename in
4848 let v = input_value chan in
4852 _ -> Hashtbl.create 13
4853 let pod2text_memo_updated () =
4854 let chan = open_out pod2text_memo_filename in
4855 output_value chan pod2text_memo;
4858 (* Useful functions.
4859 * Note we don't want to use any external OCaml libraries which
4860 * makes this a bit harder than it should be.
4862 module StringMap = Map.Make (String)
4864 let failwithf fs = ksprintf failwith fs
4866 let unique = let i = ref 0 in fun () -> incr i; !i
4868 let replace_char s c1 c2 =
4869 let s2 = String.copy s in
4870 let r = ref false in
4871 for i = 0 to String.length s2 - 1 do
4872 if String.unsafe_get s2 i = c1 then (
4873 String.unsafe_set s2 i c2;
4877 if not !r then s else s2
4881 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4883 let triml ?(test = isspace) str =
4885 let n = ref (String.length str) in
4886 while !n > 0 && test str.[!i]; do
4891 else String.sub str !i !n
4893 let trimr ?(test = isspace) str =
4894 let n = ref (String.length str) in
4895 while !n > 0 && test str.[!n-1]; do
4898 if !n = String.length str then str
4899 else String.sub str 0 !n
4901 let trim ?(test = isspace) str =
4902 trimr ~test (triml ~test str)
4904 let rec find s sub =
4905 let len = String.length s in
4906 let sublen = String.length sub in
4908 if i <= len-sublen then (
4910 if j < sublen then (
4911 if s.[i+j] = sub.[j] then loop2 (j+1)
4917 if r = -1 then loop (i+1) else r
4923 let rec replace_str s s1 s2 =
4924 let len = String.length s in
4925 let sublen = String.length s1 in
4926 let i = find s s1 in
4929 let s' = String.sub s 0 i in
4930 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4931 s' ^ s2 ^ replace_str s'' s1 s2
4934 let rec string_split sep str =
4935 let len = String.length str in
4936 let seplen = String.length sep in
4937 let i = find str sep in
4938 if i = -1 then [str]
4940 let s' = String.sub str 0 i in
4941 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4942 s' :: string_split sep s''
4945 let files_equal n1 n2 =
4946 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4947 match Sys.command cmd with
4950 | i -> failwithf "%s: failed with error code %d" cmd i
4952 let rec filter_map f = function
4956 | Some y -> y :: filter_map f xs
4957 | None -> filter_map f xs
4959 let rec find_map f = function
4960 | [] -> raise Not_found
4964 | None -> find_map f xs
4967 let rec loop i = function
4969 | x :: xs -> f i x; loop (i+1) xs
4974 let rec loop i = function
4976 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4980 let count_chars c str =
4981 let count = ref 0 in
4982 for i = 0 to String.length str - 1 do
4983 if c = String.unsafe_get str i then incr count
4987 let name_of_argt = function
4988 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4989 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4990 | FileIn n | FileOut n -> n
4992 let java_name_of_struct typ =
4993 try List.assoc typ java_structs
4996 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4998 let cols_of_struct typ =
4999 try List.assoc typ structs
5001 failwithf "cols_of_struct: unknown struct %s" typ
5003 let seq_of_test = function
5004 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5005 | TestOutputListOfDevices (s, _)
5006 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5007 | TestOutputTrue s | TestOutputFalse s
5008 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5009 | TestOutputStruct (s, _)
5010 | TestLastFail s -> s
5012 (* Handling for function flags. *)
5013 let protocol_limit_warning =
5014 "Because of the message protocol, there is a transfer limit
5015 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5017 let danger_will_robinson =
5018 "B<This command is dangerous. Without careful use you
5019 can easily destroy all your data>."
5021 let deprecation_notice flags =
5024 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5026 sprintf "This function is deprecated.
5027 In new code, use the C<%s> call instead.
5029 Deprecated functions will not be removed from the API, but the
5030 fact that they are deprecated indicates that there are problems
5031 with correct use of these functions." alt in
5036 (* Create list of optional groups. *)
5038 let h = Hashtbl.create 13 in
5040 fun (name, _, _, flags, _, _, _) ->
5044 let names = try Hashtbl.find h group with Not_found -> [] in
5045 Hashtbl.replace h group (name :: names)
5049 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5052 fun group -> group, List.sort compare (Hashtbl.find h group)
5054 List.sort (fun x y -> compare (fst x) (fst y)) groups
5056 (* Check function names etc. for consistency. *)
5057 let check_functions () =
5058 let contains_uppercase str =
5059 let len = String.length str in
5061 if i >= len then false
5064 if c >= 'A' && c <= 'Z' then true
5071 (* Check function names. *)
5073 fun (name, _, _, _, _, _, _) ->
5074 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5075 failwithf "function name %s does not need 'guestfs' prefix" name;
5077 failwithf "function name is empty";
5078 if name.[0] < 'a' || name.[0] > 'z' then
5079 failwithf "function name %s must start with lowercase a-z" name;
5080 if String.contains name '-' then
5081 failwithf "function name %s should not contain '-', use '_' instead."
5085 (* Check function parameter/return names. *)
5087 fun (name, style, _, _, _, _, _) ->
5088 let check_arg_ret_name n =
5089 if contains_uppercase n then
5090 failwithf "%s param/ret %s should not contain uppercase chars"
5092 if String.contains n '-' || String.contains n '_' then
5093 failwithf "%s param/ret %s should not contain '-' or '_'"
5096 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;
5097 if n = "int" || n = "char" || n = "short" || n = "long" then
5098 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5099 if n = "i" || n = "n" then
5100 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5101 if n = "argv" || n = "args" then
5102 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5104 (* List Haskell, OCaml and C keywords here.
5105 * http://www.haskell.org/haskellwiki/Keywords
5106 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5107 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5108 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5109 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5110 * Omitting _-containing words, since they're handled above.
5111 * Omitting the OCaml reserved word, "val", is ok,
5112 * and saves us from renaming several parameters.
5115 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5116 "char"; "class"; "const"; "constraint"; "continue"; "data";
5117 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5118 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5119 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5120 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5121 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5123 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5124 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5125 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5126 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5127 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5128 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5129 "volatile"; "when"; "where"; "while";
5131 if List.mem n reserved then
5132 failwithf "%s has param/ret using reserved word %s" name n;
5135 (match fst style with
5137 | RInt n | RInt64 n | RBool n
5138 | RConstString n | RConstOptString n | RString n
5139 | RStringList n | RStruct (n, _) | RStructList (n, _)
5140 | RHashtable n | RBufferOut n ->
5141 check_arg_ret_name n
5143 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5146 (* Check short descriptions. *)
5148 fun (name, _, _, _, _, shortdesc, _) ->
5149 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5150 failwithf "short description of %s should begin with lowercase." name;
5151 let c = shortdesc.[String.length shortdesc-1] in
5152 if c = '\n' || c = '.' then
5153 failwithf "short description of %s should not end with . or \\n." name
5156 (* Check long descriptions. *)
5158 fun (name, _, _, _, _, _, longdesc) ->
5159 if longdesc.[String.length longdesc-1] = '\n' then
5160 failwithf "long description of %s should not end with \\n." name
5163 (* Check proc_nrs. *)
5165 fun (name, _, proc_nr, _, _, _, _) ->
5166 if proc_nr <= 0 then
5167 failwithf "daemon function %s should have proc_nr > 0" name
5171 fun (name, _, proc_nr, _, _, _, _) ->
5172 if proc_nr <> -1 then
5173 failwithf "non-daemon function %s should have proc_nr -1" name
5174 ) non_daemon_functions;
5177 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5180 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5181 let rec loop = function
5184 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5186 | (name1,nr1) :: (name2,nr2) :: _ ->
5187 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5195 (* Ignore functions that have no tests. We generate a
5196 * warning when the user does 'make check' instead.
5198 | name, _, _, _, [], _, _ -> ()
5199 | name, _, _, _, tests, _, _ ->
5203 match seq_of_test test with
5205 failwithf "%s has a test containing an empty sequence" name
5206 | cmds -> List.map List.hd cmds
5208 let funcs = List.flatten funcs in
5210 let tested = List.mem name funcs in
5213 failwithf "function %s has tests but does not test itself" name
5216 (* 'pr' prints to the current output file. *)
5217 let chan = ref Pervasives.stdout
5222 let i = count_chars '\n' str in
5223 lines := !lines + i;
5224 output_string !chan str
5227 let copyright_years =
5228 let this_year = 1900 + (localtime (time ())).tm_year in
5229 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5231 (* Generate a header block in a number of standard styles. *)
5232 type comment_style =
5233 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5234 type license = GPLv2plus | LGPLv2plus
5236 let generate_header ?(extra_inputs = []) comment license =
5237 let inputs = "src/generator.ml" :: extra_inputs in
5238 let c = match comment with
5239 | CStyle -> pr "/* "; " *"
5240 | CPlusPlusStyle -> pr "// "; "//"
5241 | HashStyle -> pr "# "; "#"
5242 | OCamlStyle -> pr "(* "; " *"
5243 | HaskellStyle -> pr "{- "; " " in
5244 pr "libguestfs generated file\n";
5245 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5246 List.iter (pr "%s %s\n" c) inputs;
5247 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5249 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5253 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5254 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5255 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5256 pr "%s (at your option) any later version.\n" c;
5258 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5259 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5260 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5261 pr "%s GNU General Public License for more details.\n" c;
5263 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5264 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5265 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5268 pr "%s This library is free software; you can redistribute it and/or\n" c;
5269 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5270 pr "%s License as published by the Free Software Foundation; either\n" c;
5271 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5273 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5274 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5275 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5276 pr "%s Lesser General Public License for more details.\n" c;
5278 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5279 pr "%s License along with this library; if not, write to the Free Software\n" c;
5280 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5283 | CStyle -> pr " */\n"
5286 | OCamlStyle -> pr " *)\n"
5287 | HaskellStyle -> pr "-}\n"
5291 (* Start of main code generation functions below this line. *)
5293 (* Generate the pod documentation for the C API. *)
5294 let rec generate_actions_pod () =
5296 fun (shortname, style, _, flags, _, _, longdesc) ->
5297 if not (List.mem NotInDocs flags) then (
5298 let name = "guestfs_" ^ shortname in
5299 pr "=head2 %s\n\n" name;
5301 generate_prototype ~extern:false ~handle:"g" name style;
5303 pr "%s\n\n" longdesc;
5304 (match fst style with
5306 pr "This function returns 0 on success or -1 on error.\n\n"
5308 pr "On error this function returns -1.\n\n"
5310 pr "On error this function returns -1.\n\n"
5312 pr "This function returns a C truth value on success or -1 on error.\n\n"
5314 pr "This function returns a string, or NULL on error.
5315 The string is owned by the guest handle and must I<not> be freed.\n\n"
5316 | RConstOptString _ ->
5317 pr "This function returns a string which may be NULL.
5318 There is way to return an error from this function.
5319 The string is owned by the guest handle and must I<not> be freed.\n\n"
5321 pr "This function returns a string, or NULL on error.
5322 I<The caller must free the returned string after use>.\n\n"
5324 pr "This function returns a NULL-terminated array of strings
5325 (like L<environ(3)>), or NULL if there was an error.
5326 I<The caller must free the strings and the array after use>.\n\n"
5327 | RStruct (_, typ) ->
5328 pr "This function returns a C<struct guestfs_%s *>,
5329 or NULL if there was an error.
5330 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5331 | RStructList (_, typ) ->
5332 pr "This function returns a C<struct guestfs_%s_list *>
5333 (see E<lt>guestfs-structs.hE<gt>),
5334 or NULL if there was an error.
5335 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5337 pr "This function returns a NULL-terminated array of
5338 strings, or NULL if there was an error.
5339 The array of strings will always have length C<2n+1>, where
5340 C<n> keys and values alternate, followed by the trailing NULL entry.
5341 I<The caller must free the strings and the array after use>.\n\n"
5343 pr "This function returns a buffer, or NULL on error.
5344 The size of the returned buffer is written to C<*size_r>.
5345 I<The caller must free the returned buffer after use>.\n\n"
5347 if List.mem ProtocolLimitWarning flags then
5348 pr "%s\n\n" protocol_limit_warning;
5349 if List.mem DangerWillRobinson flags then
5350 pr "%s\n\n" danger_will_robinson;
5351 match deprecation_notice flags with
5353 | Some txt -> pr "%s\n\n" txt
5355 ) all_functions_sorted
5357 and generate_structs_pod () =
5358 (* Structs documentation. *)
5361 pr "=head2 guestfs_%s\n" typ;
5363 pr " struct guestfs_%s {\n" typ;
5366 | name, FChar -> pr " char %s;\n" name
5367 | name, FUInt32 -> pr " uint32_t %s;\n" name
5368 | name, FInt32 -> pr " int32_t %s;\n" name
5369 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5370 | name, FInt64 -> pr " int64_t %s;\n" name
5371 | name, FString -> pr " char *%s;\n" name
5373 pr " /* The next two fields describe a byte array. */\n";
5374 pr " uint32_t %s_len;\n" name;
5375 pr " char *%s;\n" name
5377 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5378 pr " char %s[32];\n" name
5379 | name, FOptPercent ->
5380 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5381 pr " float %s;\n" name
5385 pr " struct guestfs_%s_list {\n" typ;
5386 pr " uint32_t len; /* Number of elements in list. */\n";
5387 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5390 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5391 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5396 and generate_availability_pod () =
5397 (* Availability documentation. *)
5401 fun (group, functions) ->
5402 pr "=item B<%s>\n" group;
5404 pr "The following functions:\n";
5405 List.iter (pr "L</guestfs_%s>\n") functions;
5411 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5412 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5414 * We have to use an underscore instead of a dash because otherwise
5415 * rpcgen generates incorrect code.
5417 * This header is NOT exported to clients, but see also generate_structs_h.
5419 and generate_xdr () =
5420 generate_header CStyle LGPLv2plus;
5422 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5423 pr "typedef string str<>;\n";
5426 (* Internal structures. *)
5430 pr "struct guestfs_int_%s {\n" typ;
5432 | name, FChar -> pr " char %s;\n" name
5433 | name, FString -> pr " string %s<>;\n" name
5434 | name, FBuffer -> pr " opaque %s<>;\n" name
5435 | name, FUUID -> pr " opaque %s[32];\n" name
5436 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5437 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5438 | name, FOptPercent -> pr " float %s;\n" name
5442 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5447 fun (shortname, style, _, _, _, _, _) ->
5448 let name = "guestfs_" ^ shortname in
5450 (match snd style with
5453 pr "struct %s_args {\n" name;
5456 | Pathname n | Device n | Dev_or_Path n | String n ->
5457 pr " string %s<>;\n" n
5458 | OptString n -> pr " str *%s;\n" n
5459 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5460 | Bool n -> pr " bool %s;\n" n
5461 | Int n -> pr " int %s;\n" n
5462 | Int64 n -> pr " hyper %s;\n" n
5463 | FileIn _ | FileOut _ -> ()
5467 (match fst style with
5470 pr "struct %s_ret {\n" name;
5474 pr "struct %s_ret {\n" name;
5475 pr " hyper %s;\n" n;
5478 pr "struct %s_ret {\n" name;
5481 | RConstString _ | RConstOptString _ ->
5482 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5484 pr "struct %s_ret {\n" name;
5485 pr " string %s<>;\n" n;
5488 pr "struct %s_ret {\n" name;
5489 pr " str %s<>;\n" n;
5491 | RStruct (n, typ) ->
5492 pr "struct %s_ret {\n" name;
5493 pr " guestfs_int_%s %s;\n" typ n;
5495 | RStructList (n, typ) ->
5496 pr "struct %s_ret {\n" name;
5497 pr " guestfs_int_%s_list %s;\n" typ n;
5500 pr "struct %s_ret {\n" name;
5501 pr " str %s<>;\n" n;
5504 pr "struct %s_ret {\n" name;
5505 pr " opaque %s<>;\n" n;
5510 (* Table of procedure numbers. *)
5511 pr "enum guestfs_procedure {\n";
5513 fun (shortname, _, proc_nr, _, _, _, _) ->
5514 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5516 pr " GUESTFS_PROC_NR_PROCS\n";
5520 (* Having to choose a maximum message size is annoying for several
5521 * reasons (it limits what we can do in the API), but it (a) makes
5522 * the protocol a lot simpler, and (b) provides a bound on the size
5523 * of the daemon which operates in limited memory space.
5525 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5528 (* Message header, etc. *)
5530 /* The communication protocol is now documented in the guestfs(3)
5534 const GUESTFS_PROGRAM = 0x2000F5F5;
5535 const GUESTFS_PROTOCOL_VERSION = 1;
5537 /* These constants must be larger than any possible message length. */
5538 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5539 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5541 enum guestfs_message_direction {
5542 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5543 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5546 enum guestfs_message_status {
5547 GUESTFS_STATUS_OK = 0,
5548 GUESTFS_STATUS_ERROR = 1
5551 const GUESTFS_ERROR_LEN = 256;
5553 struct guestfs_message_error {
5554 string error_message<GUESTFS_ERROR_LEN>;
5557 struct guestfs_message_header {
5558 unsigned prog; /* GUESTFS_PROGRAM */
5559 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5560 guestfs_procedure proc; /* GUESTFS_PROC_x */
5561 guestfs_message_direction direction;
5562 unsigned serial; /* message serial number */
5563 guestfs_message_status status;
5566 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5568 struct guestfs_chunk {
5569 int cancel; /* if non-zero, transfer is cancelled */
5570 /* data size is 0 bytes if the transfer has finished successfully */
5571 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5575 (* Generate the guestfs-structs.h file. *)
5576 and generate_structs_h () =
5577 generate_header CStyle LGPLv2plus;
5579 (* This is a public exported header file containing various
5580 * structures. The structures are carefully written to have
5581 * exactly the same in-memory format as the XDR structures that
5582 * we use on the wire to the daemon. The reason for creating
5583 * copies of these structures here is just so we don't have to
5584 * export the whole of guestfs_protocol.h (which includes much
5585 * unrelated and XDR-dependent stuff that we don't want to be
5586 * public, or required by clients).
5588 * To reiterate, we will pass these structures to and from the
5589 * client with a simple assignment or memcpy, so the format
5590 * must be identical to what rpcgen / the RFC defines.
5593 (* Public structures. *)
5596 pr "struct guestfs_%s {\n" typ;
5599 | name, FChar -> pr " char %s;\n" name
5600 | name, FString -> pr " char *%s;\n" name
5602 pr " uint32_t %s_len;\n" name;
5603 pr " char *%s;\n" name
5604 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5605 | name, FUInt32 -> pr " uint32_t %s;\n" name
5606 | name, FInt32 -> pr " int32_t %s;\n" name
5607 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5608 | name, FInt64 -> pr " int64_t %s;\n" name
5609 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5613 pr "struct guestfs_%s_list {\n" typ;
5614 pr " uint32_t len;\n";
5615 pr " struct guestfs_%s *val;\n" typ;
5618 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5619 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5623 (* Generate the guestfs-actions.h file. *)
5624 and generate_actions_h () =
5625 generate_header CStyle LGPLv2plus;
5627 fun (shortname, style, _, _, _, _, _) ->
5628 let name = "guestfs_" ^ shortname in
5629 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5633 (* Generate the guestfs-internal-actions.h file. *)
5634 and generate_internal_actions_h () =
5635 generate_header CStyle LGPLv2plus;
5637 fun (shortname, style, _, _, _, _, _) ->
5638 let name = "guestfs__" ^ shortname in
5639 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5641 ) non_daemon_functions
5643 (* Generate the client-side dispatch stubs. *)
5644 and generate_client_actions () =
5645 generate_header CStyle LGPLv2plus;
5652 #include <inttypes.h>
5654 #include \"guestfs.h\"
5655 #include \"guestfs-internal.h\"
5656 #include \"guestfs-internal-actions.h\"
5657 #include \"guestfs_protocol.h\"
5659 #define error guestfs_error
5660 //#define perrorf guestfs_perrorf
5661 #define safe_malloc guestfs_safe_malloc
5662 #define safe_realloc guestfs_safe_realloc
5663 //#define safe_strdup guestfs_safe_strdup
5664 #define safe_memdup guestfs_safe_memdup
5666 /* Check the return message from a call for validity. */
5668 check_reply_header (guestfs_h *g,
5669 const struct guestfs_message_header *hdr,
5670 unsigned int proc_nr, unsigned int serial)
5672 if (hdr->prog != GUESTFS_PROGRAM) {
5673 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5676 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5677 error (g, \"wrong protocol version (%%d/%%d)\",
5678 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5681 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5682 error (g, \"unexpected message direction (%%d/%%d)\",
5683 hdr->direction, GUESTFS_DIRECTION_REPLY);
5686 if (hdr->proc != proc_nr) {
5687 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5690 if (hdr->serial != serial) {
5691 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5698 /* Check we are in the right state to run a high-level action. */
5700 check_state (guestfs_h *g, const char *caller)
5702 if (!guestfs__is_ready (g)) {
5703 if (guestfs__is_config (g) || guestfs__is_launching (g))
5704 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5707 error (g, \"%%s called from the wrong state, %%d != READY\",
5708 caller, guestfs__get_state (g));
5716 (* Generate code to generate guestfish call traces. *)
5717 let trace_call shortname style =
5718 pr " if (guestfs__get_trace (g)) {\n";
5721 List.exists (function
5722 | StringList _ | DeviceList _ -> true
5723 | _ -> false) (snd style) in
5729 pr " printf (\"%s\");\n" shortname;
5732 | String n (* strings *)
5738 (* guestfish doesn't support string escaping, so neither do we *)
5739 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5740 | OptString n -> (* string option *)
5741 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5742 pr " else printf (\" null\");\n"
5744 | DeviceList n -> (* string list *)
5745 pr " putchar (' ');\n";
5746 pr " putchar ('\"');\n";
5747 pr " for (i = 0; %s[i]; ++i) {\n" n;
5748 pr " if (i > 0) putchar (' ');\n";
5749 pr " fputs (%s[i], stdout);\n" n;
5751 pr " putchar ('\"');\n";
5752 | Bool n -> (* boolean *)
5753 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5754 | Int n -> (* int *)
5755 pr " printf (\" %%d\", %s);\n" n
5757 pr " printf (\" %%\" PRIi64, %s);\n" n
5759 pr " putchar ('\\n');\n";
5764 (* For non-daemon functions, generate a wrapper around each function. *)
5766 fun (shortname, style, _, _, _, _, _) ->
5767 let name = "guestfs_" ^ shortname in
5769 generate_prototype ~extern:false ~semicolon:false ~newline:true
5770 ~handle:"g" name style;
5772 trace_call shortname style;
5773 pr " return guestfs__%s " shortname;
5774 generate_c_call_args ~handle:"g" style;
5778 ) non_daemon_functions;
5780 (* Client-side stubs for each function. *)
5782 fun (shortname, style, _, _, _, _, _) ->
5783 let name = "guestfs_" ^ shortname in
5785 (* Generate the action stub. *)
5786 generate_prototype ~extern:false ~semicolon:false ~newline:true
5787 ~handle:"g" name style;
5790 match fst style with
5791 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5792 | RConstString _ | RConstOptString _ ->
5793 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5794 | RString _ | RStringList _
5795 | RStruct _ | RStructList _
5796 | RHashtable _ | RBufferOut _ ->
5801 (match snd style with
5803 | _ -> pr " struct %s_args args;\n" name
5806 pr " guestfs_message_header hdr;\n";
5807 pr " guestfs_message_error err;\n";
5809 match fst style with
5811 | RConstString _ | RConstOptString _ ->
5812 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5814 | RBool _ | RString _ | RStringList _
5815 | RStruct _ | RStructList _
5816 | RHashtable _ | RBufferOut _ ->
5817 pr " struct %s_ret ret;\n" name;
5820 pr " int serial;\n";
5823 trace_call shortname style;
5824 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5825 shortname error_code;
5826 pr " guestfs___set_busy (g);\n";
5829 (* Send the main header and arguments. *)
5830 (match snd style with
5832 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5833 (String.uppercase shortname)
5837 | Pathname n | Device n | Dev_or_Path n | String n ->
5838 pr " args.%s = (char *) %s;\n" n n
5840 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5841 | StringList n | DeviceList n ->
5842 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5843 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5845 pr " args.%s = %s;\n" n n
5847 pr " args.%s = %s;\n" n n
5849 pr " args.%s = %s;\n" n n
5850 | FileIn _ | FileOut _ -> ()
5852 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5853 (String.uppercase shortname);
5854 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5857 pr " if (serial == -1) {\n";
5858 pr " guestfs___end_busy (g);\n";
5859 pr " return %s;\n" error_code;
5863 (* Send any additional files (FileIn) requested. *)
5864 let need_read_reply_label = ref false in
5868 pr " r = guestfs___send_file (g, %s);\n" n;
5869 pr " if (r == -1) {\n";
5870 pr " guestfs___end_busy (g);\n";
5871 pr " return %s;\n" error_code;
5873 pr " if (r == -2) /* daemon cancelled */\n";
5874 pr " goto read_reply;\n";
5875 need_read_reply_label := true;
5880 (* Wait for the reply from the remote end. *)
5881 if !need_read_reply_label then pr " read_reply:\n";
5882 pr " memset (&hdr, 0, sizeof hdr);\n";
5883 pr " memset (&err, 0, sizeof err);\n";
5884 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5886 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5890 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5893 pr " if (r == -1) {\n";
5894 pr " guestfs___end_busy (g);\n";
5895 pr " return %s;\n" error_code;
5899 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5900 (String.uppercase shortname);
5901 pr " guestfs___end_busy (g);\n";
5902 pr " return %s;\n" error_code;
5906 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5907 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5908 pr " free (err.error_message);\n";
5909 pr " guestfs___end_busy (g);\n";
5910 pr " return %s;\n" error_code;
5914 (* Expecting to receive further files (FileOut)? *)
5918 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5919 pr " guestfs___end_busy (g);\n";
5920 pr " return %s;\n" error_code;
5926 pr " guestfs___end_busy (g);\n";
5928 (match fst style with
5929 | RErr -> pr " return 0;\n"
5930 | RInt n | RInt64 n | RBool n ->
5931 pr " return ret.%s;\n" n
5932 | RConstString _ | RConstOptString _ ->
5933 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5935 pr " return ret.%s; /* caller will free */\n" n
5936 | RStringList n | RHashtable n ->
5937 pr " /* caller will free this, but we need to add a NULL entry */\n";
5938 pr " ret.%s.%s_val =\n" n n;
5939 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5940 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5942 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5943 pr " return ret.%s.%s_val;\n" n n
5945 pr " /* caller will free this */\n";
5946 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5947 | RStructList (n, _) ->
5948 pr " /* caller will free this */\n";
5949 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5951 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5952 pr " * _val might be NULL here. To make the API saner for\n";
5953 pr " * callers, we turn this case into a unique pointer (using\n";
5954 pr " * malloc(1)).\n";
5956 pr " if (ret.%s.%s_len > 0) {\n" n n;
5957 pr " *size_r = ret.%s.%s_len;\n" n n;
5958 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5960 pr " free (ret.%s.%s_val);\n" n n;
5961 pr " char *p = safe_malloc (g, 1);\n";
5962 pr " *size_r = ret.%s.%s_len;\n" n n;
5970 (* Functions to free structures. *)
5971 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5972 pr " * structure format is identical to the XDR format. See note in\n";
5973 pr " * generator.ml.\n";
5980 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5982 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5988 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5990 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5997 (* Generate daemon/actions.h. *)
5998 and generate_daemon_actions_h () =
5999 generate_header CStyle GPLv2plus;
6001 pr "#include \"../src/guestfs_protocol.h\"\n";
6005 fun (name, style, _, _, _, _, _) ->
6007 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6011 (* Generate the linker script which controls the visibility of
6012 * symbols in the public ABI and ensures no other symbols get
6013 * exported accidentally.
6015 and generate_linker_script () =
6016 generate_header HashStyle GPLv2plus;
6021 "guestfs_get_error_handler";
6022 "guestfs_get_out_of_memory_handler";
6023 "guestfs_last_error";
6024 "guestfs_set_error_handler";
6025 "guestfs_set_launch_done_callback";
6026 "guestfs_set_log_message_callback";
6027 "guestfs_set_out_of_memory_handler";
6028 "guestfs_set_subprocess_quit_callback";
6030 (* Unofficial parts of the API: the bindings code use these
6031 * functions, so it is useful to export them.
6033 "guestfs_safe_calloc";
6034 "guestfs_safe_malloc";
6037 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6041 List.map (fun (typ, _) ->
6042 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6045 let globals = List.sort compare (globals @ functions @ structs) in
6049 List.iter (pr " %s;\n") globals;
6056 (* Generate the server-side stubs. *)
6057 and generate_daemon_actions () =
6058 generate_header CStyle GPLv2plus;
6060 pr "#include <config.h>\n";
6062 pr "#include <stdio.h>\n";
6063 pr "#include <stdlib.h>\n";
6064 pr "#include <string.h>\n";
6065 pr "#include <inttypes.h>\n";
6066 pr "#include <rpc/types.h>\n";
6067 pr "#include <rpc/xdr.h>\n";
6069 pr "#include \"daemon.h\"\n";
6070 pr "#include \"c-ctype.h\"\n";
6071 pr "#include \"../src/guestfs_protocol.h\"\n";
6072 pr "#include \"actions.h\"\n";
6076 fun (name, style, _, _, _, _, _) ->
6077 (* Generate server-side stubs. *)
6078 pr "static void %s_stub (XDR *xdr_in)\n" name;
6081 match fst style with
6082 | RErr | RInt _ -> pr " int r;\n"; "-1"
6083 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6084 | RBool _ -> pr " int r;\n"; "-1"
6085 | RConstString _ | RConstOptString _ ->
6086 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6087 | RString _ -> pr " char *r;\n"; "NULL"
6088 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6089 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6090 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6092 pr " size_t size = 1;\n";
6096 (match snd style with
6099 pr " struct guestfs_%s_args args;\n" name;
6102 | Device n | Dev_or_Path n
6105 | OptString n -> pr " char *%s;\n" n
6106 | StringList n | DeviceList n -> pr " char **%s;\n" n
6107 | Bool n -> pr " int %s;\n" n
6108 | Int n -> pr " int %s;\n" n
6109 | Int64 n -> pr " int64_t %s;\n" n
6110 | FileIn _ | FileOut _ -> ()
6116 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6118 (match snd style with
6121 pr " memset (&args, 0, sizeof args);\n";
6123 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6125 pr " cancel_receive ();\n";
6126 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6130 pr " char *%s = args.%s;\n" n n
6132 let pr_list_handling_code n =
6133 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6134 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6135 pr " if (%s == NULL) {\n" n;
6137 pr " cancel_receive ();\n";
6138 pr " reply_with_perror (\"realloc\");\n";
6141 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6142 pr " args.%s.%s_val = %s;\n" n n n;
6148 pr " ABS_PATH (%s, %s, goto done);\n"
6149 n (if is_filein then "cancel_receive ()" else "");
6152 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6153 n (if is_filein then "cancel_receive ()" else "");
6156 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6157 n (if is_filein then "cancel_receive ()" else "");
6158 | String n -> pr_args n
6159 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6161 pr_list_handling_code n;
6163 pr_list_handling_code n;
6164 pr " /* Ensure that each is a device,\n";
6165 pr " * and perform device name translation. */\n";
6166 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6167 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6168 (if is_filein then "cancel_receive ()" else "");
6170 | Bool n -> pr " %s = args.%s;\n" n n
6171 | Int n -> pr " %s = args.%s;\n" n n
6172 | Int64 n -> pr " %s = args.%s;\n" n n
6173 | FileIn _ | FileOut _ -> ()
6179 (* this is used at least for do_equal *)
6180 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6181 (* Emit NEED_ROOT just once, even when there are two or
6182 more Pathname args *)
6183 pr " NEED_ROOT (%s, goto done);\n"
6184 (if is_filein then "cancel_receive ()" else "");
6187 (* Don't want to call the impl with any FileIn or FileOut
6188 * parameters, since these go "outside" the RPC protocol.
6191 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6193 pr " r = do_%s " name;
6194 generate_c_call_args (fst style, args');
6197 (match fst style with
6198 | RErr | RInt _ | RInt64 _ | RBool _
6199 | RConstString _ | RConstOptString _
6200 | RString _ | RStringList _ | RHashtable _
6201 | RStruct (_, _) | RStructList (_, _) ->
6202 pr " if (r == %s)\n" error_code;
6203 pr " /* do_%s has already called reply_with_error */\n" name;
6207 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6208 pr " * an ordinary zero-length buffer), so be careful ...\n";
6210 pr " if (size == 1 && r == %s)\n" error_code;
6211 pr " /* do_%s has already called reply_with_error */\n" name;
6216 (* If there are any FileOut parameters, then the impl must
6217 * send its own reply.
6220 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6222 pr " /* do_%s has already sent a reply */\n" name
6224 match fst style with
6225 | RErr -> pr " reply (NULL, NULL);\n"
6226 | RInt n | RInt64 n | RBool n ->
6227 pr " struct guestfs_%s_ret ret;\n" name;
6228 pr " ret.%s = r;\n" n;
6229 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6231 | RConstString _ | RConstOptString _ ->
6232 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6234 pr " struct guestfs_%s_ret ret;\n" name;
6235 pr " ret.%s = r;\n" n;
6236 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6239 | RStringList n | RHashtable n ->
6240 pr " struct guestfs_%s_ret ret;\n" name;
6241 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6242 pr " ret.%s.%s_val = r;\n" n n;
6243 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6245 pr " free_strings (r);\n"
6247 pr " struct guestfs_%s_ret ret;\n" name;
6248 pr " ret.%s = *r;\n" n;
6249 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6251 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6253 | RStructList (n, _) ->
6254 pr " struct guestfs_%s_ret ret;\n" name;
6255 pr " ret.%s = *r;\n" n;
6256 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6258 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6261 pr " struct guestfs_%s_ret ret;\n" name;
6262 pr " ret.%s.%s_val = r;\n" n n;
6263 pr " ret.%s.%s_len = size;\n" n n;
6264 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6269 (* Free the args. *)
6271 (match snd style with
6274 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6281 (* Dispatch function. *)
6282 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6284 pr " switch (proc_nr) {\n";
6287 fun (name, style, _, _, _, _, _) ->
6288 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6289 pr " %s_stub (xdr_in);\n" name;
6294 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";
6299 (* LVM columns and tokenization functions. *)
6300 (* XXX This generates crap code. We should rethink how we
6306 pr "static const char *lvm_%s_cols = \"%s\";\n"
6307 typ (String.concat "," (List.map fst cols));
6310 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6312 pr " char *tok, *p, *next;\n";
6316 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6319 pr " if (!str) {\n";
6320 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6323 pr " if (!*str || c_isspace (*str)) {\n";
6324 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6329 fun (name, coltype) ->
6330 pr " if (!tok) {\n";
6331 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6334 pr " p = strchrnul (tok, ',');\n";
6335 pr " if (*p) next = p+1; else next = NULL;\n";
6336 pr " *p = '\\0';\n";
6339 pr " r->%s = strdup (tok);\n" name;
6340 pr " if (r->%s == NULL) {\n" name;
6341 pr " perror (\"strdup\");\n";
6345 pr " for (i = j = 0; i < 32; ++j) {\n";
6346 pr " if (tok[j] == '\\0') {\n";
6347 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6349 pr " } else if (tok[j] != '-')\n";
6350 pr " r->%s[i++] = tok[j];\n" name;
6353 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6354 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6358 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6359 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6363 pr " if (tok[0] == '\\0')\n";
6364 pr " r->%s = -1;\n" name;
6365 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6366 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6369 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6370 assert false (* can never be an LVM column *)
6372 pr " tok = next;\n";
6375 pr " if (tok != NULL) {\n";
6376 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6383 pr "guestfs_int_lvm_%s_list *\n" typ;
6384 pr "parse_command_line_%ss (void)\n" typ;
6386 pr " char *out, *err;\n";
6387 pr " char *p, *pend;\n";
6389 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6390 pr " void *newp;\n";
6392 pr " ret = malloc (sizeof *ret);\n";
6393 pr " if (!ret) {\n";
6394 pr " reply_with_perror (\"malloc\");\n";
6395 pr " return NULL;\n";
6398 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6399 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6401 pr " r = command (&out, &err,\n";
6402 pr " \"lvm\", \"%ss\",\n" typ;
6403 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6404 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6405 pr " if (r == -1) {\n";
6406 pr " reply_with_error (\"%%s\", err);\n";
6407 pr " free (out);\n";
6408 pr " free (err);\n";
6409 pr " free (ret);\n";
6410 pr " return NULL;\n";
6413 pr " free (err);\n";
6415 pr " /* Tokenize each line of the output. */\n";
6418 pr " while (p) {\n";
6419 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6420 pr " if (pend) {\n";
6421 pr " *pend = '\\0';\n";
6425 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6428 pr " if (!*p) { /* Empty line? Skip it. */\n";
6433 pr " /* Allocate some space to store this next entry. */\n";
6434 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6435 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6436 pr " if (newp == NULL) {\n";
6437 pr " reply_with_perror (\"realloc\");\n";
6438 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6439 pr " free (ret);\n";
6440 pr " free (out);\n";
6441 pr " return NULL;\n";
6443 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6445 pr " /* Tokenize the next entry. */\n";
6446 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6447 pr " if (r == -1) {\n";
6448 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6449 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6450 pr " free (ret);\n";
6451 pr " free (out);\n";
6452 pr " return NULL;\n";
6459 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6461 pr " free (out);\n";
6462 pr " return ret;\n";
6465 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6467 (* Generate a list of function names, for debugging in the daemon.. *)
6468 and generate_daemon_names () =
6469 generate_header CStyle GPLv2plus;
6471 pr "#include <config.h>\n";
6473 pr "#include \"daemon.h\"\n";
6476 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6477 pr "const char *function_names[] = {\n";
6479 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6483 (* Generate the optional groups for the daemon to implement
6484 * guestfs_available.
6486 and generate_daemon_optgroups_c () =
6487 generate_header CStyle GPLv2plus;
6489 pr "#include <config.h>\n";
6491 pr "#include \"daemon.h\"\n";
6492 pr "#include \"optgroups.h\"\n";
6495 pr "struct optgroup optgroups[] = {\n";
6498 pr " { \"%s\", optgroup_%s_available },\n" group group
6500 pr " { NULL, NULL }\n";
6503 and generate_daemon_optgroups_h () =
6504 generate_header CStyle GPLv2plus;
6508 pr "extern int optgroup_%s_available (void);\n" group
6511 (* Generate the tests. *)
6512 and generate_tests () =
6513 generate_header CStyle GPLv2plus;
6520 #include <sys/types.h>
6523 #include \"guestfs.h\"
6524 #include \"guestfs-internal.h\"
6526 static guestfs_h *g;
6527 static int suppress_error = 0;
6529 static void print_error (guestfs_h *g, void *data, const char *msg)
6531 if (!suppress_error)
6532 fprintf (stderr, \"%%s\\n\", msg);
6535 /* FIXME: nearly identical code appears in fish.c */
6536 static void print_strings (char *const *argv)
6540 for (argc = 0; argv[argc] != NULL; ++argc)
6541 printf (\"\\t%%s\\n\", argv[argc]);
6545 static void print_table (char const *const *argv)
6549 for (i = 0; argv[i] != NULL; i += 2)
6550 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6556 (* Generate a list of commands which are not tested anywhere. *)
6557 pr "static void no_test_warnings (void)\n";
6560 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6562 fun (_, _, _, _, tests, _, _) ->
6563 let tests = filter_map (
6565 | (_, (Always|If _|Unless _), test) -> Some test
6566 | (_, Disabled, _) -> None
6568 let seq = List.concat (List.map seq_of_test tests) in
6569 let cmds_tested = List.map List.hd seq in
6570 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6574 fun (name, _, _, _, _, _, _) ->
6575 if not (Hashtbl.mem hash name) then
6576 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6582 (* Generate the actual tests. Note that we generate the tests
6583 * in reverse order, deliberately, so that (in general) the
6584 * newest tests run first. This makes it quicker and easier to
6589 fun (name, _, _, flags, tests, _, _) ->
6590 mapi (generate_one_test name flags) tests
6591 ) (List.rev all_functions) in
6592 let test_names = List.concat test_names in
6593 let nr_tests = List.length test_names in
6596 int main (int argc, char *argv[])
6599 unsigned long int n_failed = 0;
6600 const char *filename;
6602 int nr_tests, test_num = 0;
6604 setbuf (stdout, NULL);
6606 no_test_warnings ();
6608 g = guestfs_create ();
6610 printf (\"guestfs_create FAILED\\n\");
6611 exit (EXIT_FAILURE);
6614 guestfs_set_error_handler (g, print_error, NULL);
6616 guestfs_set_path (g, \"../appliance\");
6618 filename = \"test1.img\";
6619 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6622 exit (EXIT_FAILURE);
6624 if (lseek (fd, %d, SEEK_SET) == -1) {
6628 exit (EXIT_FAILURE);
6630 if (write (fd, &c, 1) == -1) {
6634 exit (EXIT_FAILURE);
6636 if (close (fd) == -1) {
6639 exit (EXIT_FAILURE);
6641 if (guestfs_add_drive (g, filename) == -1) {
6642 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6643 exit (EXIT_FAILURE);
6646 filename = \"test2.img\";
6647 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6650 exit (EXIT_FAILURE);
6652 if (lseek (fd, %d, SEEK_SET) == -1) {
6656 exit (EXIT_FAILURE);
6658 if (write (fd, &c, 1) == -1) {
6662 exit (EXIT_FAILURE);
6664 if (close (fd) == -1) {
6667 exit (EXIT_FAILURE);
6669 if (guestfs_add_drive (g, filename) == -1) {
6670 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6671 exit (EXIT_FAILURE);
6674 filename = \"test3.img\";
6675 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6678 exit (EXIT_FAILURE);
6680 if (lseek (fd, %d, SEEK_SET) == -1) {
6684 exit (EXIT_FAILURE);
6686 if (write (fd, &c, 1) == -1) {
6690 exit (EXIT_FAILURE);
6692 if (close (fd) == -1) {
6695 exit (EXIT_FAILURE);
6697 if (guestfs_add_drive (g, filename) == -1) {
6698 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6699 exit (EXIT_FAILURE);
6702 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6703 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6704 exit (EXIT_FAILURE);
6707 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6710 if (guestfs_launch (g) == -1) {
6711 printf (\"guestfs_launch FAILED\\n\");
6712 exit (EXIT_FAILURE);
6715 /* Cancel previous alarm. */
6720 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6724 pr " test_num++;\n";
6725 pr " if (guestfs_get_verbose (g))\n";
6726 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6727 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6728 pr " if (%s () == -1) {\n" test_name;
6729 pr " printf (\"%s FAILED\\n\");\n" test_name;
6730 pr " n_failed++;\n";
6735 pr " guestfs_close (g);\n";
6736 pr " unlink (\"test1.img\");\n";
6737 pr " unlink (\"test2.img\");\n";
6738 pr " unlink (\"test3.img\");\n";
6741 pr " if (n_failed > 0) {\n";
6742 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6743 pr " exit (EXIT_FAILURE);\n";
6747 pr " exit (EXIT_SUCCESS);\n";
6750 and generate_one_test name flags i (init, prereq, test) =
6751 let test_name = sprintf "test_%s_%d" name i in
6754 static int %s_skip (void)
6758 str = getenv (\"TEST_ONLY\");
6760 return strstr (str, \"%s\") == NULL;
6761 str = getenv (\"SKIP_%s\");
6762 if (str && STREQ (str, \"1\")) return 1;
6763 str = getenv (\"SKIP_TEST_%s\");
6764 if (str && STREQ (str, \"1\")) return 1;
6768 " test_name name (String.uppercase test_name) (String.uppercase name);
6771 | Disabled | Always -> ()
6772 | If code | Unless code ->
6773 pr "static int %s_prereq (void)\n" test_name;
6781 static int %s (void)
6784 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6788 " test_name test_name test_name;
6790 (* Optional functions should only be tested if the relevant
6791 * support is available in the daemon.
6797 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6799 pr " suppress_error = 1;\n";
6800 pr " r = guestfs_available (g, (char **) groups);\n";
6801 pr " suppress_error = 0;\n";
6802 pr " if (r == -1) {\n";
6803 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6812 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6814 pr " if (! %s_prereq ()) {\n" test_name;
6815 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6819 generate_one_test_body name i test_name init test;
6821 pr " if (%s_prereq ()) {\n" test_name;
6822 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6826 generate_one_test_body name i test_name init test;
6828 generate_one_test_body name i test_name init test
6836 and generate_one_test_body name i test_name init test =
6838 | InitNone (* XXX at some point, InitNone and InitEmpty became
6839 * folded together as the same thing. Really we should
6840 * make InitNone do nothing at all, but the tests may
6841 * need to be checked to make sure this is OK.
6844 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6845 List.iter (generate_test_command_call test_name)
6846 [["blockdev_setrw"; "/dev/sda"];
6850 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6851 List.iter (generate_test_command_call test_name)
6852 [["blockdev_setrw"; "/dev/sda"];
6855 ["part_disk"; "/dev/sda"; "mbr"]]
6857 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6858 List.iter (generate_test_command_call test_name)
6859 [["blockdev_setrw"; "/dev/sda"];
6862 ["part_disk"; "/dev/sda"; "mbr"];
6863 ["mkfs"; "ext2"; "/dev/sda1"];
6864 ["mount_options"; ""; "/dev/sda1"; "/"]]
6865 | InitBasicFSonLVM ->
6866 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6868 List.iter (generate_test_command_call test_name)
6869 [["blockdev_setrw"; "/dev/sda"];
6872 ["part_disk"; "/dev/sda"; "mbr"];
6873 ["pvcreate"; "/dev/sda1"];
6874 ["vgcreate"; "VG"; "/dev/sda1"];
6875 ["lvcreate"; "LV"; "VG"; "8"];
6876 ["mkfs"; "ext2"; "/dev/VG/LV"];
6877 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6879 pr " /* InitISOFS for %s */\n" test_name;
6880 List.iter (generate_test_command_call test_name)
6881 [["blockdev_setrw"; "/dev/sda"];
6884 ["mount_ro"; "/dev/sdd"; "/"]]
6887 let get_seq_last = function
6889 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6892 let seq = List.rev seq in
6893 List.rev (List.tl seq), List.hd seq
6898 pr " /* TestRun for %s (%d) */\n" name i;
6899 List.iter (generate_test_command_call test_name) seq
6900 | TestOutput (seq, expected) ->
6901 pr " /* TestOutput for %s (%d) */\n" name i;
6902 pr " const char *expected = \"%s\";\n" (c_quote expected);
6903 let seq, last = get_seq_last seq in
6905 pr " if (STRNEQ (r, expected)) {\n";
6906 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6910 List.iter (generate_test_command_call test_name) seq;
6911 generate_test_command_call ~test test_name last
6912 | TestOutputList (seq, expected) ->
6913 pr " /* TestOutputList for %s (%d) */\n" name i;
6914 let seq, last = get_seq_last seq in
6918 pr " if (!r[%d]) {\n" i;
6919 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6920 pr " print_strings (r);\n";
6924 pr " const char *expected = \"%s\";\n" (c_quote str);
6925 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6926 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6931 pr " if (r[%d] != NULL) {\n" (List.length expected);
6932 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6934 pr " print_strings (r);\n";
6938 List.iter (generate_test_command_call test_name) seq;
6939 generate_test_command_call ~test test_name last
6940 | TestOutputListOfDevices (seq, expected) ->
6941 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6942 let seq, last = get_seq_last seq in
6946 pr " if (!r[%d]) {\n" i;
6947 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6948 pr " print_strings (r);\n";
6952 pr " const char *expected = \"%s\";\n" (c_quote str);
6953 pr " r[%d][5] = 's';\n" i;
6954 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6955 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6960 pr " if (r[%d] != NULL) {\n" (List.length expected);
6961 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6963 pr " print_strings (r);\n";
6967 List.iter (generate_test_command_call test_name) seq;
6968 generate_test_command_call ~test test_name last
6969 | TestOutputInt (seq, expected) ->
6970 pr " /* TestOutputInt for %s (%d) */\n" name i;
6971 let seq, last = get_seq_last seq in
6973 pr " if (r != %d) {\n" expected;
6974 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6980 List.iter (generate_test_command_call test_name) seq;
6981 generate_test_command_call ~test test_name last
6982 | TestOutputIntOp (seq, op, expected) ->
6983 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6984 let seq, last = get_seq_last seq in
6986 pr " if (! (r %s %d)) {\n" op expected;
6987 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6988 test_name op expected;
6993 List.iter (generate_test_command_call test_name) seq;
6994 generate_test_command_call ~test test_name last
6995 | TestOutputTrue seq ->
6996 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6997 let seq, last = get_seq_last seq in
7000 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7005 List.iter (generate_test_command_call test_name) seq;
7006 generate_test_command_call ~test test_name last
7007 | TestOutputFalse seq ->
7008 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7009 let seq, last = get_seq_last seq in
7012 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7017 List.iter (generate_test_command_call test_name) seq;
7018 generate_test_command_call ~test test_name last
7019 | TestOutputLength (seq, expected) ->
7020 pr " /* TestOutputLength for %s (%d) */\n" name i;
7021 let seq, last = get_seq_last seq in
7024 pr " for (j = 0; j < %d; ++j)\n" expected;
7025 pr " if (r[j] == NULL) {\n";
7026 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7028 pr " print_strings (r);\n";
7031 pr " if (r[j] != NULL) {\n";
7032 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7034 pr " print_strings (r);\n";
7038 List.iter (generate_test_command_call test_name) seq;
7039 generate_test_command_call ~test test_name last
7040 | TestOutputBuffer (seq, expected) ->
7041 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7042 pr " const char *expected = \"%s\";\n" (c_quote expected);
7043 let seq, last = get_seq_last seq in
7044 let len = String.length expected in
7046 pr " if (size != %d) {\n" len;
7047 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7050 pr " if (STRNEQLEN (r, expected, size)) {\n";
7051 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7055 List.iter (generate_test_command_call test_name) seq;
7056 generate_test_command_call ~test test_name last
7057 | TestOutputStruct (seq, checks) ->
7058 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7059 let seq, last = get_seq_last seq in
7063 | CompareWithInt (field, expected) ->
7064 pr " if (r->%s != %d) {\n" field expected;
7065 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7066 test_name field expected;
7067 pr " (int) r->%s);\n" field;
7070 | CompareWithIntOp (field, op, expected) ->
7071 pr " if (!(r->%s %s %d)) {\n" field op expected;
7072 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7073 test_name field op expected;
7074 pr " (int) r->%s);\n" field;
7077 | CompareWithString (field, expected) ->
7078 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7079 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7080 test_name field expected;
7081 pr " r->%s);\n" field;
7084 | CompareFieldsIntEq (field1, field2) ->
7085 pr " if (r->%s != r->%s) {\n" field1 field2;
7086 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7087 test_name field1 field2;
7088 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7091 | CompareFieldsStrEq (field1, field2) ->
7092 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7093 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7094 test_name field1 field2;
7095 pr " r->%s, r->%s);\n" field1 field2;
7100 List.iter (generate_test_command_call test_name) seq;
7101 generate_test_command_call ~test test_name last
7102 | TestLastFail seq ->
7103 pr " /* TestLastFail for %s (%d) */\n" name i;
7104 let seq, last = get_seq_last seq in
7105 List.iter (generate_test_command_call test_name) seq;
7106 generate_test_command_call test_name ~expect_error:true last
7108 (* Generate the code to run a command, leaving the result in 'r'.
7109 * If you expect to get an error then you should set expect_error:true.
7111 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7113 | [] -> assert false
7115 (* Look up the command to find out what args/ret it has. *)
7118 let _, style, _, _, _, _, _ =
7119 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7122 failwithf "%s: in test, command %s was not found" test_name name in
7124 if List.length (snd style) <> List.length args then
7125 failwithf "%s: in test, wrong number of args given to %s"
7132 | OptString n, "NULL" -> ()
7135 | Dev_or_Path n, arg
7137 | OptString n, arg ->
7138 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7142 | FileIn _, _ | FileOut _, _ -> ()
7143 | StringList n, "" | DeviceList n, "" ->
7144 pr " const char *const %s[1] = { NULL };\n" n
7145 | StringList n, arg | DeviceList n, arg ->
7146 let strs = string_split " " arg in
7149 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7151 pr " const char *const %s[] = {\n" n;
7153 fun i _ -> pr " %s_%d,\n" n i
7157 ) (List.combine (snd style) args);
7160 match fst style with
7161 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7162 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7163 | RConstString _ | RConstOptString _ ->
7164 pr " const char *r;\n"; "NULL"
7165 | RString _ -> pr " char *r;\n"; "NULL"
7166 | RStringList _ | RHashtable _ ->
7170 | RStruct (_, typ) ->
7171 pr " struct guestfs_%s *r;\n" typ; "NULL"
7172 | RStructList (_, typ) ->
7173 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7176 pr " size_t size;\n";
7179 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7180 pr " r = guestfs_%s (g" name;
7182 (* Generate the parameters. *)
7185 | OptString _, "NULL" -> pr ", NULL"
7187 | Device n, _ | Dev_or_Path n, _
7191 | FileIn _, arg | FileOut _, arg ->
7192 pr ", \"%s\"" (c_quote arg)
7193 | StringList n, _ | DeviceList n, _ ->
7194 pr ", (char **) %s" n
7197 try int_of_string arg
7198 with Failure "int_of_string" ->
7199 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7203 try Int64.of_string arg
7204 with Failure "int_of_string" ->
7205 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7208 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7209 ) (List.combine (snd style) args);
7211 (match fst style with
7212 | RBufferOut _ -> pr ", &size"
7218 if not expect_error then
7219 pr " if (r == %s)\n" error_code
7221 pr " if (r != %s)\n" error_code;
7224 (* Insert the test code. *)
7230 (match fst style with
7231 | RErr | RInt _ | RInt64 _ | RBool _
7232 | RConstString _ | RConstOptString _ -> ()
7233 | RString _ | RBufferOut _ -> pr " free (r);\n"
7234 | RStringList _ | RHashtable _ ->
7235 pr " for (i = 0; r[i] != NULL; ++i)\n";
7236 pr " free (r[i]);\n";
7238 | RStruct (_, typ) ->
7239 pr " guestfs_free_%s (r);\n" typ
7240 | RStructList (_, typ) ->
7241 pr " guestfs_free_%s_list (r);\n" typ
7247 let str = replace_str str "\r" "\\r" in
7248 let str = replace_str str "\n" "\\n" in
7249 let str = replace_str str "\t" "\\t" in
7250 let str = replace_str str "\000" "\\0" in
7253 (* Generate a lot of different functions for guestfish. *)
7254 and generate_fish_cmds () =
7255 generate_header CStyle GPLv2plus;
7259 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7261 let all_functions_sorted =
7263 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7264 ) all_functions_sorted in
7266 pr "#include <config.h>\n";
7268 pr "#include <stdio.h>\n";
7269 pr "#include <stdlib.h>\n";
7270 pr "#include <string.h>\n";
7271 pr "#include <inttypes.h>\n";
7273 pr "#include <guestfs.h>\n";
7274 pr "#include \"c-ctype.h\"\n";
7275 pr "#include \"full-write.h\"\n";
7276 pr "#include \"xstrtol.h\"\n";
7277 pr "#include \"fish.h\"\n";
7280 (* list_commands function, which implements guestfish -h *)
7281 pr "void list_commands (void)\n";
7283 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7284 pr " list_builtin_commands ();\n";
7286 fun (name, _, _, flags, _, shortdesc, _) ->
7287 let name = replace_char name '_' '-' in
7288 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7290 ) all_functions_sorted;
7291 pr " printf (\" %%s\\n\",";
7292 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7296 (* display_command function, which implements guestfish -h cmd *)
7297 pr "void display_command (const char *cmd)\n";
7300 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7301 let name2 = replace_char name '_' '-' in
7303 try find_map (function FishAlias n -> Some n | _ -> None) flags
7304 with Not_found -> name in
7305 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7307 match snd style with
7311 name2 (String.concat " " (List.map name_of_argt args)) in
7314 if List.mem ProtocolLimitWarning flags then
7315 ("\n\n" ^ protocol_limit_warning)
7318 (* For DangerWillRobinson commands, we should probably have
7319 * guestfish prompt before allowing you to use them (especially
7320 * in interactive mode). XXX
7324 if List.mem DangerWillRobinson flags then
7325 ("\n\n" ^ danger_will_robinson)
7330 match deprecation_notice flags with
7332 | Some txt -> "\n\n" ^ txt in
7334 let describe_alias =
7335 if name <> alias then
7336 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7340 pr "STRCASEEQ (cmd, \"%s\")" name;
7341 if name <> name2 then
7342 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7343 if name <> alias then
7344 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7346 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7348 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7349 "=head1 DESCRIPTION\n\n" ^
7350 longdesc ^ warnings ^ describe_alias);
7353 pr " display_builtin_command (cmd);\n";
7357 let emit_print_list_function typ =
7358 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7361 pr " unsigned int i;\n";
7363 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7364 pr " printf (\"[%%d] = {\\n\", i);\n";
7365 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7366 pr " printf (\"}\\n\");\n";
7372 (* print_* functions *)
7376 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7378 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7381 pr " unsigned int i;\n";
7387 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7389 pr " printf (\"%%s%s: \", indent);\n" name;
7390 pr " for (i = 0; i < 32; ++i)\n";
7391 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7392 pr " printf (\"\\n\");\n"
7394 pr " printf (\"%%s%s: \", indent);\n" name;
7395 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7396 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7397 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7399 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7400 pr " printf (\"\\n\");\n"
7401 | name, (FUInt64|FBytes) ->
7402 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7405 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7408 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7411 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7414 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7416 | name, FOptPercent ->
7417 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7418 typ name name typ name;
7419 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7425 (* Emit a print_TYPE_list function definition only if that function is used. *)
7428 | typ, (RStructListOnly | RStructAndList) ->
7429 (* generate the function for typ *)
7430 emit_print_list_function typ
7431 | typ, _ -> () (* empty *)
7432 ) (rstructs_used_by all_functions);
7434 (* Emit a print_TYPE function definition only if that function is used. *)
7437 | typ, (RStructOnly | RStructAndList) ->
7438 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7440 pr " print_%s_indent (%s, \"\");\n" typ typ;
7443 | typ, _ -> () (* empty *)
7444 ) (rstructs_used_by all_functions);
7446 (* run_<action> actions *)
7448 fun (name, style, _, flags, _, _, _) ->
7449 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7451 (match fst style with
7454 | RBool _ -> pr " int r;\n"
7455 | RInt64 _ -> pr " int64_t r;\n"
7456 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7457 | RString _ -> pr " char *r;\n"
7458 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7459 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7460 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7463 pr " size_t size;\n";
7469 | OptString n -> pr " const char *%s;\n" n
7473 | FileOut n -> pr " char *%s;\n" n
7474 | StringList n | DeviceList n -> pr " char **%s;\n" n
7475 | Bool n -> pr " int %s;\n" n
7476 | Int n -> pr " int %s;\n" n
7477 | Int64 n -> pr " int64_t %s;\n" n
7480 (* Check and convert parameters. *)
7481 let argc_expected = List.length (snd style) in
7482 pr " if (argc != %d) {\n" argc_expected;
7483 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7485 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7489 let parse_integer fn fntyp rtyp range name i =
7491 pr " strtol_error xerr;\n";
7492 pr " %s r;\n" fntyp;
7494 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7495 pr " if (xerr != LONGINT_OK) {\n";
7496 pr " fprintf (stderr,\n";
7497 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7498 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7503 | Some (min, max, comment) ->
7504 pr " /* %s */\n" comment;
7505 pr " if (r < %s || r > %s) {\n" min max;
7506 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7510 pr " /* The check above should ensure this assignment does not overflow. */\n";
7512 pr " %s = r;\n" name;
7521 pr " %s = argv[%d];\n" name i
7523 | Dev_or_Path name ->
7524 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7525 pr " if (%s == NULL) return -1;\n" name
7527 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7530 pr " %s = file_in (argv[%d]);\n" name i;
7531 pr " if (%s == NULL) return -1;\n" name
7533 pr " %s = file_out (argv[%d]);\n" name i;
7534 pr " if (%s == NULL) return -1;\n" name
7535 | StringList name | DeviceList name ->
7536 pr " %s = parse_string_list (argv[%d]);\n" name i;
7537 pr " if (%s == NULL) return -1;\n" name;
7539 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7542 let min = "(-(2LL<<30))"
7543 and max = "((2LL<<30)-1)"
7545 "The Int type in the generator is a signed 31 bit int." in
7546 Some (min, max, comment) in
7547 parse_integer "xstrtoll" "long long" "int" range name i
7549 parse_integer "xstrtoll" "long long" "int64_t" None name i
7552 (* Call C API function. *)
7554 try find_map (function FishAction n -> Some n | _ -> None) flags
7555 with Not_found -> sprintf "guestfs_%s" name in
7557 generate_c_call_args ~handle:"g" style;
7562 | Device name | String name
7563 | OptString name | Bool name
7564 | Int name | Int64 name -> ()
7565 | Pathname name | Dev_or_Path name | FileOut name ->
7566 pr " free (%s);\n" name
7568 pr " free_file_in (%s);\n" name
7569 | StringList name | DeviceList name ->
7570 pr " free_strings (%s);\n" name
7573 (* Any output flags? *)
7575 let flags = filter_map (
7576 function FishOutput flag -> Some flag | _ -> None
7582 failwithf "%s: more than one FishOutput flag is not allowed" name in
7584 (* Check return value for errors and display command results. *)
7585 (match fst style with
7586 | RErr -> pr " return r;\n"
7588 pr " if (r == -1) return -1;\n";
7589 (match fish_output with
7591 pr " printf (\"%%d\\n\", r);\n";
7592 | Some FishOutputOctal ->
7593 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7594 | Some FishOutputHexadecimal ->
7595 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7598 pr " if (r == -1) return -1;\n";
7599 (match fish_output with
7601 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7602 | Some FishOutputOctal ->
7603 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7604 | Some FishOutputHexadecimal ->
7605 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7608 pr " if (r == -1) return -1;\n";
7609 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7612 pr " if (r == NULL) return -1;\n";
7613 pr " printf (\"%%s\\n\", r);\n";
7615 | RConstOptString _ ->
7616 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7619 pr " if (r == NULL) return -1;\n";
7620 pr " printf (\"%%s\\n\", r);\n";
7624 pr " if (r == NULL) return -1;\n";
7625 pr " print_strings (r);\n";
7626 pr " free_strings (r);\n";
7628 | RStruct (_, typ) ->
7629 pr " if (r == NULL) return -1;\n";
7630 pr " print_%s (r);\n" typ;
7631 pr " guestfs_free_%s (r);\n" typ;
7633 | RStructList (_, typ) ->
7634 pr " if (r == NULL) return -1;\n";
7635 pr " print_%s_list (r);\n" typ;
7636 pr " guestfs_free_%s_list (r);\n" typ;
7639 pr " if (r == NULL) return -1;\n";
7640 pr " print_table (r);\n";
7641 pr " free_strings (r);\n";
7644 pr " if (r == NULL) return -1;\n";
7645 pr " if (full_write (1, r, size) != size) {\n";
7646 pr " perror (\"write\");\n";
7657 (* run_action function *)
7658 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7661 fun (name, _, _, flags, _, _, _) ->
7662 let name2 = replace_char name '_' '-' in
7664 try find_map (function FishAlias n -> Some n | _ -> None) flags
7665 with Not_found -> name in
7667 pr "STRCASEEQ (cmd, \"%s\")" name;
7668 if name <> name2 then
7669 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7670 if name <> alias then
7671 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7673 pr " return run_%s (cmd, argc, argv);\n" name;
7677 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7678 pr " if (command_num == 1)\n";
7679 pr " extended_help_message ();\n";
7686 (* Readline completion for guestfish. *)
7687 and generate_fish_completion () =
7688 generate_header CStyle GPLv2plus;
7692 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7702 #ifdef HAVE_LIBREADLINE
7703 #include <readline/readline.h>
7708 #ifdef HAVE_LIBREADLINE
7710 static const char *const commands[] = {
7711 BUILTIN_COMMANDS_FOR_COMPLETION,
7714 (* Get the commands, including the aliases. They don't need to be
7715 * sorted - the generator() function just does a dumb linear search.
7719 fun (name, _, _, flags, _, _, _) ->
7720 let name2 = replace_char name '_' '-' in
7722 try find_map (function FishAlias n -> Some n | _ -> None) flags
7723 with Not_found -> name in
7725 if name <> alias then [name2; alias] else [name2]
7727 let commands = List.flatten commands in
7729 List.iter (pr " \"%s\",\n") commands;
7735 generator (const char *text, int state)
7737 static int index, len;
7742 len = strlen (text);
7745 rl_attempted_completion_over = 1;
7747 while ((name = commands[index]) != NULL) {
7749 if (STRCASEEQLEN (name, text, len))
7750 return strdup (name);
7756 #endif /* HAVE_LIBREADLINE */
7758 #ifdef HAVE_RL_COMPLETION_MATCHES
7759 #define RL_COMPLETION_MATCHES rl_completion_matches
7761 #ifdef HAVE_COMPLETION_MATCHES
7762 #define RL_COMPLETION_MATCHES completion_matches
7764 #endif /* else just fail if we don't have either symbol */
7767 do_completion (const char *text, int start, int end)
7769 char **matches = NULL;
7771 #ifdef HAVE_LIBREADLINE
7772 rl_completion_append_character = ' ';
7775 matches = RL_COMPLETION_MATCHES (text, generator);
7776 else if (complete_dest_paths)
7777 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7784 (* Generate the POD documentation for guestfish. *)
7785 and generate_fish_actions_pod () =
7786 let all_functions_sorted =
7788 fun (_, _, _, flags, _, _, _) ->
7789 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7790 ) all_functions_sorted in
7792 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7795 fun (name, style, _, flags, _, _, longdesc) ->
7797 Str.global_substitute rex (
7800 try Str.matched_group 1 s
7802 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7803 "C<" ^ replace_char sub '_' '-' ^ ">"
7805 let name = replace_char name '_' '-' in
7807 try find_map (function FishAlias n -> Some n | _ -> None) flags
7808 with Not_found -> name in
7810 pr "=head2 %s" name;
7811 if name <> alias then
7818 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7819 | OptString n -> pr " %s" n
7820 | StringList n | DeviceList n -> pr " '%s ...'" n
7821 | Bool _ -> pr " true|false"
7822 | Int n -> pr " %s" n
7823 | Int64 n -> pr " %s" n
7824 | FileIn n | FileOut n -> pr " (%s|-)" n
7828 pr "%s\n\n" longdesc;
7830 if List.exists (function FileIn _ | FileOut _ -> true
7831 | _ -> false) (snd style) then
7832 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7834 if List.mem ProtocolLimitWarning flags then
7835 pr "%s\n\n" protocol_limit_warning;
7837 if List.mem DangerWillRobinson flags then
7838 pr "%s\n\n" danger_will_robinson;
7840 match deprecation_notice flags with
7842 | Some txt -> pr "%s\n\n" txt
7843 ) all_functions_sorted
7845 (* Generate a C function prototype. *)
7846 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7847 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7849 ?handle name style =
7850 if extern then pr "extern ";
7851 if static then pr "static ";
7852 (match fst style with
7854 | RInt _ -> pr "int "
7855 | RInt64 _ -> pr "int64_t "
7856 | RBool _ -> pr "int "
7857 | RConstString _ | RConstOptString _ -> pr "const char *"
7858 | RString _ | RBufferOut _ -> pr "char *"
7859 | RStringList _ | RHashtable _ -> pr "char **"
7860 | RStruct (_, typ) ->
7861 if not in_daemon then pr "struct guestfs_%s *" typ
7862 else pr "guestfs_int_%s *" typ
7863 | RStructList (_, typ) ->
7864 if not in_daemon then pr "struct guestfs_%s_list *" typ
7865 else pr "guestfs_int_%s_list *" typ
7867 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7868 pr "%s%s (" prefix name;
7869 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7872 let comma = ref false in
7875 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7879 if single_line then pr ", " else pr ",\n\t\t"
7886 | Device n | Dev_or_Path n
7890 pr "const char *%s" n
7891 | StringList n | DeviceList n ->
7893 pr "char *const *%s" n
7894 | Bool n -> next (); pr "int %s" n
7895 | Int n -> next (); pr "int %s" n
7896 | Int64 n -> next (); pr "int64_t %s" n
7899 if not in_daemon then (next (); pr "const char *%s" n)
7901 if is_RBufferOut then (next (); pr "size_t *size_r");
7904 if semicolon then pr ";";
7905 if newline then pr "\n"
7907 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7908 and generate_c_call_args ?handle ?(decl = false) style =
7910 let comma = ref false in
7912 if !comma then pr ", ";
7917 | Some handle -> pr "%s" handle; comma := true
7922 pr "%s" (name_of_argt arg)
7924 (* For RBufferOut calls, add implicit &size parameter. *)
7926 match fst style with
7934 (* Generate the OCaml bindings interface. *)
7935 and generate_ocaml_mli () =
7936 generate_header OCamlStyle LGPLv2plus;
7939 (** For API documentation you should refer to the C API
7940 in the guestfs(3) manual page. The OCaml API uses almost
7941 exactly the same calls. *)
7944 (** A [guestfs_h] handle. *)
7946 exception Error of string
7947 (** This exception is raised when there is an error. *)
7949 exception Handle_closed of string
7950 (** This exception is raised if you use a {!Guestfs.t} handle
7951 after calling {!close} on it. The string is the name of
7954 val create : unit -> t
7955 (** Create a {!Guestfs.t} handle. *)
7957 val close : t -> unit
7958 (** Close the {!Guestfs.t} handle and free up all resources used
7961 Handles are closed by the garbage collector when they become
7962 unreferenced, but callers can call this in order to provide
7963 predictable cleanup. *)
7966 generate_ocaml_structure_decls ();
7970 fun (name, style, _, _, _, shortdesc, _) ->
7971 generate_ocaml_prototype name style;
7972 pr "(** %s *)\n" shortdesc;
7974 ) all_functions_sorted
7976 (* Generate the OCaml bindings implementation. *)
7977 and generate_ocaml_ml () =
7978 generate_header OCamlStyle LGPLv2plus;
7983 exception Error of string
7984 exception Handle_closed of string
7986 external create : unit -> t = \"ocaml_guestfs_create\"
7987 external close : t -> unit = \"ocaml_guestfs_close\"
7989 (* Give the exceptions names, so they can be raised from the C code. *)
7991 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7992 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7996 generate_ocaml_structure_decls ();
8000 fun (name, style, _, _, _, shortdesc, _) ->
8001 generate_ocaml_prototype ~is_external:true name style;
8002 ) all_functions_sorted
8004 (* Generate the OCaml bindings C implementation. *)
8005 and generate_ocaml_c () =
8006 generate_header CStyle LGPLv2plus;
8013 #include <caml/config.h>
8014 #include <caml/alloc.h>
8015 #include <caml/callback.h>
8016 #include <caml/fail.h>
8017 #include <caml/memory.h>
8018 #include <caml/mlvalues.h>
8019 #include <caml/signals.h>
8021 #include <guestfs.h>
8023 #include \"guestfs_c.h\"
8025 /* Copy a hashtable of string pairs into an assoc-list. We return
8026 * the list in reverse order, but hashtables aren't supposed to be
8029 static CAMLprim value
8030 copy_table (char * const * argv)
8033 CAMLlocal5 (rv, pairv, kv, vv, cons);
8037 for (i = 0; argv[i] != NULL; i += 2) {
8038 kv = caml_copy_string (argv[i]);
8039 vv = caml_copy_string (argv[i+1]);
8040 pairv = caml_alloc (2, 0);
8041 Store_field (pairv, 0, kv);
8042 Store_field (pairv, 1, vv);
8043 cons = caml_alloc (2, 0);
8044 Store_field (cons, 1, rv);
8046 Store_field (cons, 0, pairv);
8054 (* Struct copy functions. *)
8056 let emit_ocaml_copy_list_function typ =
8057 pr "static CAMLprim value\n";
8058 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8060 pr " CAMLparam0 ();\n";
8061 pr " CAMLlocal2 (rv, v);\n";
8062 pr " unsigned int i;\n";
8064 pr " if (%ss->len == 0)\n" typ;
8065 pr " CAMLreturn (Atom (0));\n";
8067 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8068 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8069 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8070 pr " caml_modify (&Field (rv, i), v);\n";
8072 pr " CAMLreturn (rv);\n";
8080 let has_optpercent_col =
8081 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8083 pr "static CAMLprim value\n";
8084 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8086 pr " CAMLparam0 ();\n";
8087 if has_optpercent_col then
8088 pr " CAMLlocal3 (rv, v, v2);\n"
8090 pr " CAMLlocal2 (rv, v);\n";
8092 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8097 pr " v = caml_copy_string (%s->%s);\n" typ name
8099 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8100 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8103 pr " v = caml_alloc_string (32);\n";
8104 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8105 | name, (FBytes|FInt64|FUInt64) ->
8106 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8107 | name, (FInt32|FUInt32) ->
8108 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8109 | name, FOptPercent ->
8110 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8111 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8112 pr " v = caml_alloc (1, 0);\n";
8113 pr " Store_field (v, 0, v2);\n";
8114 pr " } else /* None */\n";
8115 pr " v = Val_int (0);\n";
8117 pr " v = Val_int (%s->%s);\n" typ name
8119 pr " Store_field (rv, %d, v);\n" i
8121 pr " CAMLreturn (rv);\n";
8126 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8129 | typ, (RStructListOnly | RStructAndList) ->
8130 (* generate the function for typ *)
8131 emit_ocaml_copy_list_function typ
8132 | typ, _ -> () (* empty *)
8133 ) (rstructs_used_by all_functions);
8137 fun (name, style, _, _, _, _, _) ->
8138 pr "/* Automatically generated wrapper for function\n";
8140 generate_ocaml_prototype name style;
8145 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8147 let needs_extra_vs =
8148 match fst style with RConstOptString _ -> true | _ -> false in
8150 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8151 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8152 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8155 pr "CAMLprim value\n";
8156 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8157 List.iter (pr ", value %s") (List.tl params);
8162 | [p1; p2; p3; p4; p5] ->
8163 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8164 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8165 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8166 pr " CAMLxparam%d (%s);\n"
8167 (List.length rest) (String.concat ", " rest)
8169 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8171 if not needs_extra_vs then
8172 pr " CAMLlocal1 (rv);\n"
8174 pr " CAMLlocal3 (rv, v, v2);\n";
8177 pr " guestfs_h *g = Guestfs_val (gv);\n";
8178 pr " if (g == NULL)\n";
8179 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8185 | Device n | Dev_or_Path n
8189 pr " const char *%s = String_val (%sv);\n" n n
8191 pr " const char *%s =\n" n;
8192 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8194 | StringList n | DeviceList n ->
8195 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8197 pr " int %s = Bool_val (%sv);\n" n n
8199 pr " int %s = Int_val (%sv);\n" n n
8201 pr " int64_t %s = Int64_val (%sv);\n" n n
8204 match fst style with
8205 | RErr -> pr " int r;\n"; "-1"
8206 | RInt _ -> pr " int r;\n"; "-1"
8207 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8208 | RBool _ -> pr " int r;\n"; "-1"
8209 | RConstString _ | RConstOptString _ ->
8210 pr " const char *r;\n"; "NULL"
8211 | RString _ -> pr " char *r;\n"; "NULL"
8216 | RStruct (_, typ) ->
8217 pr " struct guestfs_%s *r;\n" typ; "NULL"
8218 | RStructList (_, typ) ->
8219 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8226 pr " size_t size;\n";
8230 pr " caml_enter_blocking_section ();\n";
8231 pr " r = guestfs_%s " name;
8232 generate_c_call_args ~handle:"g" style;
8234 pr " caml_leave_blocking_section ();\n";
8238 | StringList n | DeviceList n ->
8239 pr " ocaml_guestfs_free_strings (%s);\n" n;
8240 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8241 | Bool _ | Int _ | Int64 _
8242 | FileIn _ | FileOut _ -> ()
8245 pr " if (r == %s)\n" error_code;
8246 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8249 (match fst style with
8250 | RErr -> pr " rv = Val_unit;\n"
8251 | RInt _ -> pr " rv = Val_int (r);\n"
8253 pr " rv = caml_copy_int64 (r);\n"
8254 | RBool _ -> pr " rv = Val_bool (r);\n"
8256 pr " rv = caml_copy_string (r);\n"
8257 | RConstOptString _ ->
8258 pr " if (r) { /* Some string */\n";
8259 pr " v = caml_alloc (1, 0);\n";
8260 pr " v2 = caml_copy_string (r);\n";
8261 pr " Store_field (v, 0, v2);\n";
8262 pr " } else /* None */\n";
8263 pr " v = Val_int (0);\n";
8265 pr " rv = caml_copy_string (r);\n";
8268 pr " rv = caml_copy_string_array ((const char **) r);\n";
8269 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8271 | RStruct (_, typ) ->
8272 pr " rv = copy_%s (r);\n" typ;
8273 pr " guestfs_free_%s (r);\n" typ;
8274 | RStructList (_, typ) ->
8275 pr " rv = copy_%s_list (r);\n" typ;
8276 pr " guestfs_free_%s_list (r);\n" typ;
8278 pr " rv = copy_table (r);\n";
8279 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8282 pr " rv = caml_alloc_string (size);\n";
8283 pr " memcpy (String_val (rv), r, size);\n";
8286 pr " CAMLreturn (rv);\n";
8290 if List.length params > 5 then (
8291 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8292 pr "CAMLprim value ";
8293 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8294 pr "CAMLprim value\n";
8295 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8297 pr " return ocaml_guestfs_%s (argv[0]" name;
8298 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8303 ) all_functions_sorted
8305 and generate_ocaml_structure_decls () =
8308 pr "type %s = {\n" typ;
8311 | name, FString -> pr " %s : string;\n" name
8312 | name, FBuffer -> pr " %s : string;\n" name
8313 | name, FUUID -> pr " %s : string;\n" name
8314 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8315 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8316 | name, FChar -> pr " %s : char;\n" name
8317 | name, FOptPercent -> pr " %s : float option;\n" name
8323 and generate_ocaml_prototype ?(is_external = false) name style =
8324 if is_external then pr "external " else pr "val ";
8325 pr "%s : t -> " name;
8328 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8329 | OptString _ -> pr "string option -> "
8330 | StringList _ | DeviceList _ -> pr "string array -> "
8331 | Bool _ -> pr "bool -> "
8332 | Int _ -> pr "int -> "
8333 | Int64 _ -> pr "int64 -> "
8335 (match fst style with
8336 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8337 | RInt _ -> pr "int"
8338 | RInt64 _ -> pr "int64"
8339 | RBool _ -> pr "bool"
8340 | RConstString _ -> pr "string"
8341 | RConstOptString _ -> pr "string option"
8342 | RString _ | RBufferOut _ -> pr "string"
8343 | RStringList _ -> pr "string array"
8344 | RStruct (_, typ) -> pr "%s" typ
8345 | RStructList (_, typ) -> pr "%s array" typ
8346 | RHashtable _ -> pr "(string * string) list"
8348 if is_external then (
8350 if List.length (snd style) + 1 > 5 then
8351 pr "\"ocaml_guestfs_%s_byte\" " name;
8352 pr "\"ocaml_guestfs_%s\"" name
8356 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8357 and generate_perl_xs () =
8358 generate_header CStyle LGPLv2plus;
8361 #include \"EXTERN.h\"
8365 #include <guestfs.h>
8368 #define PRId64 \"lld\"
8372 my_newSVll(long long val) {
8373 #ifdef USE_64_BIT_ALL
8374 return newSViv(val);
8378 len = snprintf(buf, 100, \"%%\" PRId64, val);
8379 return newSVpv(buf, len);
8384 #define PRIu64 \"llu\"
8388 my_newSVull(unsigned long long val) {
8389 #ifdef USE_64_BIT_ALL
8390 return newSVuv(val);
8394 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8395 return newSVpv(buf, len);
8399 /* http://www.perlmonks.org/?node_id=680842 */
8401 XS_unpack_charPtrPtr (SV *arg) {
8406 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8407 croak (\"array reference expected\");
8409 av = (AV *)SvRV (arg);
8410 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8412 croak (\"malloc failed\");
8414 for (i = 0; i <= av_len (av); i++) {
8415 SV **elem = av_fetch (av, i, 0);
8417 if (!elem || !*elem)
8418 croak (\"missing element in list\");
8420 ret[i] = SvPV_nolen (*elem);
8428 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8435 RETVAL = guestfs_create ();
8437 croak (\"could not create guestfs handle\");
8438 guestfs_set_error_handler (RETVAL, NULL, NULL);
8451 fun (name, style, _, _, _, _, _) ->
8452 (match fst style with
8453 | RErr -> pr "void\n"
8454 | RInt _ -> pr "SV *\n"
8455 | RInt64 _ -> pr "SV *\n"
8456 | RBool _ -> pr "SV *\n"
8457 | RConstString _ -> pr "SV *\n"
8458 | RConstOptString _ -> pr "SV *\n"
8459 | RString _ -> pr "SV *\n"
8460 | RBufferOut _ -> pr "SV *\n"
8462 | RStruct _ | RStructList _
8464 pr "void\n" (* all lists returned implictly on the stack *)
8466 (* Call and arguments. *)
8468 generate_c_call_args ~handle:"g" ~decl:true style;
8470 pr " guestfs_h *g;\n";
8474 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8477 (* http://www.perlmonks.org/?node_id=554277
8478 * Note that the implicit handle argument means we have
8479 * to add 1 to the ST(x) operator.
8481 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8482 | StringList n | DeviceList n -> pr " char **%s;\n" n
8483 | Bool n -> pr " int %s;\n" n
8484 | Int n -> pr " int %s;\n" n
8485 | Int64 n -> pr " int64_t %s;\n" n
8488 let do_cleanups () =
8491 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8492 | Bool _ | Int _ | Int64 _
8493 | FileIn _ | FileOut _ -> ()
8494 | StringList n | DeviceList n -> pr " free (%s);\n" n
8499 (match fst style with
8504 pr " r = guestfs_%s " name;
8505 generate_c_call_args ~handle:"g" style;
8508 pr " if (r == -1)\n";
8509 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8515 pr " %s = guestfs_%s " n name;
8516 generate_c_call_args ~handle:"g" style;
8519 pr " if (%s == -1)\n" n;
8520 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8521 pr " RETVAL = newSViv (%s);\n" n;
8526 pr " int64_t %s;\n" n;
8528 pr " %s = guestfs_%s " n name;
8529 generate_c_call_args ~handle:"g" style;
8532 pr " if (%s == -1)\n" n;
8533 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8534 pr " RETVAL = my_newSVll (%s);\n" n;
8539 pr " const char *%s;\n" n;
8541 pr " %s = guestfs_%s " n name;
8542 generate_c_call_args ~handle:"g" style;
8545 pr " if (%s == NULL)\n" n;
8546 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8547 pr " RETVAL = newSVpv (%s, 0);\n" n;
8550 | RConstOptString n ->
8552 pr " const char *%s;\n" n;
8554 pr " %s = guestfs_%s " n name;
8555 generate_c_call_args ~handle:"g" style;
8558 pr " if (%s == NULL)\n" n;
8559 pr " RETVAL = &PL_sv_undef;\n";
8561 pr " RETVAL = newSVpv (%s, 0);\n" n;
8566 pr " char *%s;\n" n;
8568 pr " %s = guestfs_%s " n name;
8569 generate_c_call_args ~handle:"g" style;
8572 pr " if (%s == NULL)\n" n;
8573 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8574 pr " RETVAL = newSVpv (%s, 0);\n" n;
8575 pr " free (%s);\n" n;
8578 | RStringList n | RHashtable n ->
8580 pr " char **%s;\n" n;
8583 pr " %s = guestfs_%s " n name;
8584 generate_c_call_args ~handle:"g" style;
8587 pr " if (%s == NULL)\n" n;
8588 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8589 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8590 pr " EXTEND (SP, n);\n";
8591 pr " for (i = 0; i < n; ++i) {\n";
8592 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8593 pr " free (%s[i]);\n" n;
8595 pr " free (%s);\n" n;
8596 | RStruct (n, typ) ->
8597 let cols = cols_of_struct typ in
8598 generate_perl_struct_code typ cols name style n do_cleanups
8599 | RStructList (n, typ) ->
8600 let cols = cols_of_struct typ in
8601 generate_perl_struct_list_code typ cols name style n do_cleanups
8604 pr " char *%s;\n" n;
8605 pr " size_t size;\n";
8607 pr " %s = guestfs_%s " n name;
8608 generate_c_call_args ~handle:"g" style;
8611 pr " if (%s == NULL)\n" n;
8612 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8613 pr " RETVAL = newSVpvn (%s, size);\n" n;
8614 pr " free (%s);\n" n;
8622 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8624 pr " struct guestfs_%s_list *%s;\n" typ n;
8628 pr " %s = guestfs_%s " n name;
8629 generate_c_call_args ~handle:"g" style;
8632 pr " if (%s == NULL)\n" n;
8633 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8634 pr " EXTEND (SP, %s->len);\n" n;
8635 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8636 pr " hv = newHV ();\n";
8640 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8641 name (String.length name) n name
8643 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8644 name (String.length name) n name
8646 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8647 name (String.length name) n name n name
8648 | name, (FBytes|FUInt64) ->
8649 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8650 name (String.length name) n name
8652 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8653 name (String.length name) n name
8654 | name, (FInt32|FUInt32) ->
8655 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8656 name (String.length name) n name
8658 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8659 name (String.length name) n name
8660 | name, FOptPercent ->
8661 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8662 name (String.length name) n name
8664 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8666 pr " guestfs_free_%s_list (%s);\n" typ n
8668 and generate_perl_struct_code typ cols name style n do_cleanups =
8670 pr " struct guestfs_%s *%s;\n" typ n;
8672 pr " %s = guestfs_%s " n name;
8673 generate_c_call_args ~handle:"g" style;
8676 pr " if (%s == NULL)\n" n;
8677 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8678 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8680 fun ((name, _) as col) ->
8681 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8685 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8688 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8691 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8693 | name, (FBytes|FUInt64) ->
8694 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8697 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8699 | name, (FInt32|FUInt32) ->
8700 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8703 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8705 | name, FOptPercent ->
8706 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8709 pr " free (%s);\n" n
8711 (* Generate Sys/Guestfs.pm. *)
8712 and generate_perl_pm () =
8713 generate_header HashStyle LGPLv2plus;
8720 Sys::Guestfs - Perl bindings for libguestfs
8726 my $h = Sys::Guestfs->new ();
8727 $h->add_drive ('guest.img');
8729 $h->mount ('/dev/sda1', '/');
8730 $h->touch ('/hello');
8735 The C<Sys::Guestfs> module provides a Perl XS binding to the
8736 libguestfs API for examining and modifying virtual machine
8739 Amongst the things this is good for: making batch configuration
8740 changes to guests, getting disk used/free statistics (see also:
8741 virt-df), migrating between virtualization systems (see also:
8742 virt-p2v), performing partial backups, performing partial guest
8743 clones, cloning guests and changing registry/UUID/hostname info, and
8746 Libguestfs uses Linux kernel and qemu code, and can access any type of
8747 guest filesystem that Linux and qemu can, including but not limited
8748 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8749 schemes, qcow, qcow2, vmdk.
8751 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8752 LVs, what filesystem is in each LV, etc.). It can also run commands
8753 in the context of the guest. Also you can access filesystems over
8756 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8757 functions for using libguestfs from Perl, including integration
8762 All errors turn into calls to C<croak> (see L<Carp(3)>).
8770 package Sys::Guestfs;
8776 XSLoader::load ('Sys::Guestfs');
8778 =item $h = Sys::Guestfs->new ();
8780 Create a new guestfs handle.
8786 my $class = ref ($proto) || $proto;
8788 my $self = Sys::Guestfs::_create ();
8789 bless $self, $class;
8795 (* Actions. We only need to print documentation for these as
8796 * they are pulled in from the XS code automatically.
8799 fun (name, style, _, flags, _, _, longdesc) ->
8800 if not (List.mem NotInDocs flags) then (
8801 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8803 generate_perl_prototype name style;
8805 pr "%s\n\n" longdesc;
8806 if List.mem ProtocolLimitWarning flags then
8807 pr "%s\n\n" protocol_limit_warning;
8808 if List.mem DangerWillRobinson flags then
8809 pr "%s\n\n" danger_will_robinson;
8810 match deprecation_notice flags with
8812 | Some txt -> pr "%s\n\n" txt
8814 ) all_functions_sorted;
8826 Copyright (C) %s Red Hat Inc.
8830 Please see the file COPYING.LIB for the full license.
8836 L<http://libguestfs.org>,
8837 L<Sys::Guestfs::Lib(3)>.
8842 and generate_perl_prototype name style =
8843 (match fst style with
8851 | RBufferOut n -> pr "$%s = " n
8853 | RHashtable n -> pr "%%%s = " n
8855 | RStructList (n,_) -> pr "@%s = " n
8858 let comma = ref false in
8861 if !comma then pr ", ";
8864 | Pathname n | Device n | Dev_or_Path n | String n
8865 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8867 | StringList n | DeviceList n ->
8872 (* Generate Python C module. *)
8873 and generate_python_c () =
8874 generate_header CStyle LGPLv2plus;
8883 #include \"guestfs.h\"
8891 get_handle (PyObject *obj)
8894 assert (obj != Py_None);
8895 return ((Pyguestfs_Object *) obj)->g;
8899 put_handle (guestfs_h *g)
8903 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8906 /* This list should be freed (but not the strings) after use. */
8908 get_string_list (PyObject *obj)
8915 if (!PyList_Check (obj)) {
8916 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8920 len = PyList_Size (obj);
8921 r = malloc (sizeof (char *) * (len+1));
8923 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8927 for (i = 0; i < len; ++i)
8928 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8935 put_string_list (char * const * const argv)
8940 for (argc = 0; argv[argc] != NULL; ++argc)
8943 list = PyList_New (argc);
8944 for (i = 0; i < argc; ++i)
8945 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8951 put_table (char * const * const argv)
8953 PyObject *list, *item;
8956 for (argc = 0; argv[argc] != NULL; ++argc)
8959 list = PyList_New (argc >> 1);
8960 for (i = 0; i < argc; i += 2) {
8961 item = PyTuple_New (2);
8962 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8963 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8964 PyList_SetItem (list, i >> 1, item);
8971 free_strings (char **argv)
8975 for (argc = 0; argv[argc] != NULL; ++argc)
8981 py_guestfs_create (PyObject *self, PyObject *args)
8985 g = guestfs_create ();
8987 PyErr_SetString (PyExc_RuntimeError,
8988 \"guestfs.create: failed to allocate handle\");
8991 guestfs_set_error_handler (g, NULL, NULL);
8992 return put_handle (g);
8996 py_guestfs_close (PyObject *self, PyObject *args)
9001 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9003 g = get_handle (py_g);
9007 Py_INCREF (Py_None);
9013 let emit_put_list_function typ =
9014 pr "static PyObject *\n";
9015 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9017 pr " PyObject *list;\n";
9020 pr " list = PyList_New (%ss->len);\n" typ;
9021 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9022 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9023 pr " return list;\n";
9028 (* Structures, turned into Python dictionaries. *)
9031 pr "static PyObject *\n";
9032 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9034 pr " PyObject *dict;\n";
9036 pr " dict = PyDict_New ();\n";
9040 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9041 pr " PyString_FromString (%s->%s));\n"
9044 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9045 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9048 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9049 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9051 | name, (FBytes|FUInt64) ->
9052 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9053 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9056 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9057 pr " PyLong_FromLongLong (%s->%s));\n"
9060 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9061 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9064 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9065 pr " PyLong_FromLong (%s->%s));\n"
9067 | name, FOptPercent ->
9068 pr " if (%s->%s >= 0)\n" typ name;
9069 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9070 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9073 pr " Py_INCREF (Py_None);\n";
9074 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9077 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9078 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9080 pr " return dict;\n";
9086 (* Emit a put_TYPE_list function definition only if that function is used. *)
9089 | typ, (RStructListOnly | RStructAndList) ->
9090 (* generate the function for typ *)
9091 emit_put_list_function typ
9092 | typ, _ -> () (* empty *)
9093 ) (rstructs_used_by all_functions);
9095 (* Python wrapper functions. *)
9097 fun (name, style, _, _, _, _, _) ->
9098 pr "static PyObject *\n";
9099 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9102 pr " PyObject *py_g;\n";
9103 pr " guestfs_h *g;\n";
9104 pr " PyObject *py_r;\n";
9107 match fst style with
9108 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9109 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9110 | RConstString _ | RConstOptString _ ->
9111 pr " const char *r;\n"; "NULL"
9112 | RString _ -> pr " char *r;\n"; "NULL"
9113 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9114 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9115 | RStructList (_, typ) ->
9116 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9119 pr " size_t size;\n";
9124 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9125 pr " const char *%s;\n" n
9126 | OptString n -> pr " const char *%s;\n" n
9127 | StringList n | DeviceList n ->
9128 pr " PyObject *py_%s;\n" n;
9129 pr " char **%s;\n" n
9130 | Bool n -> pr " int %s;\n" n
9131 | Int n -> pr " int %s;\n" n
9132 | Int64 n -> pr " long long %s;\n" n
9137 (* Convert the parameters. *)
9138 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9141 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9142 | OptString _ -> pr "z"
9143 | StringList _ | DeviceList _ -> pr "O"
9144 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9146 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9147 * emulate C's int/long/long long in Python?
9150 pr ":guestfs_%s\",\n" name;
9154 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9155 | OptString n -> pr ", &%s" n
9156 | StringList n | DeviceList n -> pr ", &py_%s" n
9157 | Bool n -> pr ", &%s" n
9158 | Int n -> pr ", &%s" n
9159 | Int64 n -> pr ", &%s" n
9163 pr " return NULL;\n";
9165 pr " g = get_handle (py_g);\n";
9168 | Pathname _ | Device _ | Dev_or_Path _ | String _
9169 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9170 | StringList n | DeviceList n ->
9171 pr " %s = get_string_list (py_%s);\n" n n;
9172 pr " if (!%s) return NULL;\n" n
9177 pr " r = guestfs_%s " name;
9178 generate_c_call_args ~handle:"g" style;
9183 | Pathname _ | Device _ | Dev_or_Path _ | String _
9184 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9185 | StringList n | DeviceList n ->
9186 pr " free (%s);\n" n
9189 pr " if (r == %s) {\n" error_code;
9190 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9191 pr " return NULL;\n";
9195 (match fst style with
9197 pr " Py_INCREF (Py_None);\n";
9198 pr " py_r = Py_None;\n"
9200 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9201 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9202 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9203 | RConstOptString _ ->
9205 pr " py_r = PyString_FromString (r);\n";
9207 pr " Py_INCREF (Py_None);\n";
9208 pr " py_r = Py_None;\n";
9211 pr " py_r = PyString_FromString (r);\n";
9214 pr " py_r = put_string_list (r);\n";
9215 pr " free_strings (r);\n"
9216 | RStruct (_, typ) ->
9217 pr " py_r = put_%s (r);\n" typ;
9218 pr " guestfs_free_%s (r);\n" typ
9219 | RStructList (_, typ) ->
9220 pr " py_r = put_%s_list (r);\n" typ;
9221 pr " guestfs_free_%s_list (r);\n" typ
9223 pr " py_r = put_table (r);\n";
9224 pr " free_strings (r);\n"
9226 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9230 pr " return py_r;\n";
9235 (* Table of functions. *)
9236 pr "static PyMethodDef methods[] = {\n";
9237 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9238 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9240 fun (name, _, _, _, _, _, _) ->
9241 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9244 pr " { NULL, NULL, 0, NULL }\n";
9248 (* Init function. *)
9251 initlibguestfsmod (void)
9253 static int initialized = 0;
9255 if (initialized) return;
9256 Py_InitModule ((char *) \"libguestfsmod\", methods);
9261 (* Generate Python module. *)
9262 and generate_python_py () =
9263 generate_header HashStyle LGPLv2plus;
9266 u\"\"\"Python bindings for libguestfs
9269 g = guestfs.GuestFS ()
9270 g.add_drive (\"guest.img\")
9272 parts = g.list_partitions ()
9274 The guestfs module provides a Python binding to the libguestfs API
9275 for examining and modifying virtual machine disk images.
9277 Amongst the things this is good for: making batch configuration
9278 changes to guests, getting disk used/free statistics (see also:
9279 virt-df), migrating between virtualization systems (see also:
9280 virt-p2v), performing partial backups, performing partial guest
9281 clones, cloning guests and changing registry/UUID/hostname info, and
9284 Libguestfs uses Linux kernel and qemu code, and can access any type of
9285 guest filesystem that Linux and qemu can, including but not limited
9286 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9287 schemes, qcow, qcow2, vmdk.
9289 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9290 LVs, what filesystem is in each LV, etc.). It can also run commands
9291 in the context of the guest. Also you can access filesystems over
9294 Errors which happen while using the API are turned into Python
9295 RuntimeError exceptions.
9297 To create a guestfs handle you usually have to perform the following
9300 # Create the handle, call add_drive at least once, and possibly
9301 # several times if the guest has multiple block devices:
9302 g = guestfs.GuestFS ()
9303 g.add_drive (\"guest.img\")
9305 # Launch the qemu subprocess and wait for it to become ready:
9308 # Now you can issue commands, for example:
9313 import libguestfsmod
9316 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9318 def __init__ (self):
9319 \"\"\"Create a new libguestfs handle.\"\"\"
9320 self._o = libguestfsmod.create ()
9323 libguestfsmod.close (self._o)
9328 fun (name, style, _, flags, _, _, longdesc) ->
9330 generate_py_call_args ~handle:"self" (snd style);
9333 if not (List.mem NotInDocs flags) then (
9334 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9336 match fst style with
9337 | RErr | RInt _ | RInt64 _ | RBool _
9338 | RConstOptString _ | RConstString _
9339 | RString _ | RBufferOut _ -> doc
9341 doc ^ "\n\nThis function returns a list of strings."
9342 | RStruct (_, typ) ->
9343 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9344 | RStructList (_, typ) ->
9345 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9347 doc ^ "\n\nThis function returns a dictionary." in
9349 if List.mem ProtocolLimitWarning flags then
9350 doc ^ "\n\n" ^ protocol_limit_warning
9353 if List.mem DangerWillRobinson flags then
9354 doc ^ "\n\n" ^ danger_will_robinson
9357 match deprecation_notice flags with
9359 | Some txt -> doc ^ "\n\n" ^ txt in
9360 let doc = pod2text ~width:60 name doc in
9361 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9362 let doc = String.concat "\n " doc in
9363 pr " u\"\"\"%s\"\"\"\n" doc;
9365 pr " return libguestfsmod.%s " name;
9366 generate_py_call_args ~handle:"self._o" (snd style);
9371 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9372 and generate_py_call_args ~handle args =
9374 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9377 (* Useful if you need the longdesc POD text as plain text. Returns a
9380 * Because this is very slow (the slowest part of autogeneration),
9381 * we memoize the results.
9383 and pod2text ~width name longdesc =
9384 let key = width, name, longdesc in
9385 try Hashtbl.find pod2text_memo key
9387 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9388 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9390 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9391 let chan = open_process_in cmd in
9392 let lines = ref [] in
9394 let line = input_line chan in
9395 if i = 1 then (* discard the first line of output *)
9398 let line = triml line in
9399 lines := line :: !lines;
9402 let lines = try loop 1 with End_of_file -> List.rev !lines in
9404 (match close_process_in chan with
9407 failwithf "pod2text: process exited with non-zero status (%d)" i
9408 | WSIGNALED i | WSTOPPED i ->
9409 failwithf "pod2text: process signalled or stopped by signal %d" i
9411 Hashtbl.add pod2text_memo key lines;
9412 pod2text_memo_updated ();
9415 (* Generate ruby bindings. *)
9416 and generate_ruby_c () =
9417 generate_header CStyle LGPLv2plus;
9425 #include \"guestfs.h\"
9427 #include \"extconf.h\"
9429 /* For Ruby < 1.9 */
9431 #define RARRAY_LEN(r) (RARRAY((r))->len)
9434 static VALUE m_guestfs; /* guestfs module */
9435 static VALUE c_guestfs; /* guestfs_h handle */
9436 static VALUE e_Error; /* used for all errors */
9438 static void ruby_guestfs_free (void *p)
9441 guestfs_close ((guestfs_h *) p);
9444 static VALUE ruby_guestfs_create (VALUE m)
9448 g = guestfs_create ();
9450 rb_raise (e_Error, \"failed to create guestfs handle\");
9452 /* Don't print error messages to stderr by default. */
9453 guestfs_set_error_handler (g, NULL, NULL);
9455 /* Wrap it, and make sure the close function is called when the
9458 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9461 static VALUE ruby_guestfs_close (VALUE gv)
9464 Data_Get_Struct (gv, guestfs_h, g);
9466 ruby_guestfs_free (g);
9467 DATA_PTR (gv) = NULL;
9475 fun (name, style, _, _, _, _, _) ->
9476 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9477 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9480 pr " guestfs_h *g;\n";
9481 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9483 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9489 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9490 pr " Check_Type (%sv, T_STRING);\n" n;
9491 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9493 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9494 pr " \"%s\", \"%s\");\n" n name
9496 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9497 | StringList n | DeviceList n ->
9498 pr " char **%s;\n" n;
9499 pr " Check_Type (%sv, T_ARRAY);\n" n;
9501 pr " int i, len;\n";
9502 pr " len = RARRAY_LEN (%sv);\n" n;
9503 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9505 pr " for (i = 0; i < len; ++i) {\n";
9506 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9507 pr " %s[i] = StringValueCStr (v);\n" n;
9509 pr " %s[len] = NULL;\n" n;
9512 pr " int %s = RTEST (%sv);\n" n n
9514 pr " int %s = NUM2INT (%sv);\n" n n
9516 pr " long long %s = NUM2LL (%sv);\n" n n
9521 match fst style with
9522 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9523 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9524 | RConstString _ | RConstOptString _ ->
9525 pr " const char *r;\n"; "NULL"
9526 | RString _ -> pr " char *r;\n"; "NULL"
9527 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9528 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9529 | RStructList (_, typ) ->
9530 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9533 pr " size_t size;\n";
9537 pr " r = guestfs_%s " name;
9538 generate_c_call_args ~handle:"g" style;
9543 | Pathname _ | Device _ | Dev_or_Path _ | String _
9544 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9545 | StringList n | DeviceList n ->
9546 pr " free (%s);\n" n
9549 pr " if (r == %s)\n" error_code;
9550 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9553 (match fst style with
9555 pr " return Qnil;\n"
9556 | RInt _ | RBool _ ->
9557 pr " return INT2NUM (r);\n"
9559 pr " return ULL2NUM (r);\n"
9561 pr " return rb_str_new2 (r);\n";
9562 | RConstOptString _ ->
9564 pr " return rb_str_new2 (r);\n";
9566 pr " return Qnil;\n";
9568 pr " VALUE rv = rb_str_new2 (r);\n";
9572 pr " int i, len = 0;\n";
9573 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9574 pr " VALUE rv = rb_ary_new2 (len);\n";
9575 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9576 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9577 pr " free (r[i]);\n";
9581 | RStruct (_, typ) ->
9582 let cols = cols_of_struct typ in
9583 generate_ruby_struct_code typ cols
9584 | RStructList (_, typ) ->
9585 let cols = cols_of_struct typ in
9586 generate_ruby_struct_list_code typ cols
9588 pr " VALUE rv = rb_hash_new ();\n";
9590 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9591 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9592 pr " free (r[i]);\n";
9593 pr " free (r[i+1]);\n";
9598 pr " VALUE rv = rb_str_new (r, size);\n";
9608 /* Initialize the module. */
9609 void Init__guestfs ()
9611 m_guestfs = rb_define_module (\"Guestfs\");
9612 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9613 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9615 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9616 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9619 (* Define the rest of the methods. *)
9621 fun (name, style, _, _, _, _, _) ->
9622 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9623 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9628 (* Ruby code to return a struct. *)
9629 and generate_ruby_struct_code typ cols =
9630 pr " VALUE rv = rb_hash_new ();\n";
9634 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9636 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9638 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9639 | name, (FBytes|FUInt64) ->
9640 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9642 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9644 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9646 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9647 | name, FOptPercent ->
9648 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9649 | name, FChar -> (* XXX wrong? *)
9650 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9652 pr " guestfs_free_%s (r);\n" typ;
9655 (* Ruby code to return a struct list. *)
9656 and generate_ruby_struct_list_code typ cols =
9657 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9659 pr " for (i = 0; i < r->len; ++i) {\n";
9660 pr " VALUE hv = rb_hash_new ();\n";
9664 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9666 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
9668 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9669 | name, (FBytes|FUInt64) ->
9670 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9672 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9674 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9676 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9677 | name, FOptPercent ->
9678 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9679 | name, FChar -> (* XXX wrong? *)
9680 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9682 pr " rb_ary_push (rv, hv);\n";
9684 pr " guestfs_free_%s_list (r);\n" typ;
9687 (* Generate Java bindings GuestFS.java file. *)
9688 and generate_java_java () =
9689 generate_header CStyle LGPLv2plus;
9692 package com.redhat.et.libguestfs;
9694 import java.util.HashMap;
9695 import com.redhat.et.libguestfs.LibGuestFSException;
9696 import com.redhat.et.libguestfs.PV;
9697 import com.redhat.et.libguestfs.VG;
9698 import com.redhat.et.libguestfs.LV;
9699 import com.redhat.et.libguestfs.Stat;
9700 import com.redhat.et.libguestfs.StatVFS;
9701 import com.redhat.et.libguestfs.IntBool;
9702 import com.redhat.et.libguestfs.Dirent;
9705 * The GuestFS object is a libguestfs handle.
9709 public class GuestFS {
9710 // Load the native code.
9712 System.loadLibrary (\"guestfs_jni\");
9716 * The native guestfs_h pointer.
9721 * Create a libguestfs handle.
9723 * @throws LibGuestFSException
9725 public GuestFS () throws LibGuestFSException
9729 private native long _create () throws LibGuestFSException;
9732 * Close a libguestfs handle.
9734 * You can also leave handles to be collected by the garbage
9735 * collector, but this method ensures that the resources used
9736 * by the handle are freed up immediately. If you call any
9737 * other methods after closing the handle, you will get an
9740 * @throws LibGuestFSException
9742 public void close () throws LibGuestFSException
9748 private native void _close (long g) throws LibGuestFSException;
9750 public void finalize () throws LibGuestFSException
9758 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9759 if not (List.mem NotInDocs flags); then (
9760 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9762 if List.mem ProtocolLimitWarning flags then
9763 doc ^ "\n\n" ^ protocol_limit_warning
9766 if List.mem DangerWillRobinson flags then
9767 doc ^ "\n\n" ^ danger_will_robinson
9770 match deprecation_notice flags with
9772 | Some txt -> doc ^ "\n\n" ^ txt in
9773 let doc = pod2text ~width:60 name doc in
9774 let doc = List.map ( (* RHBZ#501883 *)
9777 | nonempty -> nonempty
9779 let doc = String.concat "\n * " doc in
9782 pr " * %s\n" shortdesc;
9785 pr " * @throws LibGuestFSException\n";
9789 generate_java_prototype ~public:true ~semicolon:false name style;
9792 pr " if (g == 0)\n";
9793 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9796 if fst style <> RErr then pr "return ";
9798 generate_java_call_args ~handle:"g" (snd style);
9802 generate_java_prototype ~privat:true ~native:true name style;
9809 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9810 and generate_java_call_args ~handle args =
9812 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9815 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9816 ?(semicolon=true) name style =
9817 if privat then pr "private ";
9818 if public then pr "public ";
9819 if native then pr "native ";
9822 (match fst style with
9823 | RErr -> pr "void ";
9824 | RInt _ -> pr "int ";
9825 | RInt64 _ -> pr "long ";
9826 | RBool _ -> pr "boolean ";
9827 | RConstString _ | RConstOptString _ | RString _
9828 | RBufferOut _ -> pr "String ";
9829 | RStringList _ -> pr "String[] ";
9830 | RStruct (_, typ) ->
9831 let name = java_name_of_struct typ in
9833 | RStructList (_, typ) ->
9834 let name = java_name_of_struct typ in
9836 | RHashtable _ -> pr "HashMap<String,String> ";
9839 if native then pr "_%s " name else pr "%s " name;
9841 let needs_comma = ref false in
9850 if !needs_comma then pr ", ";
9851 needs_comma := true;
9855 | Device n | Dev_or_Path n
9861 | StringList n | DeviceList n ->
9872 pr " throws LibGuestFSException";
9873 if semicolon then pr ";"
9875 and generate_java_struct jtyp cols () =
9876 generate_header CStyle LGPLv2plus;
9879 package com.redhat.et.libguestfs;
9882 * Libguestfs %s structure.
9894 | name, FBuffer -> pr " public String %s;\n" name
9895 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9896 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9897 | name, FChar -> pr " public char %s;\n" name
9898 | name, FOptPercent ->
9899 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9900 pr " public float %s;\n" name
9905 and generate_java_c () =
9906 generate_header CStyle LGPLv2plus;
9913 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9914 #include \"guestfs.h\"
9916 /* Note that this function returns. The exception is not thrown
9917 * until after the wrapper function returns.
9920 throw_exception (JNIEnv *env, const char *msg)
9923 cl = (*env)->FindClass (env,
9924 \"com/redhat/et/libguestfs/LibGuestFSException\");
9925 (*env)->ThrowNew (env, cl, msg);
9928 JNIEXPORT jlong JNICALL
9929 Java_com_redhat_et_libguestfs_GuestFS__1create
9930 (JNIEnv *env, jobject obj)
9934 g = guestfs_create ();
9936 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9939 guestfs_set_error_handler (g, NULL, NULL);
9940 return (jlong) (long) g;
9943 JNIEXPORT void JNICALL
9944 Java_com_redhat_et_libguestfs_GuestFS__1close
9945 (JNIEnv *env, jobject obj, jlong jg)
9947 guestfs_h *g = (guestfs_h *) (long) jg;
9954 fun (name, style, _, _, _, _, _) ->
9956 (match fst style with
9957 | RErr -> pr "void ";
9958 | RInt _ -> pr "jint ";
9959 | RInt64 _ -> pr "jlong ";
9960 | RBool _ -> pr "jboolean ";
9961 | RConstString _ | RConstOptString _ | RString _
9962 | RBufferOut _ -> pr "jstring ";
9963 | RStruct _ | RHashtable _ ->
9965 | RStringList _ | RStructList _ ->
9969 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9970 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9972 pr " (JNIEnv *env, jobject obj, jlong jg";
9976 | Device n | Dev_or_Path n
9981 pr ", jstring j%s" n
9982 | StringList n | DeviceList n ->
9983 pr ", jobjectArray j%s" n
9985 pr ", jboolean j%s" n
9993 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9994 let error_code, no_ret =
9995 match fst style with
9996 | RErr -> pr " int r;\n"; "-1", ""
9998 | RInt _ -> pr " int r;\n"; "-1", "0"
9999 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10000 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10001 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10003 pr " jstring jr;\n";
10004 pr " char *r;\n"; "NULL", "NULL"
10006 pr " jobjectArray jr;\n";
10007 pr " int r_len;\n";
10008 pr " jclass cl;\n";
10009 pr " jstring jstr;\n";
10010 pr " char **r;\n"; "NULL", "NULL"
10011 | RStruct (_, typ) ->
10012 pr " jobject jr;\n";
10013 pr " jclass cl;\n";
10014 pr " jfieldID fl;\n";
10015 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10016 | RStructList (_, typ) ->
10017 pr " jobjectArray jr;\n";
10018 pr " jclass cl;\n";
10019 pr " jfieldID fl;\n";
10020 pr " jobject jfl;\n";
10021 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10022 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10024 pr " jstring jr;\n";
10026 pr " size_t size;\n";
10031 | Device n | Dev_or_Path n
10036 pr " const char *%s;\n" n
10037 | StringList n | DeviceList n ->
10038 pr " int %s_len;\n" n;
10039 pr " const char **%s;\n" n
10044 pr " int64_t %s;\n" n
10048 (match fst style with
10049 | RStringList _ | RStructList _ -> true
10050 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10051 | RConstOptString _
10052 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10053 List.exists (function
10054 | StringList _ -> true
10055 | DeviceList _ -> true
10056 | _ -> false) (snd style) in
10062 (* Get the parameters. *)
10066 | Device n | Dev_or_Path n
10070 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10072 (* This is completely undocumented, but Java null becomes
10073 * a NULL parameter.
10075 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10076 | StringList n | DeviceList n ->
10077 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10078 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10079 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10080 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10082 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10084 pr " %s[%s_len] = NULL;\n" n n;
10088 pr " %s = j%s;\n" n n
10091 (* Make the call. *)
10092 pr " r = guestfs_%s " name;
10093 generate_c_call_args ~handle:"g" style;
10096 (* Release the parameters. *)
10100 | Device n | Dev_or_Path n
10104 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10106 pr " if (j%s)\n" n;
10107 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10108 | StringList n | DeviceList n ->
10109 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10110 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10112 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10114 pr " free (%s);\n" n
10120 (* Check for errors. *)
10121 pr " if (r == %s) {\n" error_code;
10122 pr " throw_exception (env, guestfs_last_error (g));\n";
10123 pr " return %s;\n" no_ret;
10126 (* Return value. *)
10127 (match fst style with
10129 | RInt _ -> pr " return (jint) r;\n"
10130 | RBool _ -> pr " return (jboolean) r;\n"
10131 | RInt64 _ -> pr " return (jlong) r;\n"
10132 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10133 | RConstOptString _ ->
10134 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10136 pr " jr = (*env)->NewStringUTF (env, r);\n";
10140 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10141 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10142 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10143 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10144 pr " for (i = 0; i < r_len; ++i) {\n";
10145 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10146 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10147 pr " free (r[i]);\n";
10151 | RStruct (_, typ) ->
10152 let jtyp = java_name_of_struct typ in
10153 let cols = cols_of_struct typ in
10154 generate_java_struct_return typ jtyp cols
10155 | RStructList (_, typ) ->
10156 let jtyp = java_name_of_struct typ in
10157 let cols = cols_of_struct typ in
10158 generate_java_struct_list_return typ jtyp cols
10161 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10162 pr " return NULL;\n"
10164 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10173 and generate_java_struct_return typ jtyp cols =
10174 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10175 pr " jr = (*env)->AllocObject (env, cl);\n";
10179 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10180 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10183 pr " char s[33];\n";
10184 pr " memcpy (s, r->%s, 32);\n" name;
10185 pr " s[32] = 0;\n";
10186 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10187 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10191 pr " int len = r->%s_len;\n" name;
10192 pr " char s[len+1];\n";
10193 pr " memcpy (s, r->%s, len);\n" name;
10194 pr " s[len] = 0;\n";
10195 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10196 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10198 | name, (FBytes|FUInt64|FInt64) ->
10199 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10200 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10201 | name, (FUInt32|FInt32) ->
10202 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10203 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10204 | name, FOptPercent ->
10205 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10206 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10208 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10209 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10214 and generate_java_struct_list_return typ jtyp cols =
10215 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10216 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10217 pr " for (i = 0; i < r->len; ++i) {\n";
10218 pr " jfl = (*env)->AllocObject (env, cl);\n";
10222 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10223 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10226 pr " char s[33];\n";
10227 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10228 pr " s[32] = 0;\n";
10229 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10230 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10234 pr " int len = r->val[i].%s_len;\n" name;
10235 pr " char s[len+1];\n";
10236 pr " memcpy (s, r->val[i].%s, len);\n" name;
10237 pr " s[len] = 0;\n";
10238 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10239 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10241 | name, (FBytes|FUInt64|FInt64) ->
10242 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10243 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10244 | name, (FUInt32|FInt32) ->
10245 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10246 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10247 | name, FOptPercent ->
10248 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10249 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10251 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10252 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10254 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10256 pr " guestfs_free_%s_list (r);\n" typ;
10259 and generate_java_makefile_inc () =
10260 generate_header HashStyle GPLv2plus;
10262 pr "java_built_sources = \\\n";
10265 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10267 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10269 and generate_haskell_hs () =
10270 generate_header HaskellStyle LGPLv2plus;
10272 (* XXX We only know how to generate partial FFI for Haskell
10273 * at the moment. Please help out!
10275 let can_generate style =
10279 | RInt64 _, _ -> true
10281 | RConstString _, _
10282 | RConstOptString _, _
10288 | RBufferOut _, _ -> false in
10291 {-# INCLUDE <guestfs.h> #-}
10292 {-# LANGUAGE ForeignFunctionInterface #-}
10297 (* List out the names of the actions we want to export. *)
10299 fun (name, style, _, _, _, _, _) ->
10300 if can_generate style then pr ",\n %s" name
10306 -- Unfortunately some symbols duplicate ones already present
10307 -- in Prelude. We don't know which, so we hard-code a list
10309 import Prelude hiding (truncate)
10313 import Foreign.C.Types
10315 import Control.Exception
10316 import Data.Typeable
10318 data GuestfsS = GuestfsS -- represents the opaque C struct
10319 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10320 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10322 -- XXX define properly later XXX
10326 data IntBool = IntBool
10328 data StatVFS = StatVFS
10329 data Hashtable = Hashtable
10331 foreign import ccall unsafe \"guestfs_create\" c_create
10333 foreign import ccall unsafe \"&guestfs_close\" c_close
10334 :: FunPtr (GuestfsP -> IO ())
10335 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10336 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10338 create :: IO GuestfsH
10341 c_set_error_handler p nullPtr nullPtr
10342 h <- newForeignPtr c_close p
10345 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10346 :: GuestfsP -> IO CString
10348 -- last_error :: GuestfsH -> IO (Maybe String)
10349 -- last_error h = do
10350 -- str <- withForeignPtr h (\\p -> c_last_error p)
10351 -- maybePeek peekCString str
10353 last_error :: GuestfsH -> IO (String)
10355 str <- withForeignPtr h (\\p -> c_last_error p)
10356 if (str == nullPtr)
10357 then return \"no error\"
10358 else peekCString str
10362 (* Generate wrappers for each foreign function. *)
10364 fun (name, style, _, _, _, _, _) ->
10365 if can_generate style then (
10366 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10368 generate_haskell_prototype ~handle:"GuestfsP" style;
10372 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10374 pr "%s %s = do\n" name
10375 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10377 (* Convert pointer arguments using with* functions. *)
10382 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10383 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10384 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10385 | Bool _ | Int _ | Int64 _ -> ()
10387 (* Convert integer arguments. *)
10391 | Bool n -> sprintf "(fromBool %s)" n
10392 | Int n -> sprintf "(fromIntegral %s)" n
10393 | Int64 n -> sprintf "(fromIntegral %s)" n
10394 | FileIn n | FileOut n
10395 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10397 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10398 (String.concat " " ("p" :: args));
10399 (match fst style with
10400 | RErr | RInt _ | RInt64 _ | RBool _ ->
10401 pr " if (r == -1)\n";
10403 pr " err <- last_error h\n";
10405 | RConstString _ | RConstOptString _ | RString _
10406 | RStringList _ | RStruct _
10407 | RStructList _ | RHashtable _ | RBufferOut _ ->
10408 pr " if (r == nullPtr)\n";
10410 pr " err <- last_error h\n";
10413 (match fst style with
10415 pr " else return ()\n"
10417 pr " else return (fromIntegral r)\n"
10419 pr " else return (fromIntegral r)\n"
10421 pr " else return (toBool r)\n"
10423 | RConstOptString _
10430 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10436 and generate_haskell_prototype ~handle ?(hs = false) style =
10437 pr "%s -> " handle;
10438 let string = if hs then "String" else "CString" in
10439 let int = if hs then "Int" else "CInt" in
10440 let bool = if hs then "Bool" else "CInt" in
10441 let int64 = if hs then "Integer" else "Int64" in
10445 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10446 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10447 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10448 | Bool _ -> pr "%s" bool
10449 | Int _ -> pr "%s" int
10450 | Int64 _ -> pr "%s" int
10451 | FileIn _ -> pr "%s" string
10452 | FileOut _ -> pr "%s" string
10457 (match fst style with
10458 | RErr -> if not hs then pr "CInt"
10459 | RInt _ -> pr "%s" int
10460 | RInt64 _ -> pr "%s" int64
10461 | RBool _ -> pr "%s" bool
10462 | RConstString _ -> pr "%s" string
10463 | RConstOptString _ -> pr "Maybe %s" string
10464 | RString _ -> pr "%s" string
10465 | RStringList _ -> pr "[%s]" string
10466 | RStruct (_, typ) ->
10467 let name = java_name_of_struct typ in
10469 | RStructList (_, typ) ->
10470 let name = java_name_of_struct typ in
10472 | RHashtable _ -> pr "Hashtable"
10473 | RBufferOut _ -> pr "%s" string
10477 and generate_csharp () =
10478 generate_header CPlusPlusStyle LGPLv2plus;
10480 (* XXX Make this configurable by the C# assembly users. *)
10481 let library = "libguestfs.so.0" in
10484 // These C# bindings are highly experimental at present.
10486 // Firstly they only work on Linux (ie. Mono). In order to get them
10487 // to work on Windows (ie. .Net) you would need to port the library
10488 // itself to Windows first.
10490 // The second issue is that some calls are known to be incorrect and
10491 // can cause Mono to segfault. Particularly: calls which pass or
10492 // return string[], or return any structure value. This is because
10493 // we haven't worked out the correct way to do this from C#.
10495 // The third issue is that when compiling you get a lot of warnings.
10496 // We are not sure whether the warnings are important or not.
10498 // Fourthly we do not routinely build or test these bindings as part
10499 // of the make && make check cycle, which means that regressions might
10502 // Suggestions and patches are welcome.
10506 // gmcs Libguestfs.cs
10507 // mono Libguestfs.exe
10509 // (You'll probably want to add a Test class / static main function
10510 // otherwise this won't do anything useful).
10514 using System.Runtime.InteropServices;
10515 using System.Runtime.Serialization;
10516 using System.Collections;
10520 class Error : System.ApplicationException
10522 public Error (string message) : base (message) {}
10523 protected Error (SerializationInfo info, StreamingContext context) {}
10530 [DllImport (\"%s\")]
10531 static extern IntPtr guestfs_create ();
10535 _handle = guestfs_create ();
10536 if (_handle == IntPtr.Zero)
10537 throw new Error (\"could not create guestfs handle\");
10540 [DllImport (\"%s\")]
10541 static extern void guestfs_close (IntPtr h);
10545 guestfs_close (_handle);
10548 [DllImport (\"%s\")]
10549 static extern string guestfs_last_error (IntPtr h);
10551 " library library library;
10553 (* Generate C# structure bindings. We prefix struct names with
10554 * underscore because C# cannot have conflicting struct names and
10555 * method names (eg. "class stat" and "stat").
10559 pr " [StructLayout (LayoutKind.Sequential)]\n";
10560 pr " public class _%s {\n" typ;
10563 | name, FChar -> pr " char %s;\n" name
10564 | name, FString -> pr " string %s;\n" name
10566 pr " uint %s_len;\n" name;
10567 pr " string %s;\n" name
10569 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10570 pr " string %s;\n" name
10571 | name, FUInt32 -> pr " uint %s;\n" name
10572 | name, FInt32 -> pr " int %s;\n" name
10573 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10574 | name, FInt64 -> pr " long %s;\n" name
10575 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10581 (* Generate C# function bindings. *)
10583 fun (name, style, _, _, _, shortdesc, _) ->
10584 let rec csharp_return_type () =
10585 match fst style with
10587 | RBool n -> "bool"
10589 | RInt64 n -> "long"
10591 | RConstOptString n
10593 | RBufferOut n -> "string"
10594 | RStruct (_,n) -> "_" ^ n
10595 | RHashtable n -> "Hashtable"
10596 | RStringList n -> "string[]"
10597 | RStructList (_,n) -> sprintf "_%s[]" n
10599 and c_return_type () =
10600 match fst style with
10604 | RInt64 _ -> "long"
10606 | RConstOptString _
10608 | RBufferOut _ -> "string"
10609 | RStruct (_,n) -> "_" ^ n
10611 | RStringList _ -> "string[]"
10612 | RStructList (_,n) -> sprintf "_%s[]" n
10614 and c_error_comparison () =
10615 match fst style with
10619 | RInt64 _ -> "== -1"
10621 | RConstOptString _
10627 | RStructList (_,_) -> "== null"
10629 and generate_extern_prototype () =
10630 pr " static extern %s guestfs_%s (IntPtr h"
10631 (c_return_type ()) name;
10634 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10635 | FileIn n | FileOut n ->
10636 pr ", [In] string %s" n
10637 | StringList n | DeviceList n ->
10638 pr ", [In] string[] %s" n
10648 and generate_public_prototype () =
10649 pr " public %s %s (" (csharp_return_type ()) name;
10650 let comma = ref false in
10652 if !comma then pr ", ";
10657 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10658 | FileIn n | FileOut n ->
10659 next (); pr "string %s" n
10660 | StringList n | DeviceList n ->
10661 next (); pr "string[] %s" n
10663 next (); pr "bool %s" n
10665 next (); pr "int %s" n
10667 next (); pr "long %s" n
10671 and generate_call () =
10672 pr "guestfs_%s (_handle" name;
10673 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10677 pr " [DllImport (\"%s\")]\n" library;
10678 generate_extern_prototype ();
10680 pr " /// <summary>\n";
10681 pr " /// %s\n" shortdesc;
10682 pr " /// </summary>\n";
10683 generate_public_prototype ();
10685 pr " %s r;\n" (c_return_type ());
10688 pr " if (r %s)\n" (c_error_comparison ());
10689 pr " throw new Error (guestfs_last_error (_handle));\n";
10690 (match fst style with
10693 pr " return r != 0 ? true : false;\n"
10695 pr " Hashtable rr = new Hashtable ();\n";
10696 pr " for (int i = 0; i < r.Length; i += 2)\n";
10697 pr " rr.Add (r[i], r[i+1]);\n";
10699 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10700 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10706 ) all_functions_sorted;
10712 and generate_bindtests () =
10713 generate_header CStyle LGPLv2plus;
10717 #include <stdlib.h>
10718 #include <inttypes.h>
10719 #include <string.h>
10721 #include \"guestfs.h\"
10722 #include \"guestfs-internal.h\"
10723 #include \"guestfs-internal-actions.h\"
10724 #include \"guestfs_protocol.h\"
10726 #define error guestfs_error
10727 #define safe_calloc guestfs_safe_calloc
10728 #define safe_malloc guestfs_safe_malloc
10731 print_strings (char *const *argv)
10736 for (argc = 0; argv[argc] != NULL; ++argc) {
10737 if (argc > 0) printf (\", \");
10738 printf (\"\\\"%%s\\\"\", argv[argc]);
10743 /* The test0 function prints its parameters to stdout. */
10747 match test_functions with
10748 | [] -> assert false
10749 | test0 :: tests -> test0, tests in
10752 let (name, style, _, _, _, _, _) = test0 in
10753 generate_prototype ~extern:false ~semicolon:false ~newline:true
10754 ~handle:"g" ~prefix:"guestfs__" name style;
10759 | Device n | Dev_or_Path n
10762 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10763 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10764 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10765 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10766 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10767 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10769 pr " /* Java changes stdout line buffering so we need this: */\n";
10770 pr " fflush (stdout);\n";
10776 fun (name, style, _, _, _, _, _) ->
10777 if String.sub name (String.length name - 3) 3 <> "err" then (
10778 pr "/* Test normal return. */\n";
10779 generate_prototype ~extern:false ~semicolon:false ~newline:true
10780 ~handle:"g" ~prefix:"guestfs__" name style;
10782 (match fst style with
10787 pr " sscanf (val, \"%%d\", &r);\n";
10790 pr " int64_t r;\n";
10791 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10794 pr " return STREQ (val, \"true\");\n"
10796 | RConstOptString _ ->
10797 (* Can't return the input string here. Return a static
10798 * string so we ensure we get a segfault if the caller
10799 * tries to free it.
10801 pr " return \"static string\";\n"
10803 pr " return strdup (val);\n"
10805 pr " char **strs;\n";
10807 pr " sscanf (val, \"%%d\", &n);\n";
10808 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10809 pr " for (i = 0; i < n; ++i) {\n";
10810 pr " strs[i] = safe_malloc (g, 16);\n";
10811 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10813 pr " strs[n] = NULL;\n";
10814 pr " return strs;\n"
10815 | RStruct (_, typ) ->
10816 pr " struct guestfs_%s *r;\n" typ;
10817 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10819 | RStructList (_, typ) ->
10820 pr " struct guestfs_%s_list *r;\n" typ;
10821 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10822 pr " sscanf (val, \"%%d\", &r->len);\n";
10823 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10826 pr " char **strs;\n";
10828 pr " sscanf (val, \"%%d\", &n);\n";
10829 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10830 pr " for (i = 0; i < n; ++i) {\n";
10831 pr " strs[i*2] = safe_malloc (g, 16);\n";
10832 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10833 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10834 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10836 pr " strs[n*2] = NULL;\n";
10837 pr " return strs;\n"
10839 pr " return strdup (val);\n"
10844 pr "/* Test error return. */\n";
10845 generate_prototype ~extern:false ~semicolon:false ~newline:true
10846 ~handle:"g" ~prefix:"guestfs__" name style;
10848 pr " error (g, \"error\");\n";
10849 (match fst style with
10850 | RErr | RInt _ | RInt64 _ | RBool _ ->
10852 | RConstString _ | RConstOptString _
10853 | RString _ | RStringList _ | RStruct _
10857 pr " return NULL;\n"
10864 and generate_ocaml_bindtests () =
10865 generate_header OCamlStyle GPLv2plus;
10869 let g = Guestfs.create () in
10873 String.concat " " (
10876 | CallString s -> "\"" ^ s ^ "\""
10877 | CallOptString None -> "None"
10878 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10879 | CallStringList xs ->
10880 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10881 | CallInt i when i >= 0 -> string_of_int i
10882 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10883 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10884 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10885 | CallBool b -> string_of_bool b
10890 generate_lang_bindtests (
10891 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10894 pr "print_endline \"EOF\"\n"
10896 and generate_perl_bindtests () =
10897 pr "#!/usr/bin/perl -w\n";
10898 generate_header HashStyle GPLv2plus;
10905 my $g = Sys::Guestfs->new ();
10909 String.concat ", " (
10912 | CallString s -> "\"" ^ s ^ "\""
10913 | CallOptString None -> "undef"
10914 | CallOptString (Some s) -> sprintf "\"%s\"" s
10915 | CallStringList xs ->
10916 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10917 | CallInt i -> string_of_int i
10918 | CallInt64 i -> Int64.to_string i
10919 | CallBool b -> if b then "1" else "0"
10924 generate_lang_bindtests (
10925 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10928 pr "print \"EOF\\n\"\n"
10930 and generate_python_bindtests () =
10931 generate_header HashStyle GPLv2plus;
10936 g = guestfs.GuestFS ()
10940 String.concat ", " (
10943 | CallString s -> "\"" ^ s ^ "\""
10944 | CallOptString None -> "None"
10945 | CallOptString (Some s) -> sprintf "\"%s\"" s
10946 | CallStringList xs ->
10947 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10948 | CallInt i -> string_of_int i
10949 | CallInt64 i -> Int64.to_string i
10950 | CallBool b -> if b then "1" else "0"
10955 generate_lang_bindtests (
10956 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10959 pr "print \"EOF\"\n"
10961 and generate_ruby_bindtests () =
10962 generate_header HashStyle GPLv2plus;
10967 g = Guestfs::create()
10971 String.concat ", " (
10974 | CallString s -> "\"" ^ s ^ "\""
10975 | CallOptString None -> "nil"
10976 | CallOptString (Some s) -> sprintf "\"%s\"" s
10977 | CallStringList xs ->
10978 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10979 | CallInt i -> string_of_int i
10980 | CallInt64 i -> Int64.to_string i
10981 | CallBool b -> string_of_bool b
10986 generate_lang_bindtests (
10987 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10990 pr "print \"EOF\\n\"\n"
10992 and generate_java_bindtests () =
10993 generate_header CStyle GPLv2plus;
10996 import com.redhat.et.libguestfs.*;
10998 public class Bindtests {
10999 public static void main (String[] argv)
11002 GuestFS g = new GuestFS ();
11006 String.concat ", " (
11009 | CallString s -> "\"" ^ s ^ "\""
11010 | CallOptString None -> "null"
11011 | CallOptString (Some s) -> sprintf "\"%s\"" s
11012 | CallStringList xs ->
11014 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11015 | CallInt i -> string_of_int i
11016 | CallInt64 i -> Int64.to_string i
11017 | CallBool b -> string_of_bool b
11022 generate_lang_bindtests (
11023 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11027 System.out.println (\"EOF\");
11029 catch (Exception exn) {
11030 System.err.println (exn);
11037 and generate_haskell_bindtests () =
11038 generate_header HaskellStyle GPLv2plus;
11041 module Bindtests where
11042 import qualified Guestfs
11045 g <- Guestfs.create
11049 String.concat " " (
11052 | CallString s -> "\"" ^ s ^ "\""
11053 | CallOptString None -> "Nothing"
11054 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11055 | CallStringList xs ->
11056 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11057 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11058 | CallInt i -> string_of_int i
11059 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11060 | CallInt64 i -> Int64.to_string i
11061 | CallBool true -> "True"
11062 | CallBool false -> "False"
11067 generate_lang_bindtests (
11068 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11071 pr " putStrLn \"EOF\"\n"
11073 (* Language-independent bindings tests - we do it this way to
11074 * ensure there is parity in testing bindings across all languages.
11076 and generate_lang_bindtests call =
11077 call "test0" [CallString "abc"; CallOptString (Some "def");
11078 CallStringList []; CallBool false;
11079 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11080 call "test0" [CallString "abc"; CallOptString None;
11081 CallStringList []; CallBool false;
11082 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083 call "test0" [CallString ""; CallOptString (Some "def");
11084 CallStringList []; CallBool false;
11085 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086 call "test0" [CallString ""; CallOptString (Some "");
11087 CallStringList []; CallBool false;
11088 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089 call "test0" [CallString "abc"; CallOptString (Some "def");
11090 CallStringList ["1"]; CallBool false;
11091 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092 call "test0" [CallString "abc"; CallOptString (Some "def");
11093 CallStringList ["1"; "2"]; CallBool false;
11094 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095 call "test0" [CallString "abc"; CallOptString (Some "def");
11096 CallStringList ["1"]; CallBool true;
11097 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11098 call "test0" [CallString "abc"; CallOptString (Some "def");
11099 CallStringList ["1"]; CallBool false;
11100 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11101 call "test0" [CallString "abc"; CallOptString (Some "def");
11102 CallStringList ["1"]; CallBool false;
11103 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11104 call "test0" [CallString "abc"; CallOptString (Some "def");
11105 CallStringList ["1"]; CallBool false;
11106 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11107 call "test0" [CallString "abc"; CallOptString (Some "def");
11108 CallStringList ["1"]; CallBool false;
11109 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11110 call "test0" [CallString "abc"; CallOptString (Some "def");
11111 CallStringList ["1"]; CallBool false;
11112 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11113 call "test0" [CallString "abc"; CallOptString (Some "def");
11114 CallStringList ["1"]; CallBool false;
11115 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11117 (* XXX Add here tests of the return and error functions. *)
11119 (* Code to generator bindings for virt-inspector. Currently only
11120 * implemented for OCaml code (for virt-p2v 2.0).
11122 let rng_input = "inspector/virt-inspector.rng"
11124 (* Read the input file and parse it into internal structures. This is
11125 * by no means a complete RELAX NG parser, but is just enough to be
11126 * able to parse the specific input file.
11129 | Element of string * rng list (* <element name=name/> *)
11130 | Attribute of string * rng list (* <attribute name=name/> *)
11131 | Interleave of rng list (* <interleave/> *)
11132 | ZeroOrMore of rng (* <zeroOrMore/> *)
11133 | OneOrMore of rng (* <oneOrMore/> *)
11134 | Optional of rng (* <optional/> *)
11135 | Choice of string list (* <choice><value/>*</choice> *)
11136 | Value of string (* <value>str</value> *)
11137 | Text (* <text/> *)
11139 let rec string_of_rng = function
11140 | Element (name, xs) ->
11141 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11142 | Attribute (name, xs) ->
11143 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11144 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11145 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11146 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11147 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11148 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11149 | Value value -> "Value \"" ^ value ^ "\""
11152 and string_of_rng_list xs =
11153 String.concat ", " (List.map string_of_rng xs)
11155 let rec parse_rng ?defines context = function
11157 | Xml.Element ("element", ["name", name], children) :: rest ->
11158 Element (name, parse_rng ?defines context children)
11159 :: parse_rng ?defines context rest
11160 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11161 Attribute (name, parse_rng ?defines context children)
11162 :: parse_rng ?defines context rest
11163 | Xml.Element ("interleave", [], children) :: rest ->
11164 Interleave (parse_rng ?defines context children)
11165 :: parse_rng ?defines context rest
11166 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11167 let rng = parse_rng ?defines context [child] in
11169 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11171 failwithf "%s: <zeroOrMore> contains more than one child element"
11174 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11175 let rng = parse_rng ?defines context [child] in
11177 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11179 failwithf "%s: <oneOrMore> contains more than one child element"
11182 | Xml.Element ("optional", [], [child]) :: rest ->
11183 let rng = parse_rng ?defines context [child] in
11185 | [child] -> Optional child :: parse_rng ?defines context rest
11187 failwithf "%s: <optional> contains more than one child element"
11190 | Xml.Element ("choice", [], children) :: rest ->
11191 let values = List.map (
11192 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11194 failwithf "%s: can't handle anything except <value> in <choice>"
11198 :: parse_rng ?defines context rest
11199 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11200 Value value :: parse_rng ?defines context rest
11201 | Xml.Element ("text", [], []) :: rest ->
11202 Text :: parse_rng ?defines context rest
11203 | Xml.Element ("ref", ["name", name], []) :: rest ->
11204 (* Look up the reference. Because of limitations in this parser,
11205 * we can't handle arbitrarily nested <ref> yet. You can only
11206 * use <ref> from inside <start>.
11208 (match defines with
11210 failwithf "%s: contains <ref>, but no refs are defined yet" context
11212 let rng = StringMap.find name map in
11213 rng @ parse_rng ?defines context rest
11216 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11219 let xml = Xml.parse_file rng_input in
11221 | Xml.Element ("grammar", _,
11222 Xml.Element ("start", _, gram) :: defines) ->
11223 (* The <define/> elements are referenced in the <start> section,
11224 * so build a map of those first.
11226 let defines = List.fold_left (
11228 function Xml.Element ("define", ["name", name], defn) ->
11229 StringMap.add name defn map
11231 failwithf "%s: expected <define name=name/>" rng_input
11232 ) StringMap.empty defines in
11233 let defines = StringMap.mapi parse_rng defines in
11235 (* Parse the <start> clause, passing the defines. *)
11236 parse_rng ~defines "<start>" gram
11238 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11241 let name_of_field = function
11242 | Element (name, _) | Attribute (name, _)
11243 | ZeroOrMore (Element (name, _))
11244 | OneOrMore (Element (name, _))
11245 | Optional (Element (name, _)) -> name
11246 | Optional (Attribute (name, _)) -> name
11247 | Text -> (* an unnamed field in an element *)
11250 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11252 (* At the moment this function only generates OCaml types. However we
11253 * should parameterize it later so it can generate types/structs in a
11254 * variety of languages.
11256 let generate_types xs =
11257 (* A simple type is one that can be printed out directly, eg.
11258 * "string option". A complex type is one which has a name and has
11259 * to be defined via another toplevel definition, eg. a struct.
11261 * generate_type generates code for either simple or complex types.
11262 * In the simple case, it returns the string ("string option"). In
11263 * the complex case, it returns the name ("mountpoint"). In the
11264 * complex case it has to print out the definition before returning,
11265 * so it should only be called when we are at the beginning of a
11266 * new line (BOL context).
11268 let rec generate_type = function
11269 | Text -> (* string *)
11271 | Choice values -> (* [`val1|`val2|...] *)
11272 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11273 | ZeroOrMore rng -> (* <rng> list *)
11274 let t, is_simple = generate_type rng in
11275 t ^ " list (* 0 or more *)", is_simple
11276 | OneOrMore rng -> (* <rng> list *)
11277 let t, is_simple = generate_type rng in
11278 t ^ " list (* 1 or more *)", is_simple
11279 (* virt-inspector hack: bool *)
11280 | Optional (Attribute (name, [Value "1"])) ->
11282 | Optional rng -> (* <rng> list *)
11283 let t, is_simple = generate_type rng in
11284 t ^ " option", is_simple
11285 (* type name = { fields ... } *)
11286 | Element (name, fields) when is_attrs_interleave fields ->
11287 generate_type_struct name (get_attrs_interleave fields)
11288 | Element (name, [field]) (* type name = field *)
11289 | Attribute (name, [field]) ->
11290 let t, is_simple = generate_type field in
11291 if is_simple then (t, true)
11293 pr "type %s = %s\n" name t;
11296 | Element (name, fields) -> (* type name = { fields ... } *)
11297 generate_type_struct name fields
11299 failwithf "generate_type failed at: %s" (string_of_rng rng)
11301 and is_attrs_interleave = function
11302 | [Interleave _] -> true
11303 | Attribute _ :: fields -> is_attrs_interleave fields
11304 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11307 and get_attrs_interleave = function
11308 | [Interleave fields] -> fields
11309 | ((Attribute _) as field) :: fields
11310 | ((Optional (Attribute _)) as field) :: fields ->
11311 field :: get_attrs_interleave fields
11312 | _ -> assert false
11314 and generate_types xs =
11315 List.iter (fun x -> ignore (generate_type x)) xs
11317 and generate_type_struct name fields =
11318 (* Calculate the types of the fields first. We have to do this
11319 * before printing anything so we are still in BOL context.
11321 let types = List.map fst (List.map generate_type fields) in
11323 (* Special case of a struct containing just a string and another
11324 * field. Turn it into an assoc list.
11327 | ["string"; other] ->
11328 let fname1, fname2 =
11330 | [f1; f2] -> name_of_field f1, name_of_field f2
11331 | _ -> assert false in
11332 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11336 pr "type %s = {\n" name;
11338 fun (field, ftype) ->
11339 let fname = name_of_field field in
11340 pr " %s_%s : %s;\n" name fname ftype
11341 ) (List.combine fields types);
11343 (* Return the name of this type, and
11344 * false because it's not a simple type.
11351 let generate_parsers xs =
11352 (* As for generate_type above, generate_parser makes a parser for
11353 * some type, and returns the name of the parser it has generated.
11354 * Because it (may) need to print something, it should always be
11355 * called in BOL context.
11357 let rec generate_parser = function
11358 | Text -> (* string *)
11359 "string_child_or_empty"
11360 | Choice values -> (* [`val1|`val2|...] *)
11361 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11363 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11364 | ZeroOrMore rng -> (* <rng> list *)
11365 let pa = generate_parser rng in
11366 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11367 | OneOrMore rng -> (* <rng> list *)
11368 let pa = generate_parser rng in
11369 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11370 (* virt-inspector hack: bool *)
11371 | Optional (Attribute (name, [Value "1"])) ->
11372 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11373 | Optional rng -> (* <rng> list *)
11374 let pa = generate_parser rng in
11375 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11376 (* type name = { fields ... } *)
11377 | Element (name, fields) when is_attrs_interleave fields ->
11378 generate_parser_struct name (get_attrs_interleave fields)
11379 | Element (name, [field]) -> (* type name = field *)
11380 let pa = generate_parser field in
11381 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11382 pr "let %s =\n" parser_name;
11384 pr "let parse_%s = %s\n" name parser_name;
11386 | Attribute (name, [field]) ->
11387 let pa = generate_parser field in
11388 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11389 pr "let %s =\n" parser_name;
11391 pr "let parse_%s = %s\n" name parser_name;
11393 | Element (name, fields) -> (* type name = { fields ... } *)
11394 generate_parser_struct name ([], fields)
11396 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11398 and is_attrs_interleave = function
11399 | [Interleave _] -> true
11400 | Attribute _ :: fields -> is_attrs_interleave fields
11401 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11404 and get_attrs_interleave = function
11405 | [Interleave fields] -> [], fields
11406 | ((Attribute _) as field) :: fields
11407 | ((Optional (Attribute _)) as field) :: fields ->
11408 let attrs, interleaves = get_attrs_interleave fields in
11409 (field :: attrs), interleaves
11410 | _ -> assert false
11412 and generate_parsers xs =
11413 List.iter (fun x -> ignore (generate_parser x)) xs
11415 and generate_parser_struct name (attrs, interleaves) =
11416 (* Generate parsers for the fields first. We have to do this
11417 * before printing anything so we are still in BOL context.
11419 let fields = attrs @ interleaves in
11420 let pas = List.map generate_parser fields in
11422 (* Generate an intermediate tuple from all the fields first.
11423 * If the type is just a string + another field, then we will
11424 * return this directly, otherwise it is turned into a record.
11426 * RELAX NG note: This code treats <interleave> and plain lists of
11427 * fields the same. In other words, it doesn't bother enforcing
11428 * any ordering of fields in the XML.
11430 pr "let parse_%s x =\n" name;
11431 pr " let t = (\n ";
11432 let comma = ref false in
11435 if !comma then pr ",\n ";
11438 | Optional (Attribute (fname, [field])), pa ->
11440 | Optional (Element (fname, [field])), pa ->
11441 pr "%s (optional_child %S x)" pa fname
11442 | Attribute (fname, [Text]), _ ->
11443 pr "attribute %S x" fname
11444 | (ZeroOrMore _ | OneOrMore _), pa ->
11449 let fname = name_of_field field in
11450 pr "%s (child %S x)" pa fname
11451 ) (List.combine fields pas);
11455 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11459 pr " (Obj.magic t : %s)\n" name
11463 | (Optional (Attribute (fname, [field])), pa) ->
11464 pr " %s_%s =\n" name fname;
11466 | (Optional (Element (fname, [field])), pa) ->
11467 pr " %s_%s =\n" name fname;
11468 pr " (let x = optional_child %S x in\n" fname;
11471 let fname = name_of_field field in
11472 pr " %s_%s =\n" name fname;
11473 pr " (let x = child %S x in\n" fname;
11475 ) (List.combine fields pas);
11479 sprintf "parse_%s" name
11482 generate_parsers xs
11484 (* Generate ocaml/guestfs_inspector.mli. *)
11485 let generate_ocaml_inspector_mli () =
11486 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11489 (** This is an OCaml language binding to the external [virt-inspector]
11492 For more information, please read the man page [virt-inspector(1)].
11497 generate_types grammar;
11498 pr "(** The nested information returned from the {!inspect} function. *)\n";
11502 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11503 (** To inspect a libvirt domain called [name], pass a singleton
11504 list: [inspect [name]]. When using libvirt only, you may
11505 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11507 To inspect a disk image or images, pass a list of the filenames
11508 of the disk images: [inspect filenames]
11510 This function inspects the given guest or disk images and
11511 returns a list of operating system(s) found and a large amount
11512 of information about them. In the vast majority of cases,
11513 a virtual machine only contains a single operating system.
11515 If the optional [~xml] parameter is given, then this function
11516 skips running the external virt-inspector program and just
11517 parses the given XML directly (which is expected to be XML
11518 produced from a previous run of virt-inspector). The list of
11519 names and connect URI are ignored in this case.
11521 This function can throw a wide variety of exceptions, for example
11522 if the external virt-inspector program cannot be found, or if
11523 it doesn't generate valid XML.
11527 (* Generate ocaml/guestfs_inspector.ml. *)
11528 let generate_ocaml_inspector_ml () =
11529 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11534 generate_types grammar;
11538 (* Misc functions which are used by the parser code below. *)
11539 let first_child = function
11540 | Xml.Element (_, _, c::_) -> c
11541 | Xml.Element (name, _, []) ->
11542 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11543 | Xml.PCData str ->
11544 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11546 let string_child_or_empty = function
11547 | Xml.Element (_, _, [Xml.PCData s]) -> s
11548 | Xml.Element (_, _, []) -> \"\"
11549 | Xml.Element (x, _, _) ->
11550 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11552 | Xml.PCData str ->
11553 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11555 let optional_child name xml =
11556 let children = Xml.children xml in
11558 Some (List.find (function
11559 | Xml.Element (n, _, _) when n = name -> true
11560 | _ -> false) children)
11564 let child name xml =
11565 match optional_child name xml with
11568 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11570 let attribute name xml =
11571 try Xml.attrib xml name
11572 with Xml.No_attribute _ ->
11573 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11577 generate_parsers grammar;
11581 (* Run external virt-inspector, then use parser to parse the XML. *)
11582 let inspect ?connect ?xml names =
11586 if names = [] then invalid_arg \"inspect: no names given\";
11587 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11588 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11590 let cmd = List.map Filename.quote cmd in
11591 let cmd = String.concat \" \" cmd in
11592 let chan = open_process_in cmd in
11593 let xml = Xml.parse_in chan in
11594 (match close_process_in chan with
11596 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11597 | WSIGNALED i | WSTOPPED i ->
11598 failwith (\"external virt-inspector command died or stopped on sig \" ^
11603 Xml.parse_string doc in
11604 parse_operatingsystems xml
11607 (* This is used to generate the src/MAX_PROC_NR file which
11608 * contains the maximum procedure number, a surrogate for the
11609 * ABI version number. See src/Makefile.am for the details.
11611 and generate_max_proc_nr () =
11612 let proc_nrs = List.map (
11613 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11614 ) daemon_functions in
11616 let max_proc_nr = List.fold_left max 0 proc_nrs in
11618 pr "%d\n" max_proc_nr
11620 let output_to filename k =
11621 let filename_new = filename ^ ".new" in
11622 chan := open_out filename_new;
11625 chan := Pervasives.stdout;
11627 (* Is the new file different from the current file? *)
11628 if Sys.file_exists filename && files_equal filename filename_new then
11629 unlink filename_new (* same, so skip it *)
11631 (* different, overwrite old one *)
11632 (try chmod filename 0o644 with Unix_error _ -> ());
11633 rename filename_new filename;
11634 chmod filename 0o444;
11635 printf "written %s\n%!" filename;
11638 let perror msg = function
11639 | Unix_error (err, _, _) ->
11640 eprintf "%s: %s\n" msg (error_message err)
11642 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11644 (* Main program. *)
11647 try openfile "HACKING" [O_RDWR] 0
11649 | Unix_error (ENOENT, _, _) ->
11651 You are probably running this from the wrong directory.
11652 Run it from the top source directory using the command
11657 perror "open: HACKING" exn;
11660 (* Acquire a lock so parallel builds won't try to run the generator
11661 * twice at the same time. Subsequent builds will wait for the first
11662 * one to finish. Note the lock is released implicitly when the
11665 (try lockf lock_fd F_LOCK 1
11667 perror "lock: HACKING" exn;
11670 check_functions ();
11672 output_to "src/guestfs_protocol.x" generate_xdr;
11673 output_to "src/guestfs-structs.h" generate_structs_h;
11674 output_to "src/guestfs-actions.h" generate_actions_h;
11675 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11676 output_to "src/guestfs-actions.c" generate_client_actions;
11677 output_to "src/guestfs-bindtests.c" generate_bindtests;
11678 output_to "src/guestfs-structs.pod" generate_structs_pod;
11679 output_to "src/guestfs-actions.pod" generate_actions_pod;
11680 output_to "src/guestfs-availability.pod" generate_availability_pod;
11681 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11682 output_to "src/libguestfs.syms" generate_linker_script;
11683 output_to "daemon/actions.h" generate_daemon_actions_h;
11684 output_to "daemon/stubs.c" generate_daemon_actions;
11685 output_to "daemon/names.c" generate_daemon_names;
11686 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11687 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11688 output_to "capitests/tests.c" generate_tests;
11689 output_to "fish/cmds.c" generate_fish_cmds;
11690 output_to "fish/completion.c" generate_fish_completion;
11691 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11692 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11693 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11694 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11695 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11696 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11697 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11698 output_to "perl/Guestfs.xs" generate_perl_xs;
11699 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11700 output_to "perl/bindtests.pl" generate_perl_bindtests;
11701 output_to "python/guestfs-py.c" generate_python_c;
11702 output_to "python/guestfs.py" generate_python_py;
11703 output_to "python/bindtests.py" generate_python_bindtests;
11704 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11705 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11706 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11710 let cols = cols_of_struct typ in
11711 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11712 output_to filename (generate_java_struct jtyp cols);
11715 output_to "java/Makefile.inc" generate_java_makefile_inc;
11716 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11717 output_to "java/Bindtests.java" generate_java_bindtests;
11718 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11719 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11720 output_to "csharp/Libguestfs.cs" generate_csharp;
11722 (* Always generate this file last, and unconditionally. It's used
11723 * by the Makefile to know when we must re-run the generator.
11725 let chan = open_out "src/stamp-generator" in
11726 fprintf chan "1\n";
11729 printf "generated %d lines of code\n" !lines