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 (* Test for RHBZ#579608, absolute symbolic links. *)
2864 InitISOFS, Always, TestOutputList (
2865 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2866 "return first 10 lines of a file",
2868 This command returns up to the first 10 lines of a file as
2869 a list of strings.");
2871 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2872 [InitISOFS, Always, TestOutputList (
2873 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2874 InitISOFS, Always, TestOutputList (
2875 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2876 InitISOFS, Always, TestOutputList (
2877 [["head_n"; "0"; "/10klines"]], [])],
2878 "return first N lines of a file",
2880 If the parameter C<nrlines> is a positive number, this returns the first
2881 C<nrlines> lines of the file C<path>.
2883 If the parameter C<nrlines> is a negative number, this returns lines
2884 from the file C<path>, excluding the last C<nrlines> lines.
2886 If the parameter C<nrlines> is zero, this returns an empty list.");
2888 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2889 [InitISOFS, Always, TestOutputList (
2890 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2891 "return last 10 lines of a file",
2893 This command returns up to the last 10 lines of a file as
2894 a list of strings.");
2896 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2897 [InitISOFS, Always, TestOutputList (
2898 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2899 InitISOFS, Always, TestOutputList (
2900 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2901 InitISOFS, Always, TestOutputList (
2902 [["tail_n"; "0"; "/10klines"]], [])],
2903 "return last N lines of a file",
2905 If the parameter C<nrlines> is a positive number, this returns the last
2906 C<nrlines> lines of the file C<path>.
2908 If the parameter C<nrlines> is a negative number, this returns lines
2909 from the file C<path>, starting with the C<-nrlines>th line.
2911 If the parameter C<nrlines> is zero, this returns an empty list.");
2913 ("df", (RString "output", []), 125, [],
2914 [], (* XXX Tricky to test because it depends on the exact format
2915 * of the 'df' command and other imponderables.
2917 "report file system disk space usage",
2919 This command runs the C<df> command to report disk space used.
2921 This command is mostly useful for interactive sessions. It
2922 is I<not> intended that you try to parse the output string.
2923 Use C<statvfs> from programs.");
2925 ("df_h", (RString "output", []), 126, [],
2926 [], (* XXX Tricky to test because it depends on the exact format
2927 * of the 'df' command and other imponderables.
2929 "report file system disk space usage (human readable)",
2931 This command runs the C<df -h> command to report disk space used
2932 in human-readable format.
2934 This command is mostly useful for interactive sessions. It
2935 is I<not> intended that you try to parse the output string.
2936 Use C<statvfs> from programs.");
2938 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2939 [InitISOFS, Always, TestOutputInt (
2940 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2941 "estimate file space usage",
2943 This command runs the C<du -s> command to estimate file space
2946 C<path> can be a file or a directory. If C<path> is a directory
2947 then the estimate includes the contents of the directory and all
2948 subdirectories (recursively).
2950 The result is the estimated size in I<kilobytes>
2951 (ie. units of 1024 bytes).");
2953 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2954 [InitISOFS, Always, TestOutputList (
2955 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2956 "list files in an initrd",
2958 This command lists out files contained in an initrd.
2960 The files are listed without any initial C</> character. The
2961 files are listed in the order they appear (not necessarily
2962 alphabetical). Directory names are listed as separate items.
2964 Old Linux kernels (2.4 and earlier) used a compressed ext2
2965 filesystem as initrd. We I<only> support the newer initramfs
2966 format (compressed cpio files).");
2968 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2970 "mount a file using the loop device",
2972 This command lets you mount C<file> (a filesystem image
2973 in a file) on a mount point. It is entirely equivalent to
2974 the command C<mount -o loop file mountpoint>.");
2976 ("mkswap", (RErr, [Device "device"]), 130, [],
2977 [InitEmpty, Always, TestRun (
2978 [["part_disk"; "/dev/sda"; "mbr"];
2979 ["mkswap"; "/dev/sda1"]])],
2980 "create a swap partition",
2982 Create a swap partition on C<device>.");
2984 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2985 [InitEmpty, Always, TestRun (
2986 [["part_disk"; "/dev/sda"; "mbr"];
2987 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2988 "create a swap partition with a label",
2990 Create a swap partition on C<device> with label C<label>.
2992 Note that you cannot attach a swap label to a block device
2993 (eg. C</dev/sda>), just to a partition. This appears to be
2994 a limitation of the kernel or swap tools.");
2996 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2997 (let uuid = uuidgen () in
2998 [InitEmpty, Always, TestRun (
2999 [["part_disk"; "/dev/sda"; "mbr"];
3000 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3001 "create a swap partition with an explicit UUID",
3003 Create a swap partition on C<device> with UUID C<uuid>.");
3005 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3006 [InitBasicFS, Always, TestOutputStruct (
3007 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3008 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3009 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3010 InitBasicFS, Always, TestOutputStruct (
3011 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3012 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3013 "make block, character or FIFO devices",
3015 This call creates block or character special devices, or
3016 named pipes (FIFOs).
3018 The C<mode> parameter should be the mode, using the standard
3019 constants. C<devmajor> and C<devminor> are the
3020 device major and minor numbers, only used when creating block
3021 and character special devices.
3023 Note that, just like L<mknod(2)>, the mode must be bitwise
3024 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3025 just creates a regular file). These constants are
3026 available in the standard Linux header files, or you can use
3027 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3028 which are wrappers around this command which bitwise OR
3029 in the appropriate constant for you.
3031 The mode actually set is affected by the umask.");
3033 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3034 [InitBasicFS, Always, TestOutputStruct (
3035 [["mkfifo"; "0o777"; "/node"];
3036 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3037 "make FIFO (named pipe)",
3039 This call creates a FIFO (named pipe) called C<path> with
3040 mode C<mode>. It is just a convenient wrapper around
3043 The mode actually set is affected by the umask.");
3045 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3046 [InitBasicFS, Always, TestOutputStruct (
3047 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3048 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3049 "make block device node",
3051 This call creates a block device node called C<path> with
3052 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3053 It is just a convenient wrapper around C<guestfs_mknod>.
3055 The mode actually set is affected by the umask.");
3057 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3058 [InitBasicFS, Always, TestOutputStruct (
3059 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3060 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3061 "make char device node",
3063 This call creates a char device node called C<path> with
3064 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3065 It is just a convenient wrapper around C<guestfs_mknod>.
3067 The mode actually set is affected by the umask.");
3069 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3070 [InitEmpty, Always, TestOutputInt (
3071 [["umask"; "0o22"]], 0o22)],
3072 "set file mode creation mask (umask)",
3074 This function sets the mask used for creating new files and
3075 device nodes to C<mask & 0777>.
3077 Typical umask values would be C<022> which creates new files
3078 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3079 C<002> which creates new files with permissions like
3080 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3082 The default umask is C<022>. This is important because it
3083 means that directories and device nodes will be created with
3084 C<0644> or C<0755> mode even if you specify C<0777>.
3086 See also C<guestfs_get_umask>,
3087 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3089 This call returns the previous umask.");
3091 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3093 "read directories entries",
3095 This returns the list of directory entries in directory C<dir>.
3097 All entries in the directory are returned, including C<.> and
3098 C<..>. The entries are I<not> sorted, but returned in the same
3099 order as the underlying filesystem.
3101 Also this call returns basic file type information about each
3102 file. The C<ftyp> field will contain one of the following characters:
3140 The L<readdir(3)> returned a C<d_type> field with an
3145 This function is primarily intended for use by programs. To
3146 get a simple list of names, use C<guestfs_ls>. To get a printable
3147 directory for human consumption, use C<guestfs_ll>.");
3149 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3151 "create partitions on a block device",
3153 This is a simplified interface to the C<guestfs_sfdisk>
3154 command, where partition sizes are specified in megabytes
3155 only (rounded to the nearest cylinder) and you don't need
3156 to specify the cyls, heads and sectors parameters which
3157 were rarely if ever used anyway.
3159 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3160 and C<guestfs_part_disk>");
3162 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3164 "determine file type inside a compressed file",
3166 This command runs C<file> after first decompressing C<path>
3169 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3171 Since 1.0.63, use C<guestfs_file> instead which can now
3172 process compressed files.");
3174 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3176 "list extended attributes of a file or directory",
3178 This call lists the extended attributes of the file or directory
3181 At the system call level, this is a combination of the
3182 L<listxattr(2)> and L<getxattr(2)> calls.
3184 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3186 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3188 "list extended attributes of a file or directory",
3190 This is the same as C<guestfs_getxattrs>, but if C<path>
3191 is a symbolic link, then it returns the extended attributes
3192 of the link itself.");
3194 ("setxattr", (RErr, [String "xattr";
3195 String "val"; Int "vallen"; (* will be BufferIn *)
3196 Pathname "path"]), 143, [Optional "linuxxattrs"],
3198 "set extended attribute of a file or directory",
3200 This call sets the extended attribute named C<xattr>
3201 of the file C<path> to the value C<val> (of length C<vallen>).
3202 The value is arbitrary 8 bit data.
3204 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3206 ("lsetxattr", (RErr, [String "xattr";
3207 String "val"; Int "vallen"; (* will be BufferIn *)
3208 Pathname "path"]), 144, [Optional "linuxxattrs"],
3210 "set extended attribute of a file or directory",
3212 This is the same as C<guestfs_setxattr>, but if C<path>
3213 is a symbolic link, then it sets an extended attribute
3214 of the link itself.");
3216 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3218 "remove extended attribute of a file or directory",
3220 This call removes the extended attribute named C<xattr>
3221 of the file C<path>.
3223 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3225 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3227 "remove extended attribute of a file or directory",
3229 This is the same as C<guestfs_removexattr>, but if C<path>
3230 is a symbolic link, then it removes an extended attribute
3231 of the link itself.");
3233 ("mountpoints", (RHashtable "mps", []), 147, [],
3237 This call is similar to C<guestfs_mounts>. That call returns
3238 a list of devices. This one returns a hash table (map) of
3239 device name to directory where the device is mounted.");
3241 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3242 (* This is a special case: while you would expect a parameter
3243 * of type "Pathname", that doesn't work, because it implies
3244 * NEED_ROOT in the generated calling code in stubs.c, and
3245 * this function cannot use NEED_ROOT.
3248 "create a mountpoint",
3250 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3251 specialized calls that can be used to create extra mountpoints
3252 before mounting the first filesystem.
3254 These calls are I<only> necessary in some very limited circumstances,
3255 mainly the case where you want to mount a mix of unrelated and/or
3256 read-only filesystems together.
3258 For example, live CDs often contain a \"Russian doll\" nest of
3259 filesystems, an ISO outer layer, with a squashfs image inside, with
3260 an ext2/3 image inside that. You can unpack this as follows
3263 add-ro Fedora-11-i686-Live.iso
3266 mkmountpoint /squash
3269 mount-loop /cd/LiveOS/squashfs.img /squash
3270 mount-loop /squash/LiveOS/ext3fs.img /ext3
3272 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3274 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3276 "remove a mountpoint",
3278 This calls removes a mountpoint that was previously created
3279 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3280 for full details.");
3282 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3283 [InitISOFS, Always, TestOutputBuffer (
3284 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3287 This calls returns the contents of the file C<path> as a
3290 Unlike C<guestfs_cat>, this function can correctly
3291 handle files that contain embedded ASCII NUL characters.
3292 However unlike C<guestfs_download>, this function is limited
3293 in the total size of file that can be handled.");
3295 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3296 [InitISOFS, Always, TestOutputList (
3297 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3298 InitISOFS, Always, TestOutputList (
3299 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3300 (* Test for RHBZ#579608, absolute symbolic links. *)
3301 InitISOFS, Always, TestOutputList (
3302 [["grep"; "nomatch"; "/abssymlink"]], [])],
3303 "return lines matching a pattern",
3305 This calls the external C<grep> program and returns the
3308 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3309 [InitISOFS, Always, TestOutputList (
3310 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3311 "return lines matching a pattern",
3313 This calls the external C<egrep> program and returns the
3316 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3317 [InitISOFS, Always, TestOutputList (
3318 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3319 "return lines matching a pattern",
3321 This calls the external C<fgrep> program and returns the
3324 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3325 [InitISOFS, Always, TestOutputList (
3326 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3327 "return lines matching a pattern",
3329 This calls the external C<grep -i> program and returns the
3332 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3333 [InitISOFS, Always, TestOutputList (
3334 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3335 "return lines matching a pattern",
3337 This calls the external C<egrep -i> program and returns the
3340 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3341 [InitISOFS, Always, TestOutputList (
3342 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3343 "return lines matching a pattern",
3345 This calls the external C<fgrep -i> program and returns the
3348 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3349 [InitISOFS, Always, TestOutputList (
3350 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3351 "return lines matching a pattern",
3353 This calls the external C<zgrep> program and returns the
3356 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3357 [InitISOFS, Always, TestOutputList (
3358 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3359 "return lines matching a pattern",
3361 This calls the external C<zegrep> program and returns the
3364 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3365 [InitISOFS, Always, TestOutputList (
3366 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3367 "return lines matching a pattern",
3369 This calls the external C<zfgrep> program and returns the
3372 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3373 [InitISOFS, Always, TestOutputList (
3374 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3375 "return lines matching a pattern",
3377 This calls the external C<zgrep -i> program and returns the
3380 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3381 [InitISOFS, Always, TestOutputList (
3382 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3383 "return lines matching a pattern",
3385 This calls the external C<zegrep -i> program and returns the
3388 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3389 [InitISOFS, Always, TestOutputList (
3390 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3391 "return lines matching a pattern",
3393 This calls the external C<zfgrep -i> program and returns the
3396 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3397 [InitISOFS, Always, TestOutput (
3398 [["realpath"; "/../directory"]], "/directory")],
3399 "canonicalized absolute pathname",
3401 Return the canonicalized absolute pathname of C<path>. The
3402 returned path has no C<.>, C<..> or symbolic link path elements.");
3404 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3405 [InitBasicFS, Always, TestOutputStruct (
3408 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3409 "create a hard link",
3411 This command creates a hard link using the C<ln> command.");
3413 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3414 [InitBasicFS, Always, TestOutputStruct (
3417 ["ln_f"; "/a"; "/b"];
3418 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3419 "create a hard link",
3421 This command creates a hard link using the C<ln -f> command.
3422 The C<-f> option removes the link (C<linkname>) if it exists already.");
3424 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3425 [InitBasicFS, Always, TestOutputStruct (
3427 ["ln_s"; "a"; "/b"];
3428 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3429 "create a symbolic link",
3431 This command creates a symbolic link using the C<ln -s> command.");
3433 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3434 [InitBasicFS, Always, TestOutput (
3435 [["mkdir_p"; "/a/b"];
3436 ["touch"; "/a/b/c"];
3437 ["ln_sf"; "../d"; "/a/b/c"];
3438 ["readlink"; "/a/b/c"]], "../d")],
3439 "create a symbolic link",
3441 This command creates a symbolic link using the C<ln -sf> command,
3442 The C<-f> option removes the link (C<linkname>) if it exists already.");
3444 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3445 [] (* XXX tested above *),
3446 "read the target of a symbolic link",
3448 This command reads the target of a symbolic link.");
3450 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3451 [InitBasicFS, Always, TestOutputStruct (
3452 [["fallocate"; "/a"; "1000000"];
3453 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3454 "preallocate a file in the guest filesystem",
3456 This command preallocates a file (containing zero bytes) named
3457 C<path> of size C<len> bytes. If the file exists already, it
3460 Do not confuse this with the guestfish-specific
3461 C<alloc> command which allocates a file in the host and
3462 attaches it as a device.");
3464 ("swapon_device", (RErr, [Device "device"]), 170, [],
3465 [InitPartition, Always, TestRun (
3466 [["mkswap"; "/dev/sda1"];
3467 ["swapon_device"; "/dev/sda1"];
3468 ["swapoff_device"; "/dev/sda1"]])],
3469 "enable swap on device",
3471 This command enables the libguestfs appliance to use the
3472 swap device or partition named C<device>. The increased
3473 memory is made available for all commands, for example
3474 those run using C<guestfs_command> or C<guestfs_sh>.
3476 Note that you should not swap to existing guest swap
3477 partitions unless you know what you are doing. They may
3478 contain hibernation information, or other information that
3479 the guest doesn't want you to trash. You also risk leaking
3480 information about the host to the guest this way. Instead,
3481 attach a new host device to the guest and swap on that.");
3483 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3484 [], (* XXX tested by swapon_device *)
3485 "disable swap on device",
3487 This command disables the libguestfs appliance swap
3488 device or partition named C<device>.
3489 See C<guestfs_swapon_device>.");
3491 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3492 [InitBasicFS, Always, TestRun (
3493 [["fallocate"; "/swap"; "8388608"];
3494 ["mkswap_file"; "/swap"];
3495 ["swapon_file"; "/swap"];
3496 ["swapoff_file"; "/swap"]])],
3497 "enable swap on file",
3499 This command enables swap to a file.
3500 See C<guestfs_swapon_device> for other notes.");
3502 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3503 [], (* XXX tested by swapon_file *)
3504 "disable swap on file",
3506 This command disables the libguestfs appliance swap on file.");
3508 ("swapon_label", (RErr, [String "label"]), 174, [],
3509 [InitEmpty, Always, TestRun (
3510 [["part_disk"; "/dev/sdb"; "mbr"];
3511 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3512 ["swapon_label"; "swapit"];
3513 ["swapoff_label"; "swapit"];
3514 ["zero"; "/dev/sdb"];
3515 ["blockdev_rereadpt"; "/dev/sdb"]])],
3516 "enable swap on labeled swap partition",
3518 This command enables swap to a labeled swap partition.
3519 See C<guestfs_swapon_device> for other notes.");
3521 ("swapoff_label", (RErr, [String "label"]), 175, [],
3522 [], (* XXX tested by swapon_label *)
3523 "disable swap on labeled swap partition",
3525 This command disables the libguestfs appliance swap on
3526 labeled swap partition.");
3528 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3529 (let uuid = uuidgen () in
3530 [InitEmpty, Always, TestRun (
3531 [["mkswap_U"; uuid; "/dev/sdb"];
3532 ["swapon_uuid"; uuid];
3533 ["swapoff_uuid"; uuid]])]),
3534 "enable swap on swap partition by UUID",
3536 This command enables swap to a swap partition with the given UUID.
3537 See C<guestfs_swapon_device> for other notes.");
3539 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3540 [], (* XXX tested by swapon_uuid *)
3541 "disable swap on swap partition by UUID",
3543 This command disables the libguestfs appliance swap partition
3544 with the given UUID.");
3546 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3547 [InitBasicFS, Always, TestRun (
3548 [["fallocate"; "/swap"; "8388608"];
3549 ["mkswap_file"; "/swap"]])],
3550 "create a swap file",
3554 This command just writes a swap file signature to an existing
3555 file. To create the file itself, use something like C<guestfs_fallocate>.");
3557 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3558 [InitISOFS, Always, TestRun (
3559 [["inotify_init"; "0"]])],
3560 "create an inotify handle",
3562 This command creates a new inotify handle.
3563 The inotify subsystem can be used to notify events which happen to
3564 objects in the guest filesystem.
3566 C<maxevents> is the maximum number of events which will be
3567 queued up between calls to C<guestfs_inotify_read> or
3568 C<guestfs_inotify_files>.
3569 If this is passed as C<0>, then the kernel (or previously set)
3570 default is used. For Linux 2.6.29 the default was 16384 events.
3571 Beyond this limit, the kernel throws away events, but records
3572 the fact that it threw them away by setting a flag
3573 C<IN_Q_OVERFLOW> in the returned structure list (see
3574 C<guestfs_inotify_read>).
3576 Before any events are generated, you have to add some
3577 watches to the internal watch list. See:
3578 C<guestfs_inotify_add_watch>,
3579 C<guestfs_inotify_rm_watch> and
3580 C<guestfs_inotify_watch_all>.
3582 Queued up events should be read periodically by calling
3583 C<guestfs_inotify_read>
3584 (or C<guestfs_inotify_files> which is just a helpful
3585 wrapper around C<guestfs_inotify_read>). If you don't
3586 read the events out often enough then you risk the internal
3589 The handle should be closed after use by calling
3590 C<guestfs_inotify_close>. This also removes any
3591 watches automatically.
3593 See also L<inotify(7)> for an overview of the inotify interface
3594 as exposed by the Linux kernel, which is roughly what we expose
3595 via libguestfs. Note that there is one global inotify handle
3596 per libguestfs instance.");
3598 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3599 [InitBasicFS, Always, TestOutputList (
3600 [["inotify_init"; "0"];
3601 ["inotify_add_watch"; "/"; "1073741823"];
3604 ["inotify_files"]], ["a"; "b"])],
3605 "add an inotify watch",
3607 Watch C<path> for the events listed in C<mask>.
3609 Note that if C<path> is a directory then events within that
3610 directory are watched, but this does I<not> happen recursively
3611 (in subdirectories).
3613 Note for non-C or non-Linux callers: the inotify events are
3614 defined by the Linux kernel ABI and are listed in
3615 C</usr/include/sys/inotify.h>.");
3617 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3619 "remove an inotify watch",
3621 Remove a previously defined inotify watch.
3622 See C<guestfs_inotify_add_watch>.");
3624 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3626 "return list of inotify events",
3628 Return the complete queue of events that have happened
3629 since the previous read call.
3631 If no events have happened, this returns an empty list.
3633 I<Note>: In order to make sure that all events have been
3634 read, you must call this function repeatedly until it
3635 returns an empty list. The reason is that the call will
3636 read events up to the maximum appliance-to-host message
3637 size and leave remaining events in the queue.");
3639 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3641 "return list of watched files that had events",
3643 This function is a helpful wrapper around C<guestfs_inotify_read>
3644 which just returns a list of pathnames of objects that were
3645 touched. The returned pathnames are sorted and deduplicated.");
3647 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3649 "close the inotify handle",
3651 This closes the inotify handle which was previously
3652 opened by inotify_init. It removes all watches, throws
3653 away any pending events, and deallocates all resources.");
3655 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3657 "set SELinux security context",
3659 This sets the SELinux security context of the daemon
3660 to the string C<context>.
3662 See the documentation about SELINUX in L<guestfs(3)>.");
3664 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3666 "get SELinux security context",
3668 This gets the SELinux security context of the daemon.
3670 See the documentation about SELINUX in L<guestfs(3)>,
3671 and C<guestfs_setcon>");
3673 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3674 [InitEmpty, Always, TestOutput (
3675 [["part_disk"; "/dev/sda"; "mbr"];
3676 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3677 ["mount_options"; ""; "/dev/sda1"; "/"];
3678 ["write_file"; "/new"; "new file contents"; "0"];
3679 ["cat"; "/new"]], "new file contents")],
3680 "make a filesystem with block size",
3682 This call is similar to C<guestfs_mkfs>, but it allows you to
3683 control the block size of the resulting filesystem. Supported
3684 block sizes depend on the filesystem type, but typically they
3685 are C<1024>, C<2048> or C<4096> only.");
3687 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3688 [InitEmpty, Always, TestOutput (
3689 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3690 ["mke2journal"; "4096"; "/dev/sda1"];
3691 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3692 ["mount_options"; ""; "/dev/sda2"; "/"];
3693 ["write_file"; "/new"; "new file contents"; "0"];
3694 ["cat"; "/new"]], "new file contents")],
3695 "make ext2/3/4 external journal",
3697 This creates an ext2 external journal on C<device>. It is equivalent
3700 mke2fs -O journal_dev -b blocksize device");
3702 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3703 [InitEmpty, Always, TestOutput (
3704 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3705 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3706 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3707 ["mount_options"; ""; "/dev/sda2"; "/"];
3708 ["write_file"; "/new"; "new file contents"; "0"];
3709 ["cat"; "/new"]], "new file contents")],
3710 "make ext2/3/4 external journal with label",
3712 This creates an ext2 external journal on C<device> with label C<label>.");
3714 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3715 (let uuid = uuidgen () in
3716 [InitEmpty, Always, TestOutput (
3717 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3719 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3720 ["mount_options"; ""; "/dev/sda2"; "/"];
3721 ["write_file"; "/new"; "new file contents"; "0"];
3722 ["cat"; "/new"]], "new file contents")]),
3723 "make ext2/3/4 external journal with UUID",
3725 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3727 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3729 "make ext2/3/4 filesystem with external journal",
3731 This creates an ext2/3/4 filesystem on C<device> with
3732 an external journal on C<journal>. It is equivalent
3735 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3737 See also C<guestfs_mke2journal>.");
3739 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3741 "make ext2/3/4 filesystem with external journal",
3743 This creates an ext2/3/4 filesystem on C<device> with
3744 an external journal on the journal labeled C<label>.
3746 See also C<guestfs_mke2journal_L>.");
3748 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3750 "make ext2/3/4 filesystem with external journal",
3752 This creates an ext2/3/4 filesystem on C<device> with
3753 an external journal on the journal with UUID C<uuid>.
3755 See also C<guestfs_mke2journal_U>.");
3757 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3758 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3759 "load a kernel module",
3761 This loads a kernel module in the appliance.
3763 The kernel module must have been whitelisted when libguestfs
3764 was built (see C<appliance/kmod.whitelist.in> in the source).");
3766 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3767 [InitNone, Always, TestOutput (
3768 [["echo_daemon"; "This is a test"]], "This is a test"
3770 "echo arguments back to the client",
3772 This command concatenate the list of C<words> passed with single spaces between
3773 them and returns the resulting string.
3775 You can use this command to test the connection through to the daemon.
3777 See also C<guestfs_ping_daemon>.");
3779 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3780 [], (* There is a regression test for this. *)
3781 "find all files and directories, returning NUL-separated list",
3783 This command lists out all files and directories, recursively,
3784 starting at C<directory>, placing the resulting list in the
3785 external file called C<files>.
3787 This command works the same way as C<guestfs_find> with the
3788 following exceptions:
3794 The resulting list is written to an external file.
3798 Items (filenames) in the result are separated
3799 by C<\\0> characters. See L<find(1)> option I<-print0>.
3803 This command is not limited in the number of names that it
3808 The result list is not sorted.
3812 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3813 [InitISOFS, Always, TestOutput (
3814 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3815 InitISOFS, Always, TestOutput (
3816 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3817 InitISOFS, Always, TestOutput (
3818 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3819 InitISOFS, Always, TestLastFail (
3820 [["case_sensitive_path"; "/Known-1/"]]);
3821 InitBasicFS, Always, TestOutput (
3823 ["mkdir"; "/a/bbb"];
3824 ["touch"; "/a/bbb/c"];
3825 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3826 InitBasicFS, Always, TestOutput (
3828 ["mkdir"; "/a/bbb"];
3829 ["touch"; "/a/bbb/c"];
3830 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3831 InitBasicFS, Always, TestLastFail (
3833 ["mkdir"; "/a/bbb"];
3834 ["touch"; "/a/bbb/c"];
3835 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3836 "return true path on case-insensitive filesystem",
3838 This can be used to resolve case insensitive paths on
3839 a filesystem which is case sensitive. The use case is
3840 to resolve paths which you have read from Windows configuration
3841 files or the Windows Registry, to the true path.
3843 The command handles a peculiarity of the Linux ntfs-3g
3844 filesystem driver (and probably others), which is that although
3845 the underlying filesystem is case-insensitive, the driver
3846 exports the filesystem to Linux as case-sensitive.
3848 One consequence of this is that special directories such
3849 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3850 (or other things) depending on the precise details of how
3851 they were created. In Windows itself this would not be
3854 Bug or feature? You decide:
3855 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3857 This function resolves the true case of each element in the
3858 path and returns the case-sensitive path.
3860 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3861 might return C<\"/WINDOWS/system32\"> (the exact return value
3862 would depend on details of how the directories were originally
3863 created under Windows).
3866 This function does not handle drive names, backslashes etc.
3868 See also C<guestfs_realpath>.");
3870 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3871 [InitBasicFS, Always, TestOutput (
3872 [["vfs_type"; "/dev/sda1"]], "ext2")],
3873 "get the Linux VFS type corresponding to a mounted device",
3875 This command gets the block device type corresponding to
3876 a mounted device called C<device>.
3878 Usually the result is the name of the Linux VFS module that
3879 is used to mount this device (probably determined automatically
3880 if you used the C<guestfs_mount> call).");
3882 ("truncate", (RErr, [Pathname "path"]), 199, [],
3883 [InitBasicFS, Always, TestOutputStruct (
3884 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3885 ["truncate"; "/test"];
3886 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3887 "truncate a file to zero size",
3889 This command truncates C<path> to a zero-length file. The
3890 file must exist already.");
3892 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3893 [InitBasicFS, Always, TestOutputStruct (
3894 [["touch"; "/test"];
3895 ["truncate_size"; "/test"; "1000"];
3896 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3897 "truncate a file to a particular size",
3899 This command truncates C<path> to size C<size> bytes. The file
3900 must exist already. If the file is smaller than C<size> then
3901 the file is extended to the required size with null bytes.");
3903 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3904 [InitBasicFS, Always, TestOutputStruct (
3905 [["touch"; "/test"];
3906 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3907 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3908 "set timestamp of a file with nanosecond precision",
3910 This command sets the timestamps of a file with nanosecond
3913 C<atsecs, atnsecs> are the last access time (atime) in secs and
3914 nanoseconds from the epoch.
3916 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3917 secs and nanoseconds from the epoch.
3919 If the C<*nsecs> field contains the special value C<-1> then
3920 the corresponding timestamp is set to the current time. (The
3921 C<*secs> field is ignored in this case).
3923 If the C<*nsecs> field contains the special value C<-2> then
3924 the corresponding timestamp is left unchanged. (The
3925 C<*secs> field is ignored in this case).");
3927 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3928 [InitBasicFS, Always, TestOutputStruct (
3929 [["mkdir_mode"; "/test"; "0o111"];
3930 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3931 "create a directory with a particular mode",
3933 This command creates a directory, setting the initial permissions
3934 of the directory to C<mode>.
3936 For common Linux filesystems, the actual mode which is set will
3937 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3938 interpret the mode in other ways.
3940 See also C<guestfs_mkdir>, C<guestfs_umask>");
3942 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3944 "change file owner and group",
3946 Change the file owner to C<owner> and group to C<group>.
3947 This is like C<guestfs_chown> but if C<path> is a symlink then
3948 the link itself is changed, not the target.
3950 Only numeric uid and gid are supported. If you want to use
3951 names, you will need to locate and parse the password file
3952 yourself (Augeas support makes this relatively easy).");
3954 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3956 "lstat on multiple files",
3958 This call allows you to perform the C<guestfs_lstat> operation
3959 on multiple files, where all files are in the directory C<path>.
3960 C<names> is the list of files from this directory.
3962 On return you get a list of stat structs, with a one-to-one
3963 correspondence to the C<names> list. If any name did not exist
3964 or could not be lstat'd, then the C<ino> field of that structure
3967 This call is intended for programs that want to efficiently
3968 list a directory contents without making many round-trips.
3969 See also C<guestfs_lxattrlist> for a similarly efficient call
3970 for getting extended attributes. Very long directory listings
3971 might cause the protocol message size to be exceeded, causing
3972 this call to fail. The caller must split up such requests
3973 into smaller groups of names.");
3975 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3977 "lgetxattr on multiple files",
3979 This call allows you to get the extended attributes
3980 of multiple files, where all files are in the directory C<path>.
3981 C<names> is the list of files from this directory.
3983 On return you get a flat list of xattr structs which must be
3984 interpreted sequentially. The first xattr struct always has a zero-length
3985 C<attrname>. C<attrval> in this struct is zero-length
3986 to indicate there was an error doing C<lgetxattr> for this
3987 file, I<or> is a C string which is a decimal number
3988 (the number of following attributes for this file, which could
3989 be C<\"0\">). Then after the first xattr struct are the
3990 zero or more attributes for the first named file.
3991 This repeats for the second and subsequent files.
3993 This call is intended for programs that want to efficiently
3994 list a directory contents without making many round-trips.
3995 See also C<guestfs_lstatlist> for a similarly efficient call
3996 for getting standard stats. Very long directory listings
3997 might cause the protocol message size to be exceeded, causing
3998 this call to fail. The caller must split up such requests
3999 into smaller groups of names.");
4001 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4003 "readlink on multiple files",
4005 This call allows you to do a C<readlink> operation
4006 on multiple files, where all files are in the directory C<path>.
4007 C<names> is the list of files from this directory.
4009 On return you get a list of strings, with a one-to-one
4010 correspondence to the C<names> list. Each string is the
4011 value of the symbol link.
4013 If the C<readlink(2)> operation fails on any name, then
4014 the corresponding result string is the empty string C<\"\">.
4015 However the whole operation is completed even if there
4016 were C<readlink(2)> errors, and so you can call this
4017 function with names where you don't know if they are
4018 symbolic links already (albeit slightly less efficient).
4020 This call is intended for programs that want to efficiently
4021 list a directory contents without making many round-trips.
4022 Very long directory listings might cause the protocol
4023 message size to be exceeded, causing
4024 this call to fail. The caller must split up such requests
4025 into smaller groups of names.");
4027 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4028 [InitISOFS, Always, TestOutputBuffer (
4029 [["pread"; "/known-4"; "1"; "3"]], "\n");
4030 InitISOFS, Always, TestOutputBuffer (
4031 [["pread"; "/empty"; "0"; "100"]], "")],
4032 "read part of a file",
4034 This command lets you read part of a file. It reads C<count>
4035 bytes of the file, starting at C<offset>, from file C<path>.
4037 This may read fewer bytes than requested. For further details
4038 see the L<pread(2)> system call.");
4040 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4041 [InitEmpty, Always, TestRun (
4042 [["part_init"; "/dev/sda"; "gpt"]])],
4043 "create an empty partition table",
4045 This creates an empty partition table on C<device> of one of the
4046 partition types listed below. Usually C<parttype> should be
4047 either C<msdos> or C<gpt> (for large disks).
4049 Initially there are no partitions. Following this, you should
4050 call C<guestfs_part_add> for each partition required.
4052 Possible values for C<parttype> are:
4056 =item B<efi> | B<gpt>
4058 Intel EFI / GPT partition table.
4060 This is recommended for >= 2 TB partitions that will be accessed
4061 from Linux and Intel-based Mac OS X. It also has limited backwards
4062 compatibility with the C<mbr> format.
4064 =item B<mbr> | B<msdos>
4066 The standard PC \"Master Boot Record\" (MBR) format used
4067 by MS-DOS and Windows. This partition type will B<only> work
4068 for device sizes up to 2 TB. For large disks we recommend
4073 Other partition table types that may work but are not
4082 =item B<amiga> | B<rdb>
4084 Amiga \"Rigid Disk Block\" format.
4092 DASD, used on IBM mainframes.
4100 Old Mac partition format. Modern Macs use C<gpt>.
4104 NEC PC-98 format, common in Japan apparently.
4112 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4113 [InitEmpty, Always, TestRun (
4114 [["part_init"; "/dev/sda"; "mbr"];
4115 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4116 InitEmpty, Always, TestRun (
4117 [["part_init"; "/dev/sda"; "gpt"];
4118 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4119 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4120 InitEmpty, Always, TestRun (
4121 [["part_init"; "/dev/sda"; "mbr"];
4122 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4123 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4124 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4125 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4126 "add a partition to the device",
4128 This command adds a partition to C<device>. If there is no partition
4129 table on the device, call C<guestfs_part_init> first.
4131 The C<prlogex> parameter is the type of partition. Normally you
4132 should pass C<p> or C<primary> here, but MBR partition tables also
4133 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4136 C<startsect> and C<endsect> are the start and end of the partition
4137 in I<sectors>. C<endsect> may be negative, which means it counts
4138 backwards from the end of the disk (C<-1> is the last sector).
4140 Creating a partition which covers the whole disk is not so easy.
4141 Use C<guestfs_part_disk> to do that.");
4143 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4144 [InitEmpty, Always, TestRun (
4145 [["part_disk"; "/dev/sda"; "mbr"]]);
4146 InitEmpty, Always, TestRun (
4147 [["part_disk"; "/dev/sda"; "gpt"]])],
4148 "partition whole disk with a single primary partition",
4150 This command is simply a combination of C<guestfs_part_init>
4151 followed by C<guestfs_part_add> to create a single primary partition
4152 covering the whole disk.
4154 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4155 but other possible values are described in C<guestfs_part_init>.");
4157 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4158 [InitEmpty, Always, TestRun (
4159 [["part_disk"; "/dev/sda"; "mbr"];
4160 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4161 "make a partition bootable",
4163 This sets the bootable flag on partition numbered C<partnum> on
4164 device C<device>. Note that partitions are numbered from 1.
4166 The bootable flag is used by some operating systems (notably
4167 Windows) to determine which partition to boot from. It is by
4168 no means universally recognized.");
4170 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4171 [InitEmpty, Always, TestRun (
4172 [["part_disk"; "/dev/sda"; "gpt"];
4173 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4174 "set partition name",
4176 This sets the partition name on partition numbered C<partnum> on
4177 device C<device>. Note that partitions are numbered from 1.
4179 The partition name can only be set on certain types of partition
4180 table. This works on C<gpt> but not on C<mbr> partitions.");
4182 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4183 [], (* XXX Add a regression test for this. *)
4184 "list partitions on a device",
4186 This command parses the partition table on C<device> and
4187 returns the list of partitions found.
4189 The fields in the returned structure are:
4195 Partition number, counting from 1.
4199 Start of the partition I<in bytes>. To get sectors you have to
4200 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4204 End of the partition in bytes.
4208 Size of the partition in bytes.
4212 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4213 [InitEmpty, Always, TestOutput (
4214 [["part_disk"; "/dev/sda"; "gpt"];
4215 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4216 "get the partition table type",
4218 This command examines the partition table on C<device> and
4219 returns the partition table type (format) being used.
4221 Common return values include: C<msdos> (a DOS/Windows style MBR
4222 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4223 values are possible, although unusual. See C<guestfs_part_init>
4226 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4227 [InitBasicFS, Always, TestOutputBuffer (
4228 [["fill"; "0x63"; "10"; "/test"];
4229 ["read_file"; "/test"]], "cccccccccc")],
4230 "fill a file with octets",
4232 This command creates a new file called C<path>. The initial
4233 content of the file is C<len> octets of C<c>, where C<c>
4234 must be a number in the range C<[0..255]>.
4236 To fill a file with zero bytes (sparsely), it is
4237 much more efficient to use C<guestfs_truncate_size>.");
4239 ("available", (RErr, [StringList "groups"]), 216, [],
4240 [InitNone, Always, TestRun [["available"; ""]]],
4241 "test availability of some parts of the API",
4243 This command is used to check the availability of some
4244 groups of functionality in the appliance, which not all builds of
4245 the libguestfs appliance will be able to provide.
4247 The libguestfs groups, and the functions that those
4248 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4250 The argument C<groups> is a list of group names, eg:
4251 C<[\"inotify\", \"augeas\"]> would check for the availability of
4252 the Linux inotify functions and Augeas (configuration file
4255 The command returns no error if I<all> requested groups are available.
4257 It fails with an error if one or more of the requested
4258 groups is unavailable in the appliance.
4260 If an unknown group name is included in the
4261 list of groups then an error is always returned.
4269 You must call C<guestfs_launch> before calling this function.
4271 The reason is because we don't know what groups are
4272 supported by the appliance/daemon until it is running and can
4277 If a group of functions is available, this does not necessarily
4278 mean that they will work. You still have to check for errors
4279 when calling individual API functions even if they are
4284 It is usually the job of distro packagers to build
4285 complete functionality into the libguestfs appliance.
4286 Upstream libguestfs, if built from source with all
4287 requirements satisfied, will support everything.
4291 This call was added in version C<1.0.80>. In previous
4292 versions of libguestfs all you could do would be to speculatively
4293 execute a command to find out if the daemon implemented it.
4294 See also C<guestfs_version>.
4298 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4299 [InitBasicFS, Always, TestOutputBuffer (
4300 [["write_file"; "/src"; "hello, world"; "0"];
4301 ["dd"; "/src"; "/dest"];
4302 ["read_file"; "/dest"]], "hello, world")],
4303 "copy from source to destination using dd",
4305 This command copies from one source device or file C<src>
4306 to another destination device or file C<dest>. Normally you
4307 would use this to copy to or from a device or partition, for
4308 example to duplicate a filesystem.
4310 If the destination is a device, it must be as large or larger
4311 than the source file or device, otherwise the copy will fail.
4312 This command cannot do partial copies (see C<guestfs_copy_size>).");
4314 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4315 [InitBasicFS, Always, TestOutputInt (
4316 [["write_file"; "/file"; "hello, world"; "0"];
4317 ["filesize"; "/file"]], 12)],
4318 "return the size of the file in bytes",
4320 This command returns the size of C<file> in bytes.
4322 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4323 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4324 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4326 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4327 [InitBasicFSonLVM, Always, TestOutputList (
4328 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4329 ["lvs"]], ["/dev/VG/LV2"])],
4330 "rename an LVM logical volume",
4332 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4334 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4335 [InitBasicFSonLVM, Always, TestOutputList (
4337 ["vg_activate"; "false"; "VG"];
4338 ["vgrename"; "VG"; "VG2"];
4339 ["vg_activate"; "true"; "VG2"];
4340 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4341 ["vgs"]], ["VG2"])],
4342 "rename an LVM volume group",
4344 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4346 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4347 [InitISOFS, Always, TestOutputBuffer (
4348 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4349 "list the contents of a single file in an initrd",
4351 This command unpacks the file C<filename> from the initrd file
4352 called C<initrdpath>. The filename must be given I<without> the
4353 initial C</> character.
4355 For example, in guestfish you could use the following command
4356 to examine the boot script (usually called C</init>)
4357 contained in a Linux initrd or initramfs image:
4359 initrd-cat /boot/initrd-<version>.img init
4361 See also C<guestfs_initrd_list>.");
4363 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4365 "get the UUID of a physical volume",
4367 This command returns the UUID of the LVM PV C<device>.");
4369 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4371 "get the UUID of a volume group",
4373 This command returns the UUID of the LVM VG named C<vgname>.");
4375 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4377 "get the UUID of a logical volume",
4379 This command returns the UUID of the LVM LV C<device>.");
4381 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4383 "get the PV UUIDs containing the volume group",
4385 Given a VG called C<vgname>, this returns the UUIDs of all
4386 the physical volumes that this volume group resides on.
4388 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4389 calls to associate physical volumes and volume groups.
4391 See also C<guestfs_vglvuuids>.");
4393 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4395 "get the LV UUIDs of all LVs in the volume group",
4397 Given a VG called C<vgname>, this returns the UUIDs of all
4398 the logical volumes created in this volume group.
4400 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4401 calls to associate logical volumes and volume groups.
4403 See also C<guestfs_vgpvuuids>.");
4405 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4406 [InitBasicFS, Always, TestOutputBuffer (
4407 [["write_file"; "/src"; "hello, world"; "0"];
4408 ["copy_size"; "/src"; "/dest"; "5"];
4409 ["read_file"; "/dest"]], "hello")],
4410 "copy size bytes from source to destination using dd",
4412 This command copies exactly C<size> bytes from one source device
4413 or file C<src> to another destination device or file C<dest>.
4415 Note this will fail if the source is too short or if the destination
4416 is not large enough.");
4418 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4419 [InitBasicFSonLVM, Always, TestRun (
4420 [["zero_device"; "/dev/VG/LV"]])],
4421 "write zeroes to an entire device",
4423 This command writes zeroes over the entire C<device>. Compare
4424 with C<guestfs_zero> which just zeroes the first few blocks of
4427 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4428 [InitBasicFS, Always, TestOutput (
4429 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4430 ["cat"; "/hello"]], "hello\n")],
4431 "unpack compressed tarball to directory",
4433 This command uploads and unpacks local file C<tarball> (an
4434 I<xz compressed> tar file) into C<directory>.");
4436 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4438 "pack directory into compressed tarball",
4440 This command packs the contents of C<directory> and downloads
4441 it to local file C<tarball> (as an xz compressed tar archive).");
4443 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4445 "resize an NTFS filesystem",
4447 This command resizes an NTFS filesystem, expanding or
4448 shrinking it to the size of the underlying device.
4449 See also L<ntfsresize(8)>.");
4451 ("vgscan", (RErr, []), 232, [],
4452 [InitEmpty, Always, TestRun (
4454 "rescan for LVM physical volumes, volume groups and logical volumes",
4456 This rescans all block devices and rebuilds the list of LVM
4457 physical volumes, volume groups and logical volumes.");
4459 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4460 [InitEmpty, Always, TestRun (
4461 [["part_init"; "/dev/sda"; "mbr"];
4462 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4463 ["part_del"; "/dev/sda"; "1"]])],
4464 "delete a partition",
4466 This command deletes the partition numbered C<partnum> on C<device>.
4468 Note that in the case of MBR partitioning, deleting an
4469 extended partition also deletes any logical partitions
4472 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4473 [InitEmpty, Always, TestOutputTrue (
4474 [["part_init"; "/dev/sda"; "mbr"];
4475 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4476 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4477 ["part_get_bootable"; "/dev/sda"; "1"]])],
4478 "return true if a partition is bootable",
4480 This command returns true if the partition C<partnum> on
4481 C<device> has the bootable flag set.
4483 See also C<guestfs_part_set_bootable>.");
4485 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4486 [InitEmpty, Always, TestOutputInt (
4487 [["part_init"; "/dev/sda"; "mbr"];
4488 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4489 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4490 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4491 "get the MBR type byte (ID byte) from a partition",
4493 Returns the MBR type byte (also known as the ID byte) from
4494 the numbered partition C<partnum>.
4496 Note that only MBR (old DOS-style) partitions have type bytes.
4497 You will get undefined results for other partition table
4498 types (see C<guestfs_part_get_parttype>).");
4500 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4501 [], (* tested by part_get_mbr_id *)
4502 "set the MBR type byte (ID byte) of a partition",
4504 Sets the MBR type byte (also known as the ID byte) of
4505 the numbered partition C<partnum> to C<idbyte>. Note
4506 that the type bytes quoted in most documentation are
4507 in fact hexadecimal numbers, but usually documented
4508 without any leading \"0x\" which might be confusing.
4510 Note that only MBR (old DOS-style) partitions have type bytes.
4511 You will get undefined results for other partition table
4512 types (see C<guestfs_part_get_parttype>).");
4514 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4515 [InitISOFS, Always, TestOutput (
4516 [["checksum_device"; "md5"; "/dev/sdd"]],
4517 (Digest.to_hex (Digest.file "images/test.iso")))],
4518 "compute MD5, SHAx or CRC checksum of the contents of a device",
4520 This call computes the MD5, SHAx or CRC checksum of the
4521 contents of the device named C<device>. For the types of
4522 checksums supported see the C<guestfs_checksum> command.");
4524 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4525 [InitNone, Always, TestRun (
4526 [["part_disk"; "/dev/sda"; "mbr"];
4527 ["pvcreate"; "/dev/sda1"];
4528 ["vgcreate"; "VG"; "/dev/sda1"];
4529 ["lvcreate"; "LV"; "VG"; "10"];
4530 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4531 "expand an LV to fill free space",
4533 This expands an existing logical volume C<lv> so that it fills
4534 C<pc>% of the remaining free space in the volume group. Commonly
4535 you would call this with pc = 100 which expands the logical volume
4536 as much as possible, using all remaining free space in the volume
4539 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4540 [], (* XXX Augeas code needs tests. *)
4541 "clear Augeas path",
4543 Set the value associated with C<path> to C<NULL>. This
4544 is the same as the L<augtool(1)> C<clear> command.");
4546 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4547 [InitEmpty, Always, TestOutputInt (
4548 [["get_umask"]], 0o22)],
4549 "get the current umask",
4551 Return the current umask. By default the umask is C<022>
4552 unless it has been set by calling C<guestfs_umask>.");
4554 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4556 "upload a file to the appliance (internal use only)",
4558 The C<guestfs_debug_upload> command uploads a file to
4559 the libguestfs appliance.
4561 There is no comprehensive help for this command. You have
4562 to look at the file C<daemon/debug.c> in the libguestfs source
4563 to find out what it is for.");
4565 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4566 [InitBasicFS, Always, TestOutput (
4567 [["base64_in"; "../images/hello.b64"; "/hello"];
4568 ["cat"; "/hello"]], "hello\n")],
4569 "upload base64-encoded data to file",
4571 This command uploads base64-encoded data from C<base64file>
4574 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4576 "download file and encode as base64",
4578 This command downloads the contents of C<filename>, writing
4579 it out to local file C<base64file> encoded as base64.");
4581 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4583 "compute MD5, SHAx or CRC checksum of files in a directory",
4585 This command computes the checksums of all regular files in
4586 C<directory> and then emits a list of those checksums to
4587 the local output file C<sumsfile>.
4589 This can be used for verifying the integrity of a virtual
4590 machine. However to be properly secure you should pay
4591 attention to the output of the checksum command (it uses
4592 the ones from GNU coreutils). In particular when the
4593 filename is not printable, coreutils uses a special
4594 backslash syntax. For more information, see the GNU
4595 coreutils info file.");
4599 let all_functions = non_daemon_functions @ daemon_functions
4601 (* In some places we want the functions to be displayed sorted
4602 * alphabetically, so this is useful:
4604 let all_functions_sorted =
4605 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4606 compare n1 n2) all_functions
4608 (* Field types for structures. *)
4610 | FChar (* C 'char' (really, a 7 bit byte). *)
4611 | FString (* nul-terminated ASCII string, NOT NULL. *)
4612 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4617 | FBytes (* Any int measure that counts bytes. *)
4618 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4619 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4621 (* Because we generate extra parsing code for LVM command line tools,
4622 * we have to pull out the LVM columns separately here.
4632 "pv_attr", FString (* XXX *);
4633 "pv_pe_count", FInt64;
4634 "pv_pe_alloc_count", FInt64;
4637 "pv_mda_count", FInt64;
4638 "pv_mda_free", FBytes;
4639 (* Not in Fedora 10:
4640 "pv_mda_size", FBytes;
4647 "vg_attr", FString (* XXX *);
4650 "vg_sysid", FString;
4651 "vg_extent_size", FBytes;
4652 "vg_extent_count", FInt64;
4653 "vg_free_count", FInt64;
4658 "snap_count", FInt64;
4661 "vg_mda_count", FInt64;
4662 "vg_mda_free", FBytes;
4663 (* Not in Fedora 10:
4664 "vg_mda_size", FBytes;
4670 "lv_attr", FString (* XXX *);
4673 "lv_kernel_major", FInt64;
4674 "lv_kernel_minor", FInt64;
4676 "seg_count", FInt64;
4678 "snap_percent", FOptPercent;
4679 "copy_percent", FOptPercent;
4682 "mirror_log", FString;
4686 (* Names and fields in all structures (in RStruct and RStructList)
4690 (* The old RIntBool return type, only ever used for aug_defnode. Do
4691 * not use this struct in any new code.
4694 "i", FInt32; (* for historical compatibility *)
4695 "b", FInt32; (* for historical compatibility *)
4698 (* LVM PVs, VGs, LVs. *)
4699 "lvm_pv", lvm_pv_cols;
4700 "lvm_vg", lvm_vg_cols;
4701 "lvm_lv", lvm_lv_cols;
4703 (* Column names and types from stat structures.
4704 * NB. Can't use things like 'st_atime' because glibc header files
4705 * define some of these as macros. Ugh.
4736 (* Column names in dirent structure. *)
4739 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4744 (* Version numbers. *)
4752 (* Extended attribute. *)
4754 "attrname", FString;
4758 (* Inotify events. *)
4762 "in_cookie", FUInt32;
4766 (* Partition table entry. *)
4769 "part_start", FBytes;
4771 "part_size", FBytes;
4773 ] (* end of structs *)
4775 (* Ugh, Java has to be different ..
4776 * These names are also used by the Haskell bindings.
4778 let java_structs = [
4779 "int_bool", "IntBool";
4784 "statvfs", "StatVFS";
4786 "version", "Version";
4788 "inotify_event", "INotifyEvent";
4789 "partition", "Partition";
4792 (* What structs are actually returned. *)
4793 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4795 (* Returns a list of RStruct/RStructList structs that are returned
4796 * by any function. Each element of returned list is a pair:
4798 * (structname, RStructOnly)
4799 * == there exists function which returns RStruct (_, structname)
4800 * (structname, RStructListOnly)
4801 * == there exists function which returns RStructList (_, structname)
4802 * (structname, RStructAndList)
4803 * == there are functions returning both RStruct (_, structname)
4804 * and RStructList (_, structname)
4806 let rstructs_used_by functions =
4807 (* ||| is a "logical OR" for rstructs_used_t *)
4811 | _, RStructAndList -> RStructAndList
4812 | RStructOnly, RStructListOnly
4813 | RStructListOnly, RStructOnly -> RStructAndList
4814 | RStructOnly, RStructOnly -> RStructOnly
4815 | RStructListOnly, RStructListOnly -> RStructListOnly
4818 let h = Hashtbl.create 13 in
4820 (* if elem->oldv exists, update entry using ||| operator,
4821 * else just add elem->newv to the hash
4823 let update elem newv =
4824 try let oldv = Hashtbl.find h elem in
4825 Hashtbl.replace h elem (newv ||| oldv)
4826 with Not_found -> Hashtbl.add h elem newv
4830 fun (_, style, _, _, _, _, _) ->
4831 match fst style with
4832 | RStruct (_, structname) -> update structname RStructOnly
4833 | RStructList (_, structname) -> update structname RStructListOnly
4837 (* return key->values as a list of (key,value) *)
4838 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4840 (* Used for testing language bindings. *)
4842 | CallString of string
4843 | CallOptString of string option
4844 | CallStringList of string list
4846 | CallInt64 of int64
4849 (* Used to memoize the result of pod2text. *)
4850 let pod2text_memo_filename = "src/.pod2text.data"
4851 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4853 let chan = open_in pod2text_memo_filename in
4854 let v = input_value chan in
4858 _ -> Hashtbl.create 13
4859 let pod2text_memo_updated () =
4860 let chan = open_out pod2text_memo_filename in
4861 output_value chan pod2text_memo;
4864 (* Useful functions.
4865 * Note we don't want to use any external OCaml libraries which
4866 * makes this a bit harder than it should be.
4868 module StringMap = Map.Make (String)
4870 let failwithf fs = ksprintf failwith fs
4872 let unique = let i = ref 0 in fun () -> incr i; !i
4874 let replace_char s c1 c2 =
4875 let s2 = String.copy s in
4876 let r = ref false in
4877 for i = 0 to String.length s2 - 1 do
4878 if String.unsafe_get s2 i = c1 then (
4879 String.unsafe_set s2 i c2;
4883 if not !r then s else s2
4887 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4889 let triml ?(test = isspace) str =
4891 let n = ref (String.length str) in
4892 while !n > 0 && test str.[!i]; do
4897 else String.sub str !i !n
4899 let trimr ?(test = isspace) str =
4900 let n = ref (String.length str) in
4901 while !n > 0 && test str.[!n-1]; do
4904 if !n = String.length str then str
4905 else String.sub str 0 !n
4907 let trim ?(test = isspace) str =
4908 trimr ~test (triml ~test str)
4910 let rec find s sub =
4911 let len = String.length s in
4912 let sublen = String.length sub in
4914 if i <= len-sublen then (
4916 if j < sublen then (
4917 if s.[i+j] = sub.[j] then loop2 (j+1)
4923 if r = -1 then loop (i+1) else r
4929 let rec replace_str s s1 s2 =
4930 let len = String.length s in
4931 let sublen = String.length s1 in
4932 let i = find s s1 in
4935 let s' = String.sub s 0 i in
4936 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4937 s' ^ s2 ^ replace_str s'' s1 s2
4940 let rec string_split sep str =
4941 let len = String.length str in
4942 let seplen = String.length sep in
4943 let i = find str sep in
4944 if i = -1 then [str]
4946 let s' = String.sub str 0 i in
4947 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4948 s' :: string_split sep s''
4951 let files_equal n1 n2 =
4952 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4953 match Sys.command cmd with
4956 | i -> failwithf "%s: failed with error code %d" cmd i
4958 let rec filter_map f = function
4962 | Some y -> y :: filter_map f xs
4963 | None -> filter_map f xs
4965 let rec find_map f = function
4966 | [] -> raise Not_found
4970 | None -> find_map f xs
4973 let rec loop i = function
4975 | x :: xs -> f i x; loop (i+1) xs
4980 let rec loop i = function
4982 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4986 let count_chars c str =
4987 let count = ref 0 in
4988 for i = 0 to String.length str - 1 do
4989 if c = String.unsafe_get str i then incr count
4993 let name_of_argt = function
4994 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4995 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4996 | FileIn n | FileOut n -> n
4998 let java_name_of_struct typ =
4999 try List.assoc typ java_structs
5002 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5004 let cols_of_struct typ =
5005 try List.assoc typ structs
5007 failwithf "cols_of_struct: unknown struct %s" typ
5009 let seq_of_test = function
5010 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5011 | TestOutputListOfDevices (s, _)
5012 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5013 | TestOutputTrue s | TestOutputFalse s
5014 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5015 | TestOutputStruct (s, _)
5016 | TestLastFail s -> s
5018 (* Handling for function flags. *)
5019 let protocol_limit_warning =
5020 "Because of the message protocol, there is a transfer limit
5021 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5023 let danger_will_robinson =
5024 "B<This command is dangerous. Without careful use you
5025 can easily destroy all your data>."
5027 let deprecation_notice flags =
5030 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5032 sprintf "This function is deprecated.
5033 In new code, use the C<%s> call instead.
5035 Deprecated functions will not be removed from the API, but the
5036 fact that they are deprecated indicates that there are problems
5037 with correct use of these functions." alt in
5042 (* Create list of optional groups. *)
5044 let h = Hashtbl.create 13 in
5046 fun (name, _, _, flags, _, _, _) ->
5050 let names = try Hashtbl.find h group with Not_found -> [] in
5051 Hashtbl.replace h group (name :: names)
5055 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5058 fun group -> group, List.sort compare (Hashtbl.find h group)
5060 List.sort (fun x y -> compare (fst x) (fst y)) groups
5062 (* Check function names etc. for consistency. *)
5063 let check_functions () =
5064 let contains_uppercase str =
5065 let len = String.length str in
5067 if i >= len then false
5070 if c >= 'A' && c <= 'Z' then true
5077 (* Check function names. *)
5079 fun (name, _, _, _, _, _, _) ->
5080 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5081 failwithf "function name %s does not need 'guestfs' prefix" name;
5083 failwithf "function name is empty";
5084 if name.[0] < 'a' || name.[0] > 'z' then
5085 failwithf "function name %s must start with lowercase a-z" name;
5086 if String.contains name '-' then
5087 failwithf "function name %s should not contain '-', use '_' instead."
5091 (* Check function parameter/return names. *)
5093 fun (name, style, _, _, _, _, _) ->
5094 let check_arg_ret_name n =
5095 if contains_uppercase n then
5096 failwithf "%s param/ret %s should not contain uppercase chars"
5098 if String.contains n '-' || String.contains n '_' then
5099 failwithf "%s param/ret %s should not contain '-' or '_'"
5102 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;
5103 if n = "int" || n = "char" || n = "short" || n = "long" then
5104 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5105 if n = "i" || n = "n" then
5106 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5107 if n = "argv" || n = "args" then
5108 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5110 (* List Haskell, OCaml and C keywords here.
5111 * http://www.haskell.org/haskellwiki/Keywords
5112 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5113 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5114 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5115 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5116 * Omitting _-containing words, since they're handled above.
5117 * Omitting the OCaml reserved word, "val", is ok,
5118 * and saves us from renaming several parameters.
5121 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5122 "char"; "class"; "const"; "constraint"; "continue"; "data";
5123 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5124 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5125 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5126 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5127 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5129 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5130 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5131 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5132 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5133 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5134 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5135 "volatile"; "when"; "where"; "while";
5137 if List.mem n reserved then
5138 failwithf "%s has param/ret using reserved word %s" name n;
5141 (match fst style with
5143 | RInt n | RInt64 n | RBool n
5144 | RConstString n | RConstOptString n | RString n
5145 | RStringList n | RStruct (n, _) | RStructList (n, _)
5146 | RHashtable n | RBufferOut n ->
5147 check_arg_ret_name n
5149 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5152 (* Check short descriptions. *)
5154 fun (name, _, _, _, _, shortdesc, _) ->
5155 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5156 failwithf "short description of %s should begin with lowercase." name;
5157 let c = shortdesc.[String.length shortdesc-1] in
5158 if c = '\n' || c = '.' then
5159 failwithf "short description of %s should not end with . or \\n." name
5162 (* Check long descriptions. *)
5164 fun (name, _, _, _, _, _, longdesc) ->
5165 if longdesc.[String.length longdesc-1] = '\n' then
5166 failwithf "long description of %s should not end with \\n." name
5169 (* Check proc_nrs. *)
5171 fun (name, _, proc_nr, _, _, _, _) ->
5172 if proc_nr <= 0 then
5173 failwithf "daemon function %s should have proc_nr > 0" name
5177 fun (name, _, proc_nr, _, _, _, _) ->
5178 if proc_nr <> -1 then
5179 failwithf "non-daemon function %s should have proc_nr -1" name
5180 ) non_daemon_functions;
5183 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5186 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5187 let rec loop = function
5190 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5192 | (name1,nr1) :: (name2,nr2) :: _ ->
5193 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5201 (* Ignore functions that have no tests. We generate a
5202 * warning when the user does 'make check' instead.
5204 | name, _, _, _, [], _, _ -> ()
5205 | name, _, _, _, tests, _, _ ->
5209 match seq_of_test test with
5211 failwithf "%s has a test containing an empty sequence" name
5212 | cmds -> List.map List.hd cmds
5214 let funcs = List.flatten funcs in
5216 let tested = List.mem name funcs in
5219 failwithf "function %s has tests but does not test itself" name
5222 (* 'pr' prints to the current output file. *)
5223 let chan = ref Pervasives.stdout
5228 let i = count_chars '\n' str in
5229 lines := !lines + i;
5230 output_string !chan str
5233 let copyright_years =
5234 let this_year = 1900 + (localtime (time ())).tm_year in
5235 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5237 (* Generate a header block in a number of standard styles. *)
5238 type comment_style =
5239 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5240 type license = GPLv2plus | LGPLv2plus
5242 let generate_header ?(extra_inputs = []) comment license =
5243 let inputs = "src/generator.ml" :: extra_inputs in
5244 let c = match comment with
5245 | CStyle -> pr "/* "; " *"
5246 | CPlusPlusStyle -> pr "// "; "//"
5247 | HashStyle -> pr "# "; "#"
5248 | OCamlStyle -> pr "(* "; " *"
5249 | HaskellStyle -> pr "{- "; " " in
5250 pr "libguestfs generated file\n";
5251 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5252 List.iter (pr "%s %s\n" c) inputs;
5253 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5255 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5259 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5260 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5261 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5262 pr "%s (at your option) any later version.\n" c;
5264 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5265 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5266 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5267 pr "%s GNU General Public License for more details.\n" c;
5269 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5270 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5271 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5274 pr "%s This library is free software; you can redistribute it and/or\n" c;
5275 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5276 pr "%s License as published by the Free Software Foundation; either\n" c;
5277 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5279 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5280 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5281 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5282 pr "%s Lesser General Public License for more details.\n" c;
5284 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5285 pr "%s License along with this library; if not, write to the Free Software\n" c;
5286 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5289 | CStyle -> pr " */\n"
5292 | OCamlStyle -> pr " *)\n"
5293 | HaskellStyle -> pr "-}\n"
5297 (* Start of main code generation functions below this line. *)
5299 (* Generate the pod documentation for the C API. *)
5300 let rec generate_actions_pod () =
5302 fun (shortname, style, _, flags, _, _, longdesc) ->
5303 if not (List.mem NotInDocs flags) then (
5304 let name = "guestfs_" ^ shortname in
5305 pr "=head2 %s\n\n" name;
5307 generate_prototype ~extern:false ~handle:"g" name style;
5309 pr "%s\n\n" longdesc;
5310 (match fst style with
5312 pr "This function returns 0 on success or -1 on error.\n\n"
5314 pr "On error this function returns -1.\n\n"
5316 pr "On error this function returns -1.\n\n"
5318 pr "This function returns a C truth value on success or -1 on error.\n\n"
5320 pr "This function returns a string, or NULL on error.
5321 The string is owned by the guest handle and must I<not> be freed.\n\n"
5322 | RConstOptString _ ->
5323 pr "This function returns a string which may be NULL.
5324 There is way to return an error from this function.
5325 The string is owned by the guest handle and must I<not> be freed.\n\n"
5327 pr "This function returns a string, or NULL on error.
5328 I<The caller must free the returned string after use>.\n\n"
5330 pr "This function returns a NULL-terminated array of strings
5331 (like L<environ(3)>), or NULL if there was an error.
5332 I<The caller must free the strings and the array after use>.\n\n"
5333 | RStruct (_, typ) ->
5334 pr "This function returns a C<struct guestfs_%s *>,
5335 or NULL if there was an error.
5336 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5337 | RStructList (_, typ) ->
5338 pr "This function returns a C<struct guestfs_%s_list *>
5339 (see E<lt>guestfs-structs.hE<gt>),
5340 or NULL if there was an error.
5341 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5343 pr "This function returns a NULL-terminated array of
5344 strings, or NULL if there was an error.
5345 The array of strings will always have length C<2n+1>, where
5346 C<n> keys and values alternate, followed by the trailing NULL entry.
5347 I<The caller must free the strings and the array after use>.\n\n"
5349 pr "This function returns a buffer, or NULL on error.
5350 The size of the returned buffer is written to C<*size_r>.
5351 I<The caller must free the returned buffer after use>.\n\n"
5353 if List.mem ProtocolLimitWarning flags then
5354 pr "%s\n\n" protocol_limit_warning;
5355 if List.mem DangerWillRobinson flags then
5356 pr "%s\n\n" danger_will_robinson;
5357 match deprecation_notice flags with
5359 | Some txt -> pr "%s\n\n" txt
5361 ) all_functions_sorted
5363 and generate_structs_pod () =
5364 (* Structs documentation. *)
5367 pr "=head2 guestfs_%s\n" typ;
5369 pr " struct guestfs_%s {\n" typ;
5372 | name, FChar -> pr " char %s;\n" name
5373 | name, FUInt32 -> pr " uint32_t %s;\n" name
5374 | name, FInt32 -> pr " int32_t %s;\n" name
5375 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5376 | name, FInt64 -> pr " int64_t %s;\n" name
5377 | name, FString -> pr " char *%s;\n" name
5379 pr " /* The next two fields describe a byte array. */\n";
5380 pr " uint32_t %s_len;\n" name;
5381 pr " char *%s;\n" name
5383 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5384 pr " char %s[32];\n" name
5385 | name, FOptPercent ->
5386 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5387 pr " float %s;\n" name
5391 pr " struct guestfs_%s_list {\n" typ;
5392 pr " uint32_t len; /* Number of elements in list. */\n";
5393 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5396 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5397 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5402 and generate_availability_pod () =
5403 (* Availability documentation. *)
5407 fun (group, functions) ->
5408 pr "=item B<%s>\n" group;
5410 pr "The following functions:\n";
5411 List.iter (pr "L</guestfs_%s>\n") functions;
5417 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5418 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5420 * We have to use an underscore instead of a dash because otherwise
5421 * rpcgen generates incorrect code.
5423 * This header is NOT exported to clients, but see also generate_structs_h.
5425 and generate_xdr () =
5426 generate_header CStyle LGPLv2plus;
5428 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5429 pr "typedef string str<>;\n";
5432 (* Internal structures. *)
5436 pr "struct guestfs_int_%s {\n" typ;
5438 | name, FChar -> pr " char %s;\n" name
5439 | name, FString -> pr " string %s<>;\n" name
5440 | name, FBuffer -> pr " opaque %s<>;\n" name
5441 | name, FUUID -> pr " opaque %s[32];\n" name
5442 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5443 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5444 | name, FOptPercent -> pr " float %s;\n" name
5448 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5453 fun (shortname, style, _, _, _, _, _) ->
5454 let name = "guestfs_" ^ shortname in
5456 (match snd style with
5459 pr "struct %s_args {\n" name;
5462 | Pathname n | Device n | Dev_or_Path n | String n ->
5463 pr " string %s<>;\n" n
5464 | OptString n -> pr " str *%s;\n" n
5465 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5466 | Bool n -> pr " bool %s;\n" n
5467 | Int n -> pr " int %s;\n" n
5468 | Int64 n -> pr " hyper %s;\n" n
5469 | FileIn _ | FileOut _ -> ()
5473 (match fst style with
5476 pr "struct %s_ret {\n" name;
5480 pr "struct %s_ret {\n" name;
5481 pr " hyper %s;\n" n;
5484 pr "struct %s_ret {\n" name;
5487 | RConstString _ | RConstOptString _ ->
5488 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5490 pr "struct %s_ret {\n" name;
5491 pr " string %s<>;\n" n;
5494 pr "struct %s_ret {\n" name;
5495 pr " str %s<>;\n" n;
5497 | RStruct (n, typ) ->
5498 pr "struct %s_ret {\n" name;
5499 pr " guestfs_int_%s %s;\n" typ n;
5501 | RStructList (n, typ) ->
5502 pr "struct %s_ret {\n" name;
5503 pr " guestfs_int_%s_list %s;\n" typ n;
5506 pr "struct %s_ret {\n" name;
5507 pr " str %s<>;\n" n;
5510 pr "struct %s_ret {\n" name;
5511 pr " opaque %s<>;\n" n;
5516 (* Table of procedure numbers. *)
5517 pr "enum guestfs_procedure {\n";
5519 fun (shortname, _, proc_nr, _, _, _, _) ->
5520 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5522 pr " GUESTFS_PROC_NR_PROCS\n";
5526 (* Having to choose a maximum message size is annoying for several
5527 * reasons (it limits what we can do in the API), but it (a) makes
5528 * the protocol a lot simpler, and (b) provides a bound on the size
5529 * of the daemon which operates in limited memory space.
5531 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5534 (* Message header, etc. *)
5536 /* The communication protocol is now documented in the guestfs(3)
5540 const GUESTFS_PROGRAM = 0x2000F5F5;
5541 const GUESTFS_PROTOCOL_VERSION = 1;
5543 /* These constants must be larger than any possible message length. */
5544 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5545 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5547 enum guestfs_message_direction {
5548 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5549 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5552 enum guestfs_message_status {
5553 GUESTFS_STATUS_OK = 0,
5554 GUESTFS_STATUS_ERROR = 1
5557 const GUESTFS_ERROR_LEN = 256;
5559 struct guestfs_message_error {
5560 string error_message<GUESTFS_ERROR_LEN>;
5563 struct guestfs_message_header {
5564 unsigned prog; /* GUESTFS_PROGRAM */
5565 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5566 guestfs_procedure proc; /* GUESTFS_PROC_x */
5567 guestfs_message_direction direction;
5568 unsigned serial; /* message serial number */
5569 guestfs_message_status status;
5572 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5574 struct guestfs_chunk {
5575 int cancel; /* if non-zero, transfer is cancelled */
5576 /* data size is 0 bytes if the transfer has finished successfully */
5577 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5581 (* Generate the guestfs-structs.h file. *)
5582 and generate_structs_h () =
5583 generate_header CStyle LGPLv2plus;
5585 (* This is a public exported header file containing various
5586 * structures. The structures are carefully written to have
5587 * exactly the same in-memory format as the XDR structures that
5588 * we use on the wire to the daemon. The reason for creating
5589 * copies of these structures here is just so we don't have to
5590 * export the whole of guestfs_protocol.h (which includes much
5591 * unrelated and XDR-dependent stuff that we don't want to be
5592 * public, or required by clients).
5594 * To reiterate, we will pass these structures to and from the
5595 * client with a simple assignment or memcpy, so the format
5596 * must be identical to what rpcgen / the RFC defines.
5599 (* Public structures. *)
5602 pr "struct guestfs_%s {\n" typ;
5605 | name, FChar -> pr " char %s;\n" name
5606 | name, FString -> pr " char *%s;\n" name
5608 pr " uint32_t %s_len;\n" name;
5609 pr " char *%s;\n" name
5610 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5611 | name, FUInt32 -> pr " uint32_t %s;\n" name
5612 | name, FInt32 -> pr " int32_t %s;\n" name
5613 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5614 | name, FInt64 -> pr " int64_t %s;\n" name
5615 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5619 pr "struct guestfs_%s_list {\n" typ;
5620 pr " uint32_t len;\n";
5621 pr " struct guestfs_%s *val;\n" typ;
5624 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5625 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5629 (* Generate the guestfs-actions.h file. *)
5630 and generate_actions_h () =
5631 generate_header CStyle LGPLv2plus;
5633 fun (shortname, style, _, _, _, _, _) ->
5634 let name = "guestfs_" ^ shortname in
5635 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5639 (* Generate the guestfs-internal-actions.h file. *)
5640 and generate_internal_actions_h () =
5641 generate_header CStyle LGPLv2plus;
5643 fun (shortname, style, _, _, _, _, _) ->
5644 let name = "guestfs__" ^ shortname in
5645 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5647 ) non_daemon_functions
5649 (* Generate the client-side dispatch stubs. *)
5650 and generate_client_actions () =
5651 generate_header CStyle LGPLv2plus;
5658 #include <inttypes.h>
5660 #include \"guestfs.h\"
5661 #include \"guestfs-internal.h\"
5662 #include \"guestfs-internal-actions.h\"
5663 #include \"guestfs_protocol.h\"
5665 #define error guestfs_error
5666 //#define perrorf guestfs_perrorf
5667 #define safe_malloc guestfs_safe_malloc
5668 #define safe_realloc guestfs_safe_realloc
5669 //#define safe_strdup guestfs_safe_strdup
5670 #define safe_memdup guestfs_safe_memdup
5672 /* Check the return message from a call for validity. */
5674 check_reply_header (guestfs_h *g,
5675 const struct guestfs_message_header *hdr,
5676 unsigned int proc_nr, unsigned int serial)
5678 if (hdr->prog != GUESTFS_PROGRAM) {
5679 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5682 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5683 error (g, \"wrong protocol version (%%d/%%d)\",
5684 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5687 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5688 error (g, \"unexpected message direction (%%d/%%d)\",
5689 hdr->direction, GUESTFS_DIRECTION_REPLY);
5692 if (hdr->proc != proc_nr) {
5693 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5696 if (hdr->serial != serial) {
5697 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5704 /* Check we are in the right state to run a high-level action. */
5706 check_state (guestfs_h *g, const char *caller)
5708 if (!guestfs__is_ready (g)) {
5709 if (guestfs__is_config (g) || guestfs__is_launching (g))
5710 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5713 error (g, \"%%s called from the wrong state, %%d != READY\",
5714 caller, guestfs__get_state (g));
5722 (* Generate code to generate guestfish call traces. *)
5723 let trace_call shortname style =
5724 pr " if (guestfs__get_trace (g)) {\n";
5727 List.exists (function
5728 | StringList _ | DeviceList _ -> true
5729 | _ -> false) (snd style) in
5735 pr " printf (\"%s\");\n" shortname;
5738 | String n (* strings *)
5744 (* guestfish doesn't support string escaping, so neither do we *)
5745 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5746 | OptString n -> (* string option *)
5747 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5748 pr " else printf (\" null\");\n"
5750 | DeviceList n -> (* string list *)
5751 pr " putchar (' ');\n";
5752 pr " putchar ('\"');\n";
5753 pr " for (i = 0; %s[i]; ++i) {\n" n;
5754 pr " if (i > 0) putchar (' ');\n";
5755 pr " fputs (%s[i], stdout);\n" n;
5757 pr " putchar ('\"');\n";
5758 | Bool n -> (* boolean *)
5759 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5760 | Int n -> (* int *)
5761 pr " printf (\" %%d\", %s);\n" n
5763 pr " printf (\" %%\" PRIi64, %s);\n" n
5765 pr " putchar ('\\n');\n";
5770 (* For non-daemon functions, generate a wrapper around each function. *)
5772 fun (shortname, style, _, _, _, _, _) ->
5773 let name = "guestfs_" ^ shortname in
5775 generate_prototype ~extern:false ~semicolon:false ~newline:true
5776 ~handle:"g" name style;
5778 trace_call shortname style;
5779 pr " return guestfs__%s " shortname;
5780 generate_c_call_args ~handle:"g" style;
5784 ) non_daemon_functions;
5786 (* Client-side stubs for each function. *)
5788 fun (shortname, style, _, _, _, _, _) ->
5789 let name = "guestfs_" ^ shortname in
5791 (* Generate the action stub. *)
5792 generate_prototype ~extern:false ~semicolon:false ~newline:true
5793 ~handle:"g" name style;
5796 match fst style with
5797 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5798 | RConstString _ | RConstOptString _ ->
5799 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5800 | RString _ | RStringList _
5801 | RStruct _ | RStructList _
5802 | RHashtable _ | RBufferOut _ ->
5807 (match snd style with
5809 | _ -> pr " struct %s_args args;\n" name
5812 pr " guestfs_message_header hdr;\n";
5813 pr " guestfs_message_error err;\n";
5815 match fst style with
5817 | RConstString _ | RConstOptString _ ->
5818 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5820 | RBool _ | RString _ | RStringList _
5821 | RStruct _ | RStructList _
5822 | RHashtable _ | RBufferOut _ ->
5823 pr " struct %s_ret ret;\n" name;
5826 pr " int serial;\n";
5829 trace_call shortname style;
5830 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5831 shortname error_code;
5832 pr " guestfs___set_busy (g);\n";
5835 (* Send the main header and arguments. *)
5836 (match snd style with
5838 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5839 (String.uppercase shortname)
5843 | Pathname n | Device n | Dev_or_Path n | String n ->
5844 pr " args.%s = (char *) %s;\n" n n
5846 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5847 | StringList n | DeviceList n ->
5848 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5849 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5851 pr " args.%s = %s;\n" n n
5853 pr " args.%s = %s;\n" n n
5855 pr " args.%s = %s;\n" n n
5856 | FileIn _ | FileOut _ -> ()
5858 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5859 (String.uppercase shortname);
5860 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5863 pr " if (serial == -1) {\n";
5864 pr " guestfs___end_busy (g);\n";
5865 pr " return %s;\n" error_code;
5869 (* Send any additional files (FileIn) requested. *)
5870 let need_read_reply_label = ref false in
5874 pr " r = guestfs___send_file (g, %s);\n" n;
5875 pr " if (r == -1) {\n";
5876 pr " guestfs___end_busy (g);\n";
5877 pr " return %s;\n" error_code;
5879 pr " if (r == -2) /* daemon cancelled */\n";
5880 pr " goto read_reply;\n";
5881 need_read_reply_label := true;
5886 (* Wait for the reply from the remote end. *)
5887 if !need_read_reply_label then pr " read_reply:\n";
5888 pr " memset (&hdr, 0, sizeof hdr);\n";
5889 pr " memset (&err, 0, sizeof err);\n";
5890 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5892 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5896 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5899 pr " if (r == -1) {\n";
5900 pr " guestfs___end_busy (g);\n";
5901 pr " return %s;\n" error_code;
5905 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5906 (String.uppercase shortname);
5907 pr " guestfs___end_busy (g);\n";
5908 pr " return %s;\n" error_code;
5912 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5913 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5914 pr " free (err.error_message);\n";
5915 pr " guestfs___end_busy (g);\n";
5916 pr " return %s;\n" error_code;
5920 (* Expecting to receive further files (FileOut)? *)
5924 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5925 pr " guestfs___end_busy (g);\n";
5926 pr " return %s;\n" error_code;
5932 pr " guestfs___end_busy (g);\n";
5934 (match fst style with
5935 | RErr -> pr " return 0;\n"
5936 | RInt n | RInt64 n | RBool n ->
5937 pr " return ret.%s;\n" n
5938 | RConstString _ | RConstOptString _ ->
5939 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5941 pr " return ret.%s; /* caller will free */\n" n
5942 | RStringList n | RHashtable n ->
5943 pr " /* caller will free this, but we need to add a NULL entry */\n";
5944 pr " ret.%s.%s_val =\n" n n;
5945 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5946 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5948 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5949 pr " return ret.%s.%s_val;\n" n n
5951 pr " /* caller will free this */\n";
5952 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5953 | RStructList (n, _) ->
5954 pr " /* caller will free this */\n";
5955 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5957 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5958 pr " * _val might be NULL here. To make the API saner for\n";
5959 pr " * callers, we turn this case into a unique pointer (using\n";
5960 pr " * malloc(1)).\n";
5962 pr " if (ret.%s.%s_len > 0) {\n" n n;
5963 pr " *size_r = ret.%s.%s_len;\n" n n;
5964 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5966 pr " free (ret.%s.%s_val);\n" n n;
5967 pr " char *p = safe_malloc (g, 1);\n";
5968 pr " *size_r = ret.%s.%s_len;\n" n n;
5976 (* Functions to free structures. *)
5977 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5978 pr " * structure format is identical to the XDR format. See note in\n";
5979 pr " * generator.ml.\n";
5986 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5988 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5994 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5996 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6003 (* Generate daemon/actions.h. *)
6004 and generate_daemon_actions_h () =
6005 generate_header CStyle GPLv2plus;
6007 pr "#include \"../src/guestfs_protocol.h\"\n";
6011 fun (name, style, _, _, _, _, _) ->
6013 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6017 (* Generate the linker script which controls the visibility of
6018 * symbols in the public ABI and ensures no other symbols get
6019 * exported accidentally.
6021 and generate_linker_script () =
6022 generate_header HashStyle GPLv2plus;
6027 "guestfs_get_error_handler";
6028 "guestfs_get_out_of_memory_handler";
6029 "guestfs_last_error";
6030 "guestfs_set_error_handler";
6031 "guestfs_set_launch_done_callback";
6032 "guestfs_set_log_message_callback";
6033 "guestfs_set_out_of_memory_handler";
6034 "guestfs_set_subprocess_quit_callback";
6036 (* Unofficial parts of the API: the bindings code use these
6037 * functions, so it is useful to export them.
6039 "guestfs_safe_calloc";
6040 "guestfs_safe_malloc";
6043 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6047 List.map (fun (typ, _) ->
6048 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6051 let globals = List.sort compare (globals @ functions @ structs) in
6055 List.iter (pr " %s;\n") globals;
6062 (* Generate the server-side stubs. *)
6063 and generate_daemon_actions () =
6064 generate_header CStyle GPLv2plus;
6066 pr "#include <config.h>\n";
6068 pr "#include <stdio.h>\n";
6069 pr "#include <stdlib.h>\n";
6070 pr "#include <string.h>\n";
6071 pr "#include <inttypes.h>\n";
6072 pr "#include <rpc/types.h>\n";
6073 pr "#include <rpc/xdr.h>\n";
6075 pr "#include \"daemon.h\"\n";
6076 pr "#include \"c-ctype.h\"\n";
6077 pr "#include \"../src/guestfs_protocol.h\"\n";
6078 pr "#include \"actions.h\"\n";
6082 fun (name, style, _, _, _, _, _) ->
6083 (* Generate server-side stubs. *)
6084 pr "static void %s_stub (XDR *xdr_in)\n" name;
6087 match fst style with
6088 | RErr | RInt _ -> pr " int r;\n"; "-1"
6089 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6090 | RBool _ -> pr " int r;\n"; "-1"
6091 | RConstString _ | RConstOptString _ ->
6092 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6093 | RString _ -> pr " char *r;\n"; "NULL"
6094 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6095 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6096 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6098 pr " size_t size = 1;\n";
6102 (match snd style with
6105 pr " struct guestfs_%s_args args;\n" name;
6108 | Device n | Dev_or_Path n
6111 | OptString n -> pr " char *%s;\n" n
6112 | StringList n | DeviceList n -> pr " char **%s;\n" n
6113 | Bool n -> pr " int %s;\n" n
6114 | Int n -> pr " int %s;\n" n
6115 | Int64 n -> pr " int64_t %s;\n" n
6116 | FileIn _ | FileOut _ -> ()
6122 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6124 (match snd style with
6127 pr " memset (&args, 0, sizeof args);\n";
6129 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6131 pr " cancel_receive ();\n";
6132 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6136 pr " char *%s = args.%s;\n" n n
6138 let pr_list_handling_code n =
6139 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6140 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6141 pr " if (%s == NULL) {\n" n;
6143 pr " cancel_receive ();\n";
6144 pr " reply_with_perror (\"realloc\");\n";
6147 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6148 pr " args.%s.%s_val = %s;\n" n n n;
6154 pr " ABS_PATH (%s, %s, goto done);\n"
6155 n (if is_filein then "cancel_receive ()" else "");
6158 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6159 n (if is_filein then "cancel_receive ()" else "");
6162 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6163 n (if is_filein then "cancel_receive ()" else "");
6164 | String n -> pr_args n
6165 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6167 pr_list_handling_code n;
6169 pr_list_handling_code n;
6170 pr " /* Ensure that each is a device,\n";
6171 pr " * and perform device name translation. */\n";
6172 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6173 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6174 (if is_filein then "cancel_receive ()" else "");
6176 | Bool n -> pr " %s = args.%s;\n" n n
6177 | Int n -> pr " %s = args.%s;\n" n n
6178 | Int64 n -> pr " %s = args.%s;\n" n n
6179 | FileIn _ | FileOut _ -> ()
6185 (* this is used at least for do_equal *)
6186 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6187 (* Emit NEED_ROOT just once, even when there are two or
6188 more Pathname args *)
6189 pr " NEED_ROOT (%s, goto done);\n"
6190 (if is_filein then "cancel_receive ()" else "");
6193 (* Don't want to call the impl with any FileIn or FileOut
6194 * parameters, since these go "outside" the RPC protocol.
6197 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6199 pr " r = do_%s " name;
6200 generate_c_call_args (fst style, args');
6203 (match fst style with
6204 | RErr | RInt _ | RInt64 _ | RBool _
6205 | RConstString _ | RConstOptString _
6206 | RString _ | RStringList _ | RHashtable _
6207 | RStruct (_, _) | RStructList (_, _) ->
6208 pr " if (r == %s)\n" error_code;
6209 pr " /* do_%s has already called reply_with_error */\n" name;
6213 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6214 pr " * an ordinary zero-length buffer), so be careful ...\n";
6216 pr " if (size == 1 && r == %s)\n" error_code;
6217 pr " /* do_%s has already called reply_with_error */\n" name;
6222 (* If there are any FileOut parameters, then the impl must
6223 * send its own reply.
6226 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6228 pr " /* do_%s has already sent a reply */\n" name
6230 match fst style with
6231 | RErr -> pr " reply (NULL, NULL);\n"
6232 | RInt n | RInt64 n | RBool n ->
6233 pr " struct guestfs_%s_ret ret;\n" name;
6234 pr " ret.%s = r;\n" n;
6235 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6237 | RConstString _ | RConstOptString _ ->
6238 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6240 pr " struct guestfs_%s_ret ret;\n" name;
6241 pr " ret.%s = r;\n" n;
6242 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6245 | RStringList n | RHashtable n ->
6246 pr " struct guestfs_%s_ret ret;\n" name;
6247 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6248 pr " ret.%s.%s_val = r;\n" n n;
6249 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6251 pr " free_strings (r);\n"
6253 pr " struct guestfs_%s_ret ret;\n" name;
6254 pr " ret.%s = *r;\n" n;
6255 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6257 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6259 | RStructList (n, _) ->
6260 pr " struct guestfs_%s_ret ret;\n" name;
6261 pr " ret.%s = *r;\n" n;
6262 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6264 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6267 pr " struct guestfs_%s_ret ret;\n" name;
6268 pr " ret.%s.%s_val = r;\n" n n;
6269 pr " ret.%s.%s_len = size;\n" n n;
6270 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6275 (* Free the args. *)
6277 (match snd style with
6280 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6287 (* Dispatch function. *)
6288 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6290 pr " switch (proc_nr) {\n";
6293 fun (name, style, _, _, _, _, _) ->
6294 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6295 pr " %s_stub (xdr_in);\n" name;
6300 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";
6305 (* LVM columns and tokenization functions. *)
6306 (* XXX This generates crap code. We should rethink how we
6312 pr "static const char *lvm_%s_cols = \"%s\";\n"
6313 typ (String.concat "," (List.map fst cols));
6316 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6318 pr " char *tok, *p, *next;\n";
6322 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6325 pr " if (!str) {\n";
6326 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6329 pr " if (!*str || c_isspace (*str)) {\n";
6330 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6335 fun (name, coltype) ->
6336 pr " if (!tok) {\n";
6337 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6340 pr " p = strchrnul (tok, ',');\n";
6341 pr " if (*p) next = p+1; else next = NULL;\n";
6342 pr " *p = '\\0';\n";
6345 pr " r->%s = strdup (tok);\n" name;
6346 pr " if (r->%s == NULL) {\n" name;
6347 pr " perror (\"strdup\");\n";
6351 pr " for (i = j = 0; i < 32; ++j) {\n";
6352 pr " if (tok[j] == '\\0') {\n";
6353 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6355 pr " } else if (tok[j] != '-')\n";
6356 pr " r->%s[i++] = tok[j];\n" name;
6359 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6360 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6364 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6365 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6369 pr " if (tok[0] == '\\0')\n";
6370 pr " r->%s = -1;\n" name;
6371 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6372 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6375 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6376 assert false (* can never be an LVM column *)
6378 pr " tok = next;\n";
6381 pr " if (tok != NULL) {\n";
6382 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6389 pr "guestfs_int_lvm_%s_list *\n" typ;
6390 pr "parse_command_line_%ss (void)\n" typ;
6392 pr " char *out, *err;\n";
6393 pr " char *p, *pend;\n";
6395 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6396 pr " void *newp;\n";
6398 pr " ret = malloc (sizeof *ret);\n";
6399 pr " if (!ret) {\n";
6400 pr " reply_with_perror (\"malloc\");\n";
6401 pr " return NULL;\n";
6404 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6405 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6407 pr " r = command (&out, &err,\n";
6408 pr " \"lvm\", \"%ss\",\n" typ;
6409 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6410 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6411 pr " if (r == -1) {\n";
6412 pr " reply_with_error (\"%%s\", err);\n";
6413 pr " free (out);\n";
6414 pr " free (err);\n";
6415 pr " free (ret);\n";
6416 pr " return NULL;\n";
6419 pr " free (err);\n";
6421 pr " /* Tokenize each line of the output. */\n";
6424 pr " while (p) {\n";
6425 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6426 pr " if (pend) {\n";
6427 pr " *pend = '\\0';\n";
6431 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6434 pr " if (!*p) { /* Empty line? Skip it. */\n";
6439 pr " /* Allocate some space to store this next entry. */\n";
6440 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6441 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6442 pr " if (newp == NULL) {\n";
6443 pr " reply_with_perror (\"realloc\");\n";
6444 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6445 pr " free (ret);\n";
6446 pr " free (out);\n";
6447 pr " return NULL;\n";
6449 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6451 pr " /* Tokenize the next entry. */\n";
6452 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6453 pr " if (r == -1) {\n";
6454 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6455 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6456 pr " free (ret);\n";
6457 pr " free (out);\n";
6458 pr " return NULL;\n";
6465 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6467 pr " free (out);\n";
6468 pr " return ret;\n";
6471 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6473 (* Generate a list of function names, for debugging in the daemon.. *)
6474 and generate_daemon_names () =
6475 generate_header CStyle GPLv2plus;
6477 pr "#include <config.h>\n";
6479 pr "#include \"daemon.h\"\n";
6482 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6483 pr "const char *function_names[] = {\n";
6485 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6489 (* Generate the optional groups for the daemon to implement
6490 * guestfs_available.
6492 and generate_daemon_optgroups_c () =
6493 generate_header CStyle GPLv2plus;
6495 pr "#include <config.h>\n";
6497 pr "#include \"daemon.h\"\n";
6498 pr "#include \"optgroups.h\"\n";
6501 pr "struct optgroup optgroups[] = {\n";
6504 pr " { \"%s\", optgroup_%s_available },\n" group group
6506 pr " { NULL, NULL }\n";
6509 and generate_daemon_optgroups_h () =
6510 generate_header CStyle GPLv2plus;
6514 pr "extern int optgroup_%s_available (void);\n" group
6517 (* Generate the tests. *)
6518 and generate_tests () =
6519 generate_header CStyle GPLv2plus;
6526 #include <sys/types.h>
6529 #include \"guestfs.h\"
6530 #include \"guestfs-internal.h\"
6532 static guestfs_h *g;
6533 static int suppress_error = 0;
6535 static void print_error (guestfs_h *g, void *data, const char *msg)
6537 if (!suppress_error)
6538 fprintf (stderr, \"%%s\\n\", msg);
6541 /* FIXME: nearly identical code appears in fish.c */
6542 static void print_strings (char *const *argv)
6546 for (argc = 0; argv[argc] != NULL; ++argc)
6547 printf (\"\\t%%s\\n\", argv[argc]);
6551 static void print_table (char const *const *argv)
6555 for (i = 0; argv[i] != NULL; i += 2)
6556 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6562 (* Generate a list of commands which are not tested anywhere. *)
6563 pr "static void no_test_warnings (void)\n";
6566 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6568 fun (_, _, _, _, tests, _, _) ->
6569 let tests = filter_map (
6571 | (_, (Always|If _|Unless _), test) -> Some test
6572 | (_, Disabled, _) -> None
6574 let seq = List.concat (List.map seq_of_test tests) in
6575 let cmds_tested = List.map List.hd seq in
6576 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6580 fun (name, _, _, _, _, _, _) ->
6581 if not (Hashtbl.mem hash name) then
6582 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6588 (* Generate the actual tests. Note that we generate the tests
6589 * in reverse order, deliberately, so that (in general) the
6590 * newest tests run first. This makes it quicker and easier to
6595 fun (name, _, _, flags, tests, _, _) ->
6596 mapi (generate_one_test name flags) tests
6597 ) (List.rev all_functions) in
6598 let test_names = List.concat test_names in
6599 let nr_tests = List.length test_names in
6602 int main (int argc, char *argv[])
6605 unsigned long int n_failed = 0;
6606 const char *filename;
6608 int nr_tests, test_num = 0;
6610 setbuf (stdout, NULL);
6612 no_test_warnings ();
6614 g = guestfs_create ();
6616 printf (\"guestfs_create FAILED\\n\");
6617 exit (EXIT_FAILURE);
6620 guestfs_set_error_handler (g, print_error, NULL);
6622 guestfs_set_path (g, \"../appliance\");
6624 filename = \"test1.img\";
6625 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6628 exit (EXIT_FAILURE);
6630 if (lseek (fd, %d, SEEK_SET) == -1) {
6634 exit (EXIT_FAILURE);
6636 if (write (fd, &c, 1) == -1) {
6640 exit (EXIT_FAILURE);
6642 if (close (fd) == -1) {
6645 exit (EXIT_FAILURE);
6647 if (guestfs_add_drive (g, filename) == -1) {
6648 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6649 exit (EXIT_FAILURE);
6652 filename = \"test2.img\";
6653 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6656 exit (EXIT_FAILURE);
6658 if (lseek (fd, %d, SEEK_SET) == -1) {
6662 exit (EXIT_FAILURE);
6664 if (write (fd, &c, 1) == -1) {
6668 exit (EXIT_FAILURE);
6670 if (close (fd) == -1) {
6673 exit (EXIT_FAILURE);
6675 if (guestfs_add_drive (g, filename) == -1) {
6676 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6677 exit (EXIT_FAILURE);
6680 filename = \"test3.img\";
6681 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6684 exit (EXIT_FAILURE);
6686 if (lseek (fd, %d, SEEK_SET) == -1) {
6690 exit (EXIT_FAILURE);
6692 if (write (fd, &c, 1) == -1) {
6696 exit (EXIT_FAILURE);
6698 if (close (fd) == -1) {
6701 exit (EXIT_FAILURE);
6703 if (guestfs_add_drive (g, filename) == -1) {
6704 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6705 exit (EXIT_FAILURE);
6708 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6709 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6710 exit (EXIT_FAILURE);
6713 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6716 if (guestfs_launch (g) == -1) {
6717 printf (\"guestfs_launch FAILED\\n\");
6718 exit (EXIT_FAILURE);
6721 /* Cancel previous alarm. */
6726 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6730 pr " test_num++;\n";
6731 pr " if (guestfs_get_verbose (g))\n";
6732 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6733 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6734 pr " if (%s () == -1) {\n" test_name;
6735 pr " printf (\"%s FAILED\\n\");\n" test_name;
6736 pr " n_failed++;\n";
6741 pr " guestfs_close (g);\n";
6742 pr " unlink (\"test1.img\");\n";
6743 pr " unlink (\"test2.img\");\n";
6744 pr " unlink (\"test3.img\");\n";
6747 pr " if (n_failed > 0) {\n";
6748 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6749 pr " exit (EXIT_FAILURE);\n";
6753 pr " exit (EXIT_SUCCESS);\n";
6756 and generate_one_test name flags i (init, prereq, test) =
6757 let test_name = sprintf "test_%s_%d" name i in
6760 static int %s_skip (void)
6764 str = getenv (\"TEST_ONLY\");
6766 return strstr (str, \"%s\") == NULL;
6767 str = getenv (\"SKIP_%s\");
6768 if (str && STREQ (str, \"1\")) return 1;
6769 str = getenv (\"SKIP_TEST_%s\");
6770 if (str && STREQ (str, \"1\")) return 1;
6774 " test_name name (String.uppercase test_name) (String.uppercase name);
6777 | Disabled | Always -> ()
6778 | If code | Unless code ->
6779 pr "static int %s_prereq (void)\n" test_name;
6787 static int %s (void)
6790 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6794 " test_name test_name test_name;
6796 (* Optional functions should only be tested if the relevant
6797 * support is available in the daemon.
6803 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6805 pr " suppress_error = 1;\n";
6806 pr " r = guestfs_available (g, (char **) groups);\n";
6807 pr " suppress_error = 0;\n";
6808 pr " if (r == -1) {\n";
6809 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6818 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6820 pr " if (! %s_prereq ()) {\n" test_name;
6821 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6825 generate_one_test_body name i test_name init test;
6827 pr " if (%s_prereq ()) {\n" test_name;
6828 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6832 generate_one_test_body name i test_name init test;
6834 generate_one_test_body name i test_name init test
6842 and generate_one_test_body name i test_name init test =
6844 | InitNone (* XXX at some point, InitNone and InitEmpty became
6845 * folded together as the same thing. Really we should
6846 * make InitNone do nothing at all, but the tests may
6847 * need to be checked to make sure this is OK.
6850 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6851 List.iter (generate_test_command_call test_name)
6852 [["blockdev_setrw"; "/dev/sda"];
6856 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6857 List.iter (generate_test_command_call test_name)
6858 [["blockdev_setrw"; "/dev/sda"];
6861 ["part_disk"; "/dev/sda"; "mbr"]]
6863 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6864 List.iter (generate_test_command_call test_name)
6865 [["blockdev_setrw"; "/dev/sda"];
6868 ["part_disk"; "/dev/sda"; "mbr"];
6869 ["mkfs"; "ext2"; "/dev/sda1"];
6870 ["mount_options"; ""; "/dev/sda1"; "/"]]
6871 | InitBasicFSonLVM ->
6872 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6874 List.iter (generate_test_command_call test_name)
6875 [["blockdev_setrw"; "/dev/sda"];
6878 ["part_disk"; "/dev/sda"; "mbr"];
6879 ["pvcreate"; "/dev/sda1"];
6880 ["vgcreate"; "VG"; "/dev/sda1"];
6881 ["lvcreate"; "LV"; "VG"; "8"];
6882 ["mkfs"; "ext2"; "/dev/VG/LV"];
6883 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6885 pr " /* InitISOFS for %s */\n" test_name;
6886 List.iter (generate_test_command_call test_name)
6887 [["blockdev_setrw"; "/dev/sda"];
6890 ["mount_ro"; "/dev/sdd"; "/"]]
6893 let get_seq_last = function
6895 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6898 let seq = List.rev seq in
6899 List.rev (List.tl seq), List.hd seq
6904 pr " /* TestRun for %s (%d) */\n" name i;
6905 List.iter (generate_test_command_call test_name) seq
6906 | TestOutput (seq, expected) ->
6907 pr " /* TestOutput for %s (%d) */\n" name i;
6908 pr " const char *expected = \"%s\";\n" (c_quote expected);
6909 let seq, last = get_seq_last seq in
6911 pr " if (STRNEQ (r, expected)) {\n";
6912 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6916 List.iter (generate_test_command_call test_name) seq;
6917 generate_test_command_call ~test test_name last
6918 | TestOutputList (seq, expected) ->
6919 pr " /* TestOutputList for %s (%d) */\n" name i;
6920 let seq, last = get_seq_last seq in
6924 pr " if (!r[%d]) {\n" i;
6925 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6926 pr " print_strings (r);\n";
6930 pr " const char *expected = \"%s\";\n" (c_quote str);
6931 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6932 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6937 pr " if (r[%d] != NULL) {\n" (List.length expected);
6938 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6940 pr " print_strings (r);\n";
6944 List.iter (generate_test_command_call test_name) seq;
6945 generate_test_command_call ~test test_name last
6946 | TestOutputListOfDevices (seq, expected) ->
6947 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6948 let seq, last = get_seq_last seq in
6952 pr " if (!r[%d]) {\n" i;
6953 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6954 pr " print_strings (r);\n";
6958 pr " const char *expected = \"%s\";\n" (c_quote str);
6959 pr " r[%d][5] = 's';\n" i;
6960 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6961 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6966 pr " if (r[%d] != NULL) {\n" (List.length expected);
6967 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6969 pr " print_strings (r);\n";
6973 List.iter (generate_test_command_call test_name) seq;
6974 generate_test_command_call ~test test_name last
6975 | TestOutputInt (seq, expected) ->
6976 pr " /* TestOutputInt for %s (%d) */\n" name i;
6977 let seq, last = get_seq_last seq in
6979 pr " if (r != %d) {\n" expected;
6980 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6986 List.iter (generate_test_command_call test_name) seq;
6987 generate_test_command_call ~test test_name last
6988 | TestOutputIntOp (seq, op, expected) ->
6989 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6990 let seq, last = get_seq_last seq in
6992 pr " if (! (r %s %d)) {\n" op expected;
6993 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6994 test_name op expected;
6999 List.iter (generate_test_command_call test_name) seq;
7000 generate_test_command_call ~test test_name last
7001 | TestOutputTrue seq ->
7002 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7003 let seq, last = get_seq_last seq in
7006 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7011 List.iter (generate_test_command_call test_name) seq;
7012 generate_test_command_call ~test test_name last
7013 | TestOutputFalse seq ->
7014 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7015 let seq, last = get_seq_last seq in
7018 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7023 List.iter (generate_test_command_call test_name) seq;
7024 generate_test_command_call ~test test_name last
7025 | TestOutputLength (seq, expected) ->
7026 pr " /* TestOutputLength for %s (%d) */\n" name i;
7027 let seq, last = get_seq_last seq in
7030 pr " for (j = 0; j < %d; ++j)\n" expected;
7031 pr " if (r[j] == NULL) {\n";
7032 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7034 pr " print_strings (r);\n";
7037 pr " if (r[j] != NULL) {\n";
7038 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7040 pr " print_strings (r);\n";
7044 List.iter (generate_test_command_call test_name) seq;
7045 generate_test_command_call ~test test_name last
7046 | TestOutputBuffer (seq, expected) ->
7047 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7048 pr " const char *expected = \"%s\";\n" (c_quote expected);
7049 let seq, last = get_seq_last seq in
7050 let len = String.length expected in
7052 pr " if (size != %d) {\n" len;
7053 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7056 pr " if (STRNEQLEN (r, expected, size)) {\n";
7057 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7061 List.iter (generate_test_command_call test_name) seq;
7062 generate_test_command_call ~test test_name last
7063 | TestOutputStruct (seq, checks) ->
7064 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7065 let seq, last = get_seq_last seq in
7069 | CompareWithInt (field, expected) ->
7070 pr " if (r->%s != %d) {\n" field expected;
7071 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7072 test_name field expected;
7073 pr " (int) r->%s);\n" field;
7076 | CompareWithIntOp (field, op, expected) ->
7077 pr " if (!(r->%s %s %d)) {\n" field op expected;
7078 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7079 test_name field op expected;
7080 pr " (int) r->%s);\n" field;
7083 | CompareWithString (field, expected) ->
7084 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7085 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7086 test_name field expected;
7087 pr " r->%s);\n" field;
7090 | CompareFieldsIntEq (field1, field2) ->
7091 pr " if (r->%s != r->%s) {\n" field1 field2;
7092 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7093 test_name field1 field2;
7094 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7097 | CompareFieldsStrEq (field1, field2) ->
7098 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7099 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7100 test_name field1 field2;
7101 pr " r->%s, r->%s);\n" field1 field2;
7106 List.iter (generate_test_command_call test_name) seq;
7107 generate_test_command_call ~test test_name last
7108 | TestLastFail seq ->
7109 pr " /* TestLastFail for %s (%d) */\n" name i;
7110 let seq, last = get_seq_last seq in
7111 List.iter (generate_test_command_call test_name) seq;
7112 generate_test_command_call test_name ~expect_error:true last
7114 (* Generate the code to run a command, leaving the result in 'r'.
7115 * If you expect to get an error then you should set expect_error:true.
7117 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7119 | [] -> assert false
7121 (* Look up the command to find out what args/ret it has. *)
7124 let _, style, _, _, _, _, _ =
7125 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7128 failwithf "%s: in test, command %s was not found" test_name name in
7130 if List.length (snd style) <> List.length args then
7131 failwithf "%s: in test, wrong number of args given to %s"
7138 | OptString n, "NULL" -> ()
7141 | Dev_or_Path n, arg
7143 | OptString n, arg ->
7144 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7148 | FileIn _, _ | FileOut _, _ -> ()
7149 | StringList n, "" | DeviceList n, "" ->
7150 pr " const char *const %s[1] = { NULL };\n" n
7151 | StringList n, arg | DeviceList n, arg ->
7152 let strs = string_split " " arg in
7155 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7157 pr " const char *const %s[] = {\n" n;
7159 fun i _ -> pr " %s_%d,\n" n i
7163 ) (List.combine (snd style) args);
7166 match fst style with
7167 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7168 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7169 | RConstString _ | RConstOptString _ ->
7170 pr " const char *r;\n"; "NULL"
7171 | RString _ -> pr " char *r;\n"; "NULL"
7172 | RStringList _ | RHashtable _ ->
7176 | RStruct (_, typ) ->
7177 pr " struct guestfs_%s *r;\n" typ; "NULL"
7178 | RStructList (_, typ) ->
7179 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7182 pr " size_t size;\n";
7185 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7186 pr " r = guestfs_%s (g" name;
7188 (* Generate the parameters. *)
7191 | OptString _, "NULL" -> pr ", NULL"
7193 | Device n, _ | Dev_or_Path n, _
7197 | FileIn _, arg | FileOut _, arg ->
7198 pr ", \"%s\"" (c_quote arg)
7199 | StringList n, _ | DeviceList n, _ ->
7200 pr ", (char **) %s" n
7203 try int_of_string arg
7204 with Failure "int_of_string" ->
7205 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7209 try Int64.of_string arg
7210 with Failure "int_of_string" ->
7211 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7214 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7215 ) (List.combine (snd style) args);
7217 (match fst style with
7218 | RBufferOut _ -> pr ", &size"
7224 if not expect_error then
7225 pr " if (r == %s)\n" error_code
7227 pr " if (r != %s)\n" error_code;
7230 (* Insert the test code. *)
7236 (match fst style with
7237 | RErr | RInt _ | RInt64 _ | RBool _
7238 | RConstString _ | RConstOptString _ -> ()
7239 | RString _ | RBufferOut _ -> pr " free (r);\n"
7240 | RStringList _ | RHashtable _ ->
7241 pr " for (i = 0; r[i] != NULL; ++i)\n";
7242 pr " free (r[i]);\n";
7244 | RStruct (_, typ) ->
7245 pr " guestfs_free_%s (r);\n" typ
7246 | RStructList (_, typ) ->
7247 pr " guestfs_free_%s_list (r);\n" typ
7253 let str = replace_str str "\r" "\\r" in
7254 let str = replace_str str "\n" "\\n" in
7255 let str = replace_str str "\t" "\\t" in
7256 let str = replace_str str "\000" "\\0" in
7259 (* Generate a lot of different functions for guestfish. *)
7260 and generate_fish_cmds () =
7261 generate_header CStyle GPLv2plus;
7265 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7267 let all_functions_sorted =
7269 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7270 ) all_functions_sorted in
7272 pr "#include <config.h>\n";
7274 pr "#include <stdio.h>\n";
7275 pr "#include <stdlib.h>\n";
7276 pr "#include <string.h>\n";
7277 pr "#include <inttypes.h>\n";
7279 pr "#include <guestfs.h>\n";
7280 pr "#include \"c-ctype.h\"\n";
7281 pr "#include \"full-write.h\"\n";
7282 pr "#include \"xstrtol.h\"\n";
7283 pr "#include \"fish.h\"\n";
7286 (* list_commands function, which implements guestfish -h *)
7287 pr "void list_commands (void)\n";
7289 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7290 pr " list_builtin_commands ();\n";
7292 fun (name, _, _, flags, _, shortdesc, _) ->
7293 let name = replace_char name '_' '-' in
7294 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7296 ) all_functions_sorted;
7297 pr " printf (\" %%s\\n\",";
7298 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7302 (* display_command function, which implements guestfish -h cmd *)
7303 pr "void display_command (const char *cmd)\n";
7306 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7307 let name2 = replace_char name '_' '-' in
7309 try find_map (function FishAlias n -> Some n | _ -> None) flags
7310 with Not_found -> name in
7311 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7313 match snd style with
7317 name2 (String.concat " " (List.map name_of_argt args)) in
7320 if List.mem ProtocolLimitWarning flags then
7321 ("\n\n" ^ protocol_limit_warning)
7324 (* For DangerWillRobinson commands, we should probably have
7325 * guestfish prompt before allowing you to use them (especially
7326 * in interactive mode). XXX
7330 if List.mem DangerWillRobinson flags then
7331 ("\n\n" ^ danger_will_robinson)
7336 match deprecation_notice flags with
7338 | Some txt -> "\n\n" ^ txt in
7340 let describe_alias =
7341 if name <> alias then
7342 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7346 pr "STRCASEEQ (cmd, \"%s\")" name;
7347 if name <> name2 then
7348 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7349 if name <> alias then
7350 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7352 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7354 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7355 "=head1 DESCRIPTION\n\n" ^
7356 longdesc ^ warnings ^ describe_alias);
7359 pr " display_builtin_command (cmd);\n";
7363 let emit_print_list_function typ =
7364 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7367 pr " unsigned int i;\n";
7369 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7370 pr " printf (\"[%%d] = {\\n\", i);\n";
7371 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7372 pr " printf (\"}\\n\");\n";
7378 (* print_* functions *)
7382 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7384 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7387 pr " unsigned int i;\n";
7393 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7395 pr " printf (\"%%s%s: \", indent);\n" name;
7396 pr " for (i = 0; i < 32; ++i)\n";
7397 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7398 pr " printf (\"\\n\");\n"
7400 pr " printf (\"%%s%s: \", indent);\n" name;
7401 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7402 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7403 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7405 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7406 pr " printf (\"\\n\");\n"
7407 | name, (FUInt64|FBytes) ->
7408 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7411 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7414 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7417 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7420 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7422 | name, FOptPercent ->
7423 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7424 typ name name typ name;
7425 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7431 (* Emit a print_TYPE_list function definition only if that function is used. *)
7434 | typ, (RStructListOnly | RStructAndList) ->
7435 (* generate the function for typ *)
7436 emit_print_list_function typ
7437 | typ, _ -> () (* empty *)
7438 ) (rstructs_used_by all_functions);
7440 (* Emit a print_TYPE function definition only if that function is used. *)
7443 | typ, (RStructOnly | RStructAndList) ->
7444 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7446 pr " print_%s_indent (%s, \"\");\n" typ typ;
7449 | typ, _ -> () (* empty *)
7450 ) (rstructs_used_by all_functions);
7452 (* run_<action> actions *)
7454 fun (name, style, _, flags, _, _, _) ->
7455 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7457 (match fst style with
7460 | RBool _ -> pr " int r;\n"
7461 | RInt64 _ -> pr " int64_t r;\n"
7462 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7463 | RString _ -> pr " char *r;\n"
7464 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7465 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7466 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7469 pr " size_t size;\n";
7475 | OptString n -> pr " const char *%s;\n" n
7479 | FileOut n -> pr " char *%s;\n" n
7480 | StringList n | DeviceList n -> pr " char **%s;\n" n
7481 | Bool n -> pr " int %s;\n" n
7482 | Int n -> pr " int %s;\n" n
7483 | Int64 n -> pr " int64_t %s;\n" n
7486 (* Check and convert parameters. *)
7487 let argc_expected = List.length (snd style) in
7488 pr " if (argc != %d) {\n" argc_expected;
7489 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7491 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7495 let parse_integer fn fntyp rtyp range name i =
7497 pr " strtol_error xerr;\n";
7498 pr " %s r;\n" fntyp;
7500 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7501 pr " if (xerr != LONGINT_OK) {\n";
7502 pr " fprintf (stderr,\n";
7503 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7504 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7509 | Some (min, max, comment) ->
7510 pr " /* %s */\n" comment;
7511 pr " if (r < %s || r > %s) {\n" min max;
7512 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7516 pr " /* The check above should ensure this assignment does not overflow. */\n";
7518 pr " %s = r;\n" name;
7527 pr " %s = argv[%d];\n" name i
7529 | Dev_or_Path name ->
7530 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7531 pr " if (%s == NULL) return -1;\n" name
7533 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7536 pr " %s = file_in (argv[%d]);\n" name i;
7537 pr " if (%s == NULL) return -1;\n" name
7539 pr " %s = file_out (argv[%d]);\n" name i;
7540 pr " if (%s == NULL) return -1;\n" name
7541 | StringList name | DeviceList name ->
7542 pr " %s = parse_string_list (argv[%d]);\n" name i;
7543 pr " if (%s == NULL) return -1;\n" name;
7545 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7548 let min = "(-(2LL<<30))"
7549 and max = "((2LL<<30)-1)"
7551 "The Int type in the generator is a signed 31 bit int." in
7552 Some (min, max, comment) in
7553 parse_integer "xstrtoll" "long long" "int" range name i
7555 parse_integer "xstrtoll" "long long" "int64_t" None name i
7558 (* Call C API function. *)
7560 try find_map (function FishAction n -> Some n | _ -> None) flags
7561 with Not_found -> sprintf "guestfs_%s" name in
7563 generate_c_call_args ~handle:"g" style;
7568 | Device name | String name
7569 | OptString name | Bool name
7570 | Int name | Int64 name -> ()
7571 | Pathname name | Dev_or_Path name | FileOut name ->
7572 pr " free (%s);\n" name
7574 pr " free_file_in (%s);\n" name
7575 | StringList name | DeviceList name ->
7576 pr " free_strings (%s);\n" name
7579 (* Any output flags? *)
7581 let flags = filter_map (
7582 function FishOutput flag -> Some flag | _ -> None
7588 failwithf "%s: more than one FishOutput flag is not allowed" name in
7590 (* Check return value for errors and display command results. *)
7591 (match fst style with
7592 | RErr -> pr " return r;\n"
7594 pr " if (r == -1) return -1;\n";
7595 (match fish_output with
7597 pr " printf (\"%%d\\n\", r);\n";
7598 | Some FishOutputOctal ->
7599 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7600 | Some FishOutputHexadecimal ->
7601 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7604 pr " if (r == -1) return -1;\n";
7605 (match fish_output with
7607 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7608 | Some FishOutputOctal ->
7609 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7610 | Some FishOutputHexadecimal ->
7611 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7614 pr " if (r == -1) return -1;\n";
7615 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7618 pr " if (r == NULL) return -1;\n";
7619 pr " printf (\"%%s\\n\", r);\n";
7621 | RConstOptString _ ->
7622 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7625 pr " if (r == NULL) return -1;\n";
7626 pr " printf (\"%%s\\n\", r);\n";
7630 pr " if (r == NULL) return -1;\n";
7631 pr " print_strings (r);\n";
7632 pr " free_strings (r);\n";
7634 | RStruct (_, typ) ->
7635 pr " if (r == NULL) return -1;\n";
7636 pr " print_%s (r);\n" typ;
7637 pr " guestfs_free_%s (r);\n" typ;
7639 | RStructList (_, typ) ->
7640 pr " if (r == NULL) return -1;\n";
7641 pr " print_%s_list (r);\n" typ;
7642 pr " guestfs_free_%s_list (r);\n" typ;
7645 pr " if (r == NULL) return -1;\n";
7646 pr " print_table (r);\n";
7647 pr " free_strings (r);\n";
7650 pr " if (r == NULL) return -1;\n";
7651 pr " if (full_write (1, r, size) != size) {\n";
7652 pr " perror (\"write\");\n";
7663 (* run_action function *)
7664 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7667 fun (name, _, _, flags, _, _, _) ->
7668 let name2 = replace_char name '_' '-' in
7670 try find_map (function FishAlias n -> Some n | _ -> None) flags
7671 with Not_found -> name in
7673 pr "STRCASEEQ (cmd, \"%s\")" name;
7674 if name <> name2 then
7675 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7676 if name <> alias then
7677 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7679 pr " return run_%s (cmd, argc, argv);\n" name;
7683 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7684 pr " if (command_num == 1)\n";
7685 pr " extended_help_message ();\n";
7692 (* Readline completion for guestfish. *)
7693 and generate_fish_completion () =
7694 generate_header CStyle GPLv2plus;
7698 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7708 #ifdef HAVE_LIBREADLINE
7709 #include <readline/readline.h>
7714 #ifdef HAVE_LIBREADLINE
7716 static const char *const commands[] = {
7717 BUILTIN_COMMANDS_FOR_COMPLETION,
7720 (* Get the commands, including the aliases. They don't need to be
7721 * sorted - the generator() function just does a dumb linear search.
7725 fun (name, _, _, flags, _, _, _) ->
7726 let name2 = replace_char name '_' '-' in
7728 try find_map (function FishAlias n -> Some n | _ -> None) flags
7729 with Not_found -> name in
7731 if name <> alias then [name2; alias] else [name2]
7733 let commands = List.flatten commands in
7735 List.iter (pr " \"%s\",\n") commands;
7741 generator (const char *text, int state)
7743 static int index, len;
7748 len = strlen (text);
7751 rl_attempted_completion_over = 1;
7753 while ((name = commands[index]) != NULL) {
7755 if (STRCASEEQLEN (name, text, len))
7756 return strdup (name);
7762 #endif /* HAVE_LIBREADLINE */
7764 #ifdef HAVE_RL_COMPLETION_MATCHES
7765 #define RL_COMPLETION_MATCHES rl_completion_matches
7767 #ifdef HAVE_COMPLETION_MATCHES
7768 #define RL_COMPLETION_MATCHES completion_matches
7770 #endif /* else just fail if we don't have either symbol */
7773 do_completion (const char *text, int start, int end)
7775 char **matches = NULL;
7777 #ifdef HAVE_LIBREADLINE
7778 rl_completion_append_character = ' ';
7781 matches = RL_COMPLETION_MATCHES (text, generator);
7782 else if (complete_dest_paths)
7783 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7790 (* Generate the POD documentation for guestfish. *)
7791 and generate_fish_actions_pod () =
7792 let all_functions_sorted =
7794 fun (_, _, _, flags, _, _, _) ->
7795 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7796 ) all_functions_sorted in
7798 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7801 fun (name, style, _, flags, _, _, longdesc) ->
7803 Str.global_substitute rex (
7806 try Str.matched_group 1 s
7808 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7809 "C<" ^ replace_char sub '_' '-' ^ ">"
7811 let name = replace_char name '_' '-' in
7813 try find_map (function FishAlias n -> Some n | _ -> None) flags
7814 with Not_found -> name in
7816 pr "=head2 %s" name;
7817 if name <> alias then
7824 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7825 | OptString n -> pr " %s" n
7826 | StringList n | DeviceList n -> pr " '%s ...'" n
7827 | Bool _ -> pr " true|false"
7828 | Int n -> pr " %s" n
7829 | Int64 n -> pr " %s" n
7830 | FileIn n | FileOut n -> pr " (%s|-)" n
7834 pr "%s\n\n" longdesc;
7836 if List.exists (function FileIn _ | FileOut _ -> true
7837 | _ -> false) (snd style) then
7838 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7840 if List.mem ProtocolLimitWarning flags then
7841 pr "%s\n\n" protocol_limit_warning;
7843 if List.mem DangerWillRobinson flags then
7844 pr "%s\n\n" danger_will_robinson;
7846 match deprecation_notice flags with
7848 | Some txt -> pr "%s\n\n" txt
7849 ) all_functions_sorted
7851 (* Generate a C function prototype. *)
7852 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7853 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7855 ?handle name style =
7856 if extern then pr "extern ";
7857 if static then pr "static ";
7858 (match fst style with
7860 | RInt _ -> pr "int "
7861 | RInt64 _ -> pr "int64_t "
7862 | RBool _ -> pr "int "
7863 | RConstString _ | RConstOptString _ -> pr "const char *"
7864 | RString _ | RBufferOut _ -> pr "char *"
7865 | RStringList _ | RHashtable _ -> pr "char **"
7866 | RStruct (_, typ) ->
7867 if not in_daemon then pr "struct guestfs_%s *" typ
7868 else pr "guestfs_int_%s *" typ
7869 | RStructList (_, typ) ->
7870 if not in_daemon then pr "struct guestfs_%s_list *" typ
7871 else pr "guestfs_int_%s_list *" typ
7873 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7874 pr "%s%s (" prefix name;
7875 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7878 let comma = ref false in
7881 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7885 if single_line then pr ", " else pr ",\n\t\t"
7892 | Device n | Dev_or_Path n
7896 pr "const char *%s" n
7897 | StringList n | DeviceList n ->
7899 pr "char *const *%s" n
7900 | Bool n -> next (); pr "int %s" n
7901 | Int n -> next (); pr "int %s" n
7902 | Int64 n -> next (); pr "int64_t %s" n
7905 if not in_daemon then (next (); pr "const char *%s" n)
7907 if is_RBufferOut then (next (); pr "size_t *size_r");
7910 if semicolon then pr ";";
7911 if newline then pr "\n"
7913 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7914 and generate_c_call_args ?handle ?(decl = false) style =
7916 let comma = ref false in
7918 if !comma then pr ", ";
7923 | Some handle -> pr "%s" handle; comma := true
7928 pr "%s" (name_of_argt arg)
7930 (* For RBufferOut calls, add implicit &size parameter. *)
7932 match fst style with
7940 (* Generate the OCaml bindings interface. *)
7941 and generate_ocaml_mli () =
7942 generate_header OCamlStyle LGPLv2plus;
7945 (** For API documentation you should refer to the C API
7946 in the guestfs(3) manual page. The OCaml API uses almost
7947 exactly the same calls. *)
7950 (** A [guestfs_h] handle. *)
7952 exception Error of string
7953 (** This exception is raised when there is an error. *)
7955 exception Handle_closed of string
7956 (** This exception is raised if you use a {!Guestfs.t} handle
7957 after calling {!close} on it. The string is the name of
7960 val create : unit -> t
7961 (** Create a {!Guestfs.t} handle. *)
7963 val close : t -> unit
7964 (** Close the {!Guestfs.t} handle and free up all resources used
7967 Handles are closed by the garbage collector when they become
7968 unreferenced, but callers can call this in order to provide
7969 predictable cleanup. *)
7972 generate_ocaml_structure_decls ();
7976 fun (name, style, _, _, _, shortdesc, _) ->
7977 generate_ocaml_prototype name style;
7978 pr "(** %s *)\n" shortdesc;
7980 ) all_functions_sorted
7982 (* Generate the OCaml bindings implementation. *)
7983 and generate_ocaml_ml () =
7984 generate_header OCamlStyle LGPLv2plus;
7989 exception Error of string
7990 exception Handle_closed of string
7992 external create : unit -> t = \"ocaml_guestfs_create\"
7993 external close : t -> unit = \"ocaml_guestfs_close\"
7995 (* Give the exceptions names, so they can be raised from the C code. *)
7997 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7998 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8002 generate_ocaml_structure_decls ();
8006 fun (name, style, _, _, _, shortdesc, _) ->
8007 generate_ocaml_prototype ~is_external:true name style;
8008 ) all_functions_sorted
8010 (* Generate the OCaml bindings C implementation. *)
8011 and generate_ocaml_c () =
8012 generate_header CStyle LGPLv2plus;
8019 #include <caml/config.h>
8020 #include <caml/alloc.h>
8021 #include <caml/callback.h>
8022 #include <caml/fail.h>
8023 #include <caml/memory.h>
8024 #include <caml/mlvalues.h>
8025 #include <caml/signals.h>
8027 #include <guestfs.h>
8029 #include \"guestfs_c.h\"
8031 /* Copy a hashtable of string pairs into an assoc-list. We return
8032 * the list in reverse order, but hashtables aren't supposed to be
8035 static CAMLprim value
8036 copy_table (char * const * argv)
8039 CAMLlocal5 (rv, pairv, kv, vv, cons);
8043 for (i = 0; argv[i] != NULL; i += 2) {
8044 kv = caml_copy_string (argv[i]);
8045 vv = caml_copy_string (argv[i+1]);
8046 pairv = caml_alloc (2, 0);
8047 Store_field (pairv, 0, kv);
8048 Store_field (pairv, 1, vv);
8049 cons = caml_alloc (2, 0);
8050 Store_field (cons, 1, rv);
8052 Store_field (cons, 0, pairv);
8060 (* Struct copy functions. *)
8062 let emit_ocaml_copy_list_function typ =
8063 pr "static CAMLprim value\n";
8064 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8066 pr " CAMLparam0 ();\n";
8067 pr " CAMLlocal2 (rv, v);\n";
8068 pr " unsigned int i;\n";
8070 pr " if (%ss->len == 0)\n" typ;
8071 pr " CAMLreturn (Atom (0));\n";
8073 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8074 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8075 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8076 pr " caml_modify (&Field (rv, i), v);\n";
8078 pr " CAMLreturn (rv);\n";
8086 let has_optpercent_col =
8087 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8089 pr "static CAMLprim value\n";
8090 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8092 pr " CAMLparam0 ();\n";
8093 if has_optpercent_col then
8094 pr " CAMLlocal3 (rv, v, v2);\n"
8096 pr " CAMLlocal2 (rv, v);\n";
8098 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8103 pr " v = caml_copy_string (%s->%s);\n" typ name
8105 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8106 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8109 pr " v = caml_alloc_string (32);\n";
8110 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8111 | name, (FBytes|FInt64|FUInt64) ->
8112 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8113 | name, (FInt32|FUInt32) ->
8114 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8115 | name, FOptPercent ->
8116 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8117 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8118 pr " v = caml_alloc (1, 0);\n";
8119 pr " Store_field (v, 0, v2);\n";
8120 pr " } else /* None */\n";
8121 pr " v = Val_int (0);\n";
8123 pr " v = Val_int (%s->%s);\n" typ name
8125 pr " Store_field (rv, %d, v);\n" i
8127 pr " CAMLreturn (rv);\n";
8132 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8135 | typ, (RStructListOnly | RStructAndList) ->
8136 (* generate the function for typ *)
8137 emit_ocaml_copy_list_function typ
8138 | typ, _ -> () (* empty *)
8139 ) (rstructs_used_by all_functions);
8143 fun (name, style, _, _, _, _, _) ->
8144 pr "/* Automatically generated wrapper for function\n";
8146 generate_ocaml_prototype name style;
8151 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8153 let needs_extra_vs =
8154 match fst style with RConstOptString _ -> true | _ -> false in
8156 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8157 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8158 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8161 pr "CAMLprim value\n";
8162 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8163 List.iter (pr ", value %s") (List.tl params);
8168 | [p1; p2; p3; p4; p5] ->
8169 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8170 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8171 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8172 pr " CAMLxparam%d (%s);\n"
8173 (List.length rest) (String.concat ", " rest)
8175 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8177 if not needs_extra_vs then
8178 pr " CAMLlocal1 (rv);\n"
8180 pr " CAMLlocal3 (rv, v, v2);\n";
8183 pr " guestfs_h *g = Guestfs_val (gv);\n";
8184 pr " if (g == NULL)\n";
8185 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8191 | Device n | Dev_or_Path n
8195 pr " const char *%s = String_val (%sv);\n" n n
8197 pr " const char *%s =\n" n;
8198 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8200 | StringList n | DeviceList n ->
8201 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8203 pr " int %s = Bool_val (%sv);\n" n n
8205 pr " int %s = Int_val (%sv);\n" n n
8207 pr " int64_t %s = Int64_val (%sv);\n" n n
8210 match fst style with
8211 | RErr -> pr " int r;\n"; "-1"
8212 | RInt _ -> pr " int r;\n"; "-1"
8213 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8214 | RBool _ -> pr " int r;\n"; "-1"
8215 | RConstString _ | RConstOptString _ ->
8216 pr " const char *r;\n"; "NULL"
8217 | RString _ -> pr " char *r;\n"; "NULL"
8222 | RStruct (_, typ) ->
8223 pr " struct guestfs_%s *r;\n" typ; "NULL"
8224 | RStructList (_, typ) ->
8225 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8232 pr " size_t size;\n";
8236 pr " caml_enter_blocking_section ();\n";
8237 pr " r = guestfs_%s " name;
8238 generate_c_call_args ~handle:"g" style;
8240 pr " caml_leave_blocking_section ();\n";
8244 | StringList n | DeviceList n ->
8245 pr " ocaml_guestfs_free_strings (%s);\n" n;
8246 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8247 | Bool _ | Int _ | Int64 _
8248 | FileIn _ | FileOut _ -> ()
8251 pr " if (r == %s)\n" error_code;
8252 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8255 (match fst style with
8256 | RErr -> pr " rv = Val_unit;\n"
8257 | RInt _ -> pr " rv = Val_int (r);\n"
8259 pr " rv = caml_copy_int64 (r);\n"
8260 | RBool _ -> pr " rv = Val_bool (r);\n"
8262 pr " rv = caml_copy_string (r);\n"
8263 | RConstOptString _ ->
8264 pr " if (r) { /* Some string */\n";
8265 pr " v = caml_alloc (1, 0);\n";
8266 pr " v2 = caml_copy_string (r);\n";
8267 pr " Store_field (v, 0, v2);\n";
8268 pr " } else /* None */\n";
8269 pr " v = Val_int (0);\n";
8271 pr " rv = caml_copy_string (r);\n";
8274 pr " rv = caml_copy_string_array ((const char **) r);\n";
8275 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8277 | RStruct (_, typ) ->
8278 pr " rv = copy_%s (r);\n" typ;
8279 pr " guestfs_free_%s (r);\n" typ;
8280 | RStructList (_, typ) ->
8281 pr " rv = copy_%s_list (r);\n" typ;
8282 pr " guestfs_free_%s_list (r);\n" typ;
8284 pr " rv = copy_table (r);\n";
8285 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8288 pr " rv = caml_alloc_string (size);\n";
8289 pr " memcpy (String_val (rv), r, size);\n";
8292 pr " CAMLreturn (rv);\n";
8296 if List.length params > 5 then (
8297 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8298 pr "CAMLprim value ";
8299 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8300 pr "CAMLprim value\n";
8301 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8303 pr " return ocaml_guestfs_%s (argv[0]" name;
8304 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8309 ) all_functions_sorted
8311 and generate_ocaml_structure_decls () =
8314 pr "type %s = {\n" typ;
8317 | name, FString -> pr " %s : string;\n" name
8318 | name, FBuffer -> pr " %s : string;\n" name
8319 | name, FUUID -> pr " %s : string;\n" name
8320 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8321 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8322 | name, FChar -> pr " %s : char;\n" name
8323 | name, FOptPercent -> pr " %s : float option;\n" name
8329 and generate_ocaml_prototype ?(is_external = false) name style =
8330 if is_external then pr "external " else pr "val ";
8331 pr "%s : t -> " name;
8334 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8335 | OptString _ -> pr "string option -> "
8336 | StringList _ | DeviceList _ -> pr "string array -> "
8337 | Bool _ -> pr "bool -> "
8338 | Int _ -> pr "int -> "
8339 | Int64 _ -> pr "int64 -> "
8341 (match fst style with
8342 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8343 | RInt _ -> pr "int"
8344 | RInt64 _ -> pr "int64"
8345 | RBool _ -> pr "bool"
8346 | RConstString _ -> pr "string"
8347 | RConstOptString _ -> pr "string option"
8348 | RString _ | RBufferOut _ -> pr "string"
8349 | RStringList _ -> pr "string array"
8350 | RStruct (_, typ) -> pr "%s" typ
8351 | RStructList (_, typ) -> pr "%s array" typ
8352 | RHashtable _ -> pr "(string * string) list"
8354 if is_external then (
8356 if List.length (snd style) + 1 > 5 then
8357 pr "\"ocaml_guestfs_%s_byte\" " name;
8358 pr "\"ocaml_guestfs_%s\"" name
8362 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8363 and generate_perl_xs () =
8364 generate_header CStyle LGPLv2plus;
8367 #include \"EXTERN.h\"
8371 #include <guestfs.h>
8374 #define PRId64 \"lld\"
8378 my_newSVll(long long val) {
8379 #ifdef USE_64_BIT_ALL
8380 return newSViv(val);
8384 len = snprintf(buf, 100, \"%%\" PRId64, val);
8385 return newSVpv(buf, len);
8390 #define PRIu64 \"llu\"
8394 my_newSVull(unsigned long long val) {
8395 #ifdef USE_64_BIT_ALL
8396 return newSVuv(val);
8400 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8401 return newSVpv(buf, len);
8405 /* http://www.perlmonks.org/?node_id=680842 */
8407 XS_unpack_charPtrPtr (SV *arg) {
8412 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8413 croak (\"array reference expected\");
8415 av = (AV *)SvRV (arg);
8416 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8418 croak (\"malloc failed\");
8420 for (i = 0; i <= av_len (av); i++) {
8421 SV **elem = av_fetch (av, i, 0);
8423 if (!elem || !*elem)
8424 croak (\"missing element in list\");
8426 ret[i] = SvPV_nolen (*elem);
8434 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8441 RETVAL = guestfs_create ();
8443 croak (\"could not create guestfs handle\");
8444 guestfs_set_error_handler (RETVAL, NULL, NULL);
8457 fun (name, style, _, _, _, _, _) ->
8458 (match fst style with
8459 | RErr -> pr "void\n"
8460 | RInt _ -> pr "SV *\n"
8461 | RInt64 _ -> pr "SV *\n"
8462 | RBool _ -> pr "SV *\n"
8463 | RConstString _ -> pr "SV *\n"
8464 | RConstOptString _ -> pr "SV *\n"
8465 | RString _ -> pr "SV *\n"
8466 | RBufferOut _ -> pr "SV *\n"
8468 | RStruct _ | RStructList _
8470 pr "void\n" (* all lists returned implictly on the stack *)
8472 (* Call and arguments. *)
8474 generate_c_call_args ~handle:"g" ~decl:true style;
8476 pr " guestfs_h *g;\n";
8480 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8483 (* http://www.perlmonks.org/?node_id=554277
8484 * Note that the implicit handle argument means we have
8485 * to add 1 to the ST(x) operator.
8487 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8488 | StringList n | DeviceList n -> pr " char **%s;\n" n
8489 | Bool n -> pr " int %s;\n" n
8490 | Int n -> pr " int %s;\n" n
8491 | Int64 n -> pr " int64_t %s;\n" n
8494 let do_cleanups () =
8497 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8498 | Bool _ | Int _ | Int64 _
8499 | FileIn _ | FileOut _ -> ()
8500 | StringList n | DeviceList n -> pr " free (%s);\n" n
8505 (match fst style with
8510 pr " r = guestfs_%s " name;
8511 generate_c_call_args ~handle:"g" style;
8514 pr " if (r == -1)\n";
8515 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8521 pr " %s = guestfs_%s " n name;
8522 generate_c_call_args ~handle:"g" style;
8525 pr " if (%s == -1)\n" n;
8526 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8527 pr " RETVAL = newSViv (%s);\n" n;
8532 pr " int64_t %s;\n" n;
8534 pr " %s = guestfs_%s " n name;
8535 generate_c_call_args ~handle:"g" style;
8538 pr " if (%s == -1)\n" n;
8539 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8540 pr " RETVAL = my_newSVll (%s);\n" n;
8545 pr " const char *%s;\n" n;
8547 pr " %s = guestfs_%s " n name;
8548 generate_c_call_args ~handle:"g" style;
8551 pr " if (%s == NULL)\n" n;
8552 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8553 pr " RETVAL = newSVpv (%s, 0);\n" n;
8556 | RConstOptString n ->
8558 pr " const char *%s;\n" n;
8560 pr " %s = guestfs_%s " n name;
8561 generate_c_call_args ~handle:"g" style;
8564 pr " if (%s == NULL)\n" n;
8565 pr " RETVAL = &PL_sv_undef;\n";
8567 pr " RETVAL = newSVpv (%s, 0);\n" n;
8572 pr " char *%s;\n" n;
8574 pr " %s = guestfs_%s " n name;
8575 generate_c_call_args ~handle:"g" style;
8578 pr " if (%s == NULL)\n" n;
8579 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8580 pr " RETVAL = newSVpv (%s, 0);\n" n;
8581 pr " free (%s);\n" n;
8584 | RStringList n | RHashtable n ->
8586 pr " char **%s;\n" n;
8589 pr " %s = guestfs_%s " n name;
8590 generate_c_call_args ~handle:"g" style;
8593 pr " if (%s == NULL)\n" n;
8594 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8595 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8596 pr " EXTEND (SP, n);\n";
8597 pr " for (i = 0; i < n; ++i) {\n";
8598 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8599 pr " free (%s[i]);\n" n;
8601 pr " free (%s);\n" n;
8602 | RStruct (n, typ) ->
8603 let cols = cols_of_struct typ in
8604 generate_perl_struct_code typ cols name style n do_cleanups
8605 | RStructList (n, typ) ->
8606 let cols = cols_of_struct typ in
8607 generate_perl_struct_list_code typ cols name style n do_cleanups
8610 pr " char *%s;\n" n;
8611 pr " size_t size;\n";
8613 pr " %s = guestfs_%s " n name;
8614 generate_c_call_args ~handle:"g" style;
8617 pr " if (%s == NULL)\n" n;
8618 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8619 pr " RETVAL = newSVpvn (%s, size);\n" n;
8620 pr " free (%s);\n" n;
8628 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8630 pr " struct guestfs_%s_list *%s;\n" typ n;
8634 pr " %s = guestfs_%s " n name;
8635 generate_c_call_args ~handle:"g" style;
8638 pr " if (%s == NULL)\n" n;
8639 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8640 pr " EXTEND (SP, %s->len);\n" n;
8641 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8642 pr " hv = newHV ();\n";
8646 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8647 name (String.length name) n name
8649 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8650 name (String.length name) n name
8652 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8653 name (String.length name) n name n name
8654 | name, (FBytes|FUInt64) ->
8655 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8656 name (String.length name) n name
8658 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8659 name (String.length name) n name
8660 | name, (FInt32|FUInt32) ->
8661 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8662 name (String.length name) n name
8664 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8665 name (String.length name) n name
8666 | name, FOptPercent ->
8667 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8668 name (String.length name) n name
8670 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8672 pr " guestfs_free_%s_list (%s);\n" typ n
8674 and generate_perl_struct_code typ cols name style n do_cleanups =
8676 pr " struct guestfs_%s *%s;\n" typ n;
8678 pr " %s = guestfs_%s " n name;
8679 generate_c_call_args ~handle:"g" style;
8682 pr " if (%s == NULL)\n" n;
8683 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8684 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8686 fun ((name, _) as col) ->
8687 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8691 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8694 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8697 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8699 | name, (FBytes|FUInt64) ->
8700 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8703 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8705 | name, (FInt32|FUInt32) ->
8706 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8709 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8711 | name, FOptPercent ->
8712 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8715 pr " free (%s);\n" n
8717 (* Generate Sys/Guestfs.pm. *)
8718 and generate_perl_pm () =
8719 generate_header HashStyle LGPLv2plus;
8726 Sys::Guestfs - Perl bindings for libguestfs
8732 my $h = Sys::Guestfs->new ();
8733 $h->add_drive ('guest.img');
8735 $h->mount ('/dev/sda1', '/');
8736 $h->touch ('/hello');
8741 The C<Sys::Guestfs> module provides a Perl XS binding to the
8742 libguestfs API for examining and modifying virtual machine
8745 Amongst the things this is good for: making batch configuration
8746 changes to guests, getting disk used/free statistics (see also:
8747 virt-df), migrating between virtualization systems (see also:
8748 virt-p2v), performing partial backups, performing partial guest
8749 clones, cloning guests and changing registry/UUID/hostname info, and
8752 Libguestfs uses Linux kernel and qemu code, and can access any type of
8753 guest filesystem that Linux and qemu can, including but not limited
8754 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8755 schemes, qcow, qcow2, vmdk.
8757 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8758 LVs, what filesystem is in each LV, etc.). It can also run commands
8759 in the context of the guest. Also you can access filesystems over
8762 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8763 functions for using libguestfs from Perl, including integration
8768 All errors turn into calls to C<croak> (see L<Carp(3)>).
8776 package Sys::Guestfs;
8782 XSLoader::load ('Sys::Guestfs');
8784 =item $h = Sys::Guestfs->new ();
8786 Create a new guestfs handle.
8792 my $class = ref ($proto) || $proto;
8794 my $self = Sys::Guestfs::_create ();
8795 bless $self, $class;
8801 (* Actions. We only need to print documentation for these as
8802 * they are pulled in from the XS code automatically.
8805 fun (name, style, _, flags, _, _, longdesc) ->
8806 if not (List.mem NotInDocs flags) then (
8807 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8809 generate_perl_prototype name style;
8811 pr "%s\n\n" longdesc;
8812 if List.mem ProtocolLimitWarning flags then
8813 pr "%s\n\n" protocol_limit_warning;
8814 if List.mem DangerWillRobinson flags then
8815 pr "%s\n\n" danger_will_robinson;
8816 match deprecation_notice flags with
8818 | Some txt -> pr "%s\n\n" txt
8820 ) all_functions_sorted;
8832 Copyright (C) %s Red Hat Inc.
8836 Please see the file COPYING.LIB for the full license.
8842 L<http://libguestfs.org>,
8843 L<Sys::Guestfs::Lib(3)>.
8848 and generate_perl_prototype name style =
8849 (match fst style with
8857 | RBufferOut n -> pr "$%s = " n
8859 | RHashtable n -> pr "%%%s = " n
8861 | RStructList (n,_) -> pr "@%s = " n
8864 let comma = ref false in
8867 if !comma then pr ", ";
8870 | Pathname n | Device n | Dev_or_Path n | String n
8871 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8873 | StringList n | DeviceList n ->
8878 (* Generate Python C module. *)
8879 and generate_python_c () =
8880 generate_header CStyle LGPLv2plus;
8889 #include \"guestfs.h\"
8897 get_handle (PyObject *obj)
8900 assert (obj != Py_None);
8901 return ((Pyguestfs_Object *) obj)->g;
8905 put_handle (guestfs_h *g)
8909 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8912 /* This list should be freed (but not the strings) after use. */
8914 get_string_list (PyObject *obj)
8921 if (!PyList_Check (obj)) {
8922 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8926 len = PyList_Size (obj);
8927 r = malloc (sizeof (char *) * (len+1));
8929 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8933 for (i = 0; i < len; ++i)
8934 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8941 put_string_list (char * const * const argv)
8946 for (argc = 0; argv[argc] != NULL; ++argc)
8949 list = PyList_New (argc);
8950 for (i = 0; i < argc; ++i)
8951 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8957 put_table (char * const * const argv)
8959 PyObject *list, *item;
8962 for (argc = 0; argv[argc] != NULL; ++argc)
8965 list = PyList_New (argc >> 1);
8966 for (i = 0; i < argc; i += 2) {
8967 item = PyTuple_New (2);
8968 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8969 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8970 PyList_SetItem (list, i >> 1, item);
8977 free_strings (char **argv)
8981 for (argc = 0; argv[argc] != NULL; ++argc)
8987 py_guestfs_create (PyObject *self, PyObject *args)
8991 g = guestfs_create ();
8993 PyErr_SetString (PyExc_RuntimeError,
8994 \"guestfs.create: failed to allocate handle\");
8997 guestfs_set_error_handler (g, NULL, NULL);
8998 return put_handle (g);
9002 py_guestfs_close (PyObject *self, PyObject *args)
9007 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9009 g = get_handle (py_g);
9013 Py_INCREF (Py_None);
9019 let emit_put_list_function typ =
9020 pr "static PyObject *\n";
9021 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9023 pr " PyObject *list;\n";
9026 pr " list = PyList_New (%ss->len);\n" typ;
9027 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9028 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9029 pr " return list;\n";
9034 (* Structures, turned into Python dictionaries. *)
9037 pr "static PyObject *\n";
9038 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9040 pr " PyObject *dict;\n";
9042 pr " dict = PyDict_New ();\n";
9046 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9047 pr " PyString_FromString (%s->%s));\n"
9050 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9051 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9054 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9055 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9057 | name, (FBytes|FUInt64) ->
9058 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9059 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9062 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9063 pr " PyLong_FromLongLong (%s->%s));\n"
9066 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9067 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9070 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9071 pr " PyLong_FromLong (%s->%s));\n"
9073 | name, FOptPercent ->
9074 pr " if (%s->%s >= 0)\n" typ name;
9075 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9076 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9079 pr " Py_INCREF (Py_None);\n";
9080 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9083 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9084 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9086 pr " return dict;\n";
9092 (* Emit a put_TYPE_list function definition only if that function is used. *)
9095 | typ, (RStructListOnly | RStructAndList) ->
9096 (* generate the function for typ *)
9097 emit_put_list_function typ
9098 | typ, _ -> () (* empty *)
9099 ) (rstructs_used_by all_functions);
9101 (* Python wrapper functions. *)
9103 fun (name, style, _, _, _, _, _) ->
9104 pr "static PyObject *\n";
9105 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9108 pr " PyObject *py_g;\n";
9109 pr " guestfs_h *g;\n";
9110 pr " PyObject *py_r;\n";
9113 match fst style with
9114 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9115 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9116 | RConstString _ | RConstOptString _ ->
9117 pr " const char *r;\n"; "NULL"
9118 | RString _ -> pr " char *r;\n"; "NULL"
9119 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9120 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9121 | RStructList (_, typ) ->
9122 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9125 pr " size_t size;\n";
9130 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9131 pr " const char *%s;\n" n
9132 | OptString n -> pr " const char *%s;\n" n
9133 | StringList n | DeviceList n ->
9134 pr " PyObject *py_%s;\n" n;
9135 pr " char **%s;\n" n
9136 | Bool n -> pr " int %s;\n" n
9137 | Int n -> pr " int %s;\n" n
9138 | Int64 n -> pr " long long %s;\n" n
9143 (* Convert the parameters. *)
9144 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9147 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9148 | OptString _ -> pr "z"
9149 | StringList _ | DeviceList _ -> pr "O"
9150 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9152 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9153 * emulate C's int/long/long long in Python?
9156 pr ":guestfs_%s\",\n" name;
9160 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9161 | OptString n -> pr ", &%s" n
9162 | StringList n | DeviceList n -> pr ", &py_%s" n
9163 | Bool n -> pr ", &%s" n
9164 | Int n -> pr ", &%s" n
9165 | Int64 n -> pr ", &%s" n
9169 pr " return NULL;\n";
9171 pr " g = get_handle (py_g);\n";
9174 | Pathname _ | Device _ | Dev_or_Path _ | String _
9175 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9176 | StringList n | DeviceList n ->
9177 pr " %s = get_string_list (py_%s);\n" n n;
9178 pr " if (!%s) return NULL;\n" n
9183 pr " r = guestfs_%s " name;
9184 generate_c_call_args ~handle:"g" style;
9189 | Pathname _ | Device _ | Dev_or_Path _ | String _
9190 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9191 | StringList n | DeviceList n ->
9192 pr " free (%s);\n" n
9195 pr " if (r == %s) {\n" error_code;
9196 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9197 pr " return NULL;\n";
9201 (match fst style with
9203 pr " Py_INCREF (Py_None);\n";
9204 pr " py_r = Py_None;\n"
9206 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9207 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9208 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9209 | RConstOptString _ ->
9211 pr " py_r = PyString_FromString (r);\n";
9213 pr " Py_INCREF (Py_None);\n";
9214 pr " py_r = Py_None;\n";
9217 pr " py_r = PyString_FromString (r);\n";
9220 pr " py_r = put_string_list (r);\n";
9221 pr " free_strings (r);\n"
9222 | RStruct (_, typ) ->
9223 pr " py_r = put_%s (r);\n" typ;
9224 pr " guestfs_free_%s (r);\n" typ
9225 | RStructList (_, typ) ->
9226 pr " py_r = put_%s_list (r);\n" typ;
9227 pr " guestfs_free_%s_list (r);\n" typ
9229 pr " py_r = put_table (r);\n";
9230 pr " free_strings (r);\n"
9232 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9236 pr " return py_r;\n";
9241 (* Table of functions. *)
9242 pr "static PyMethodDef methods[] = {\n";
9243 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9244 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9246 fun (name, _, _, _, _, _, _) ->
9247 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9250 pr " { NULL, NULL, 0, NULL }\n";
9254 (* Init function. *)
9257 initlibguestfsmod (void)
9259 static int initialized = 0;
9261 if (initialized) return;
9262 Py_InitModule ((char *) \"libguestfsmod\", methods);
9267 (* Generate Python module. *)
9268 and generate_python_py () =
9269 generate_header HashStyle LGPLv2plus;
9272 u\"\"\"Python bindings for libguestfs
9275 g = guestfs.GuestFS ()
9276 g.add_drive (\"guest.img\")
9278 parts = g.list_partitions ()
9280 The guestfs module provides a Python binding to the libguestfs API
9281 for examining and modifying virtual machine disk images.
9283 Amongst the things this is good for: making batch configuration
9284 changes to guests, getting disk used/free statistics (see also:
9285 virt-df), migrating between virtualization systems (see also:
9286 virt-p2v), performing partial backups, performing partial guest
9287 clones, cloning guests and changing registry/UUID/hostname info, and
9290 Libguestfs uses Linux kernel and qemu code, and can access any type of
9291 guest filesystem that Linux and qemu can, including but not limited
9292 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9293 schemes, qcow, qcow2, vmdk.
9295 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9296 LVs, what filesystem is in each LV, etc.). It can also run commands
9297 in the context of the guest. Also you can access filesystems over
9300 Errors which happen while using the API are turned into Python
9301 RuntimeError exceptions.
9303 To create a guestfs handle you usually have to perform the following
9306 # Create the handle, call add_drive at least once, and possibly
9307 # several times if the guest has multiple block devices:
9308 g = guestfs.GuestFS ()
9309 g.add_drive (\"guest.img\")
9311 # Launch the qemu subprocess and wait for it to become ready:
9314 # Now you can issue commands, for example:
9319 import libguestfsmod
9322 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9324 def __init__ (self):
9325 \"\"\"Create a new libguestfs handle.\"\"\"
9326 self._o = libguestfsmod.create ()
9329 libguestfsmod.close (self._o)
9334 fun (name, style, _, flags, _, _, longdesc) ->
9336 generate_py_call_args ~handle:"self" (snd style);
9339 if not (List.mem NotInDocs flags) then (
9340 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9342 match fst style with
9343 | RErr | RInt _ | RInt64 _ | RBool _
9344 | RConstOptString _ | RConstString _
9345 | RString _ | RBufferOut _ -> doc
9347 doc ^ "\n\nThis function returns a list of strings."
9348 | RStruct (_, typ) ->
9349 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9350 | RStructList (_, typ) ->
9351 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9353 doc ^ "\n\nThis function returns a dictionary." in
9355 if List.mem ProtocolLimitWarning flags then
9356 doc ^ "\n\n" ^ protocol_limit_warning
9359 if List.mem DangerWillRobinson flags then
9360 doc ^ "\n\n" ^ danger_will_robinson
9363 match deprecation_notice flags with
9365 | Some txt -> doc ^ "\n\n" ^ txt in
9366 let doc = pod2text ~width:60 name doc in
9367 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9368 let doc = String.concat "\n " doc in
9369 pr " u\"\"\"%s\"\"\"\n" doc;
9371 pr " return libguestfsmod.%s " name;
9372 generate_py_call_args ~handle:"self._o" (snd style);
9377 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9378 and generate_py_call_args ~handle args =
9380 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9383 (* Useful if you need the longdesc POD text as plain text. Returns a
9386 * Because this is very slow (the slowest part of autogeneration),
9387 * we memoize the results.
9389 and pod2text ~width name longdesc =
9390 let key = width, name, longdesc in
9391 try Hashtbl.find pod2text_memo key
9393 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9394 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9396 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9397 let chan = open_process_in cmd in
9398 let lines = ref [] in
9400 let line = input_line chan in
9401 if i = 1 then (* discard the first line of output *)
9404 let line = triml line in
9405 lines := line :: !lines;
9408 let lines = try loop 1 with End_of_file -> List.rev !lines in
9410 (match close_process_in chan with
9413 failwithf "pod2text: process exited with non-zero status (%d)" i
9414 | WSIGNALED i | WSTOPPED i ->
9415 failwithf "pod2text: process signalled or stopped by signal %d" i
9417 Hashtbl.add pod2text_memo key lines;
9418 pod2text_memo_updated ();
9421 (* Generate ruby bindings. *)
9422 and generate_ruby_c () =
9423 generate_header CStyle LGPLv2plus;
9431 #include \"guestfs.h\"
9433 #include \"extconf.h\"
9435 /* For Ruby < 1.9 */
9437 #define RARRAY_LEN(r) (RARRAY((r))->len)
9440 static VALUE m_guestfs; /* guestfs module */
9441 static VALUE c_guestfs; /* guestfs_h handle */
9442 static VALUE e_Error; /* used for all errors */
9444 static void ruby_guestfs_free (void *p)
9447 guestfs_close ((guestfs_h *) p);
9450 static VALUE ruby_guestfs_create (VALUE m)
9454 g = guestfs_create ();
9456 rb_raise (e_Error, \"failed to create guestfs handle\");
9458 /* Don't print error messages to stderr by default. */
9459 guestfs_set_error_handler (g, NULL, NULL);
9461 /* Wrap it, and make sure the close function is called when the
9464 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9467 static VALUE ruby_guestfs_close (VALUE gv)
9470 Data_Get_Struct (gv, guestfs_h, g);
9472 ruby_guestfs_free (g);
9473 DATA_PTR (gv) = NULL;
9481 fun (name, style, _, _, _, _, _) ->
9482 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9483 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9486 pr " guestfs_h *g;\n";
9487 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9489 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9495 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9496 pr " Check_Type (%sv, T_STRING);\n" n;
9497 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9499 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9500 pr " \"%s\", \"%s\");\n" n name
9502 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9503 | StringList n | DeviceList n ->
9504 pr " char **%s;\n" n;
9505 pr " Check_Type (%sv, T_ARRAY);\n" n;
9507 pr " int i, len;\n";
9508 pr " len = RARRAY_LEN (%sv);\n" n;
9509 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9511 pr " for (i = 0; i < len; ++i) {\n";
9512 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9513 pr " %s[i] = StringValueCStr (v);\n" n;
9515 pr " %s[len] = NULL;\n" n;
9518 pr " int %s = RTEST (%sv);\n" n n
9520 pr " int %s = NUM2INT (%sv);\n" n n
9522 pr " long long %s = NUM2LL (%sv);\n" n n
9527 match fst style with
9528 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9529 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9530 | RConstString _ | RConstOptString _ ->
9531 pr " const char *r;\n"; "NULL"
9532 | RString _ -> pr " char *r;\n"; "NULL"
9533 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9534 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9535 | RStructList (_, typ) ->
9536 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9539 pr " size_t size;\n";
9543 pr " r = guestfs_%s " name;
9544 generate_c_call_args ~handle:"g" style;
9549 | Pathname _ | Device _ | Dev_or_Path _ | String _
9550 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9551 | StringList n | DeviceList n ->
9552 pr " free (%s);\n" n
9555 pr " if (r == %s)\n" error_code;
9556 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9559 (match fst style with
9561 pr " return Qnil;\n"
9562 | RInt _ | RBool _ ->
9563 pr " return INT2NUM (r);\n"
9565 pr " return ULL2NUM (r);\n"
9567 pr " return rb_str_new2 (r);\n";
9568 | RConstOptString _ ->
9570 pr " return rb_str_new2 (r);\n";
9572 pr " return Qnil;\n";
9574 pr " VALUE rv = rb_str_new2 (r);\n";
9578 pr " int i, len = 0;\n";
9579 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9580 pr " VALUE rv = rb_ary_new2 (len);\n";
9581 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9582 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9583 pr " free (r[i]);\n";
9587 | RStruct (_, typ) ->
9588 let cols = cols_of_struct typ in
9589 generate_ruby_struct_code typ cols
9590 | RStructList (_, typ) ->
9591 let cols = cols_of_struct typ in
9592 generate_ruby_struct_list_code typ cols
9594 pr " VALUE rv = rb_hash_new ();\n";
9596 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9597 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9598 pr " free (r[i]);\n";
9599 pr " free (r[i+1]);\n";
9604 pr " VALUE rv = rb_str_new (r, size);\n";
9614 /* Initialize the module. */
9615 void Init__guestfs ()
9617 m_guestfs = rb_define_module (\"Guestfs\");
9618 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9619 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9621 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9622 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9625 (* Define the rest of the methods. *)
9627 fun (name, style, _, _, _, _, _) ->
9628 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9629 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9634 (* Ruby code to return a struct. *)
9635 and generate_ruby_struct_code typ cols =
9636 pr " VALUE rv = rb_hash_new ();\n";
9640 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9642 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9644 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9645 | name, (FBytes|FUInt64) ->
9646 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9648 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9650 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9652 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9653 | name, FOptPercent ->
9654 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9655 | name, FChar -> (* XXX wrong? *)
9656 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9658 pr " guestfs_free_%s (r);\n" typ;
9661 (* Ruby code to return a struct list. *)
9662 and generate_ruby_struct_list_code typ cols =
9663 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9665 pr " for (i = 0; i < r->len; ++i) {\n";
9666 pr " VALUE hv = rb_hash_new ();\n";
9670 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9672 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
9674 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9675 | name, (FBytes|FUInt64) ->
9676 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9678 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9680 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9682 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9683 | name, FOptPercent ->
9684 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9685 | name, FChar -> (* XXX wrong? *)
9686 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9688 pr " rb_ary_push (rv, hv);\n";
9690 pr " guestfs_free_%s_list (r);\n" typ;
9693 (* Generate Java bindings GuestFS.java file. *)
9694 and generate_java_java () =
9695 generate_header CStyle LGPLv2plus;
9698 package com.redhat.et.libguestfs;
9700 import java.util.HashMap;
9701 import com.redhat.et.libguestfs.LibGuestFSException;
9702 import com.redhat.et.libguestfs.PV;
9703 import com.redhat.et.libguestfs.VG;
9704 import com.redhat.et.libguestfs.LV;
9705 import com.redhat.et.libguestfs.Stat;
9706 import com.redhat.et.libguestfs.StatVFS;
9707 import com.redhat.et.libguestfs.IntBool;
9708 import com.redhat.et.libguestfs.Dirent;
9711 * The GuestFS object is a libguestfs handle.
9715 public class GuestFS {
9716 // Load the native code.
9718 System.loadLibrary (\"guestfs_jni\");
9722 * The native guestfs_h pointer.
9727 * Create a libguestfs handle.
9729 * @throws LibGuestFSException
9731 public GuestFS () throws LibGuestFSException
9735 private native long _create () throws LibGuestFSException;
9738 * Close a libguestfs handle.
9740 * You can also leave handles to be collected by the garbage
9741 * collector, but this method ensures that the resources used
9742 * by the handle are freed up immediately. If you call any
9743 * other methods after closing the handle, you will get an
9746 * @throws LibGuestFSException
9748 public void close () throws LibGuestFSException
9754 private native void _close (long g) throws LibGuestFSException;
9756 public void finalize () throws LibGuestFSException
9764 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9765 if not (List.mem NotInDocs flags); then (
9766 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9768 if List.mem ProtocolLimitWarning flags then
9769 doc ^ "\n\n" ^ protocol_limit_warning
9772 if List.mem DangerWillRobinson flags then
9773 doc ^ "\n\n" ^ danger_will_robinson
9776 match deprecation_notice flags with
9778 | Some txt -> doc ^ "\n\n" ^ txt in
9779 let doc = pod2text ~width:60 name doc in
9780 let doc = List.map ( (* RHBZ#501883 *)
9783 | nonempty -> nonempty
9785 let doc = String.concat "\n * " doc in
9788 pr " * %s\n" shortdesc;
9791 pr " * @throws LibGuestFSException\n";
9795 generate_java_prototype ~public:true ~semicolon:false name style;
9798 pr " if (g == 0)\n";
9799 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9802 if fst style <> RErr then pr "return ";
9804 generate_java_call_args ~handle:"g" (snd style);
9808 generate_java_prototype ~privat:true ~native:true name style;
9815 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9816 and generate_java_call_args ~handle args =
9818 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9821 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9822 ?(semicolon=true) name style =
9823 if privat then pr "private ";
9824 if public then pr "public ";
9825 if native then pr "native ";
9828 (match fst style with
9829 | RErr -> pr "void ";
9830 | RInt _ -> pr "int ";
9831 | RInt64 _ -> pr "long ";
9832 | RBool _ -> pr "boolean ";
9833 | RConstString _ | RConstOptString _ | RString _
9834 | RBufferOut _ -> pr "String ";
9835 | RStringList _ -> pr "String[] ";
9836 | RStruct (_, typ) ->
9837 let name = java_name_of_struct typ in
9839 | RStructList (_, typ) ->
9840 let name = java_name_of_struct typ in
9842 | RHashtable _ -> pr "HashMap<String,String> ";
9845 if native then pr "_%s " name else pr "%s " name;
9847 let needs_comma = ref false in
9856 if !needs_comma then pr ", ";
9857 needs_comma := true;
9861 | Device n | Dev_or_Path n
9867 | StringList n | DeviceList n ->
9878 pr " throws LibGuestFSException";
9879 if semicolon then pr ";"
9881 and generate_java_struct jtyp cols () =
9882 generate_header CStyle LGPLv2plus;
9885 package com.redhat.et.libguestfs;
9888 * Libguestfs %s structure.
9900 | name, FBuffer -> pr " public String %s;\n" name
9901 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9902 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9903 | name, FChar -> pr " public char %s;\n" name
9904 | name, FOptPercent ->
9905 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9906 pr " public float %s;\n" name
9911 and generate_java_c () =
9912 generate_header CStyle LGPLv2plus;
9919 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9920 #include \"guestfs.h\"
9922 /* Note that this function returns. The exception is not thrown
9923 * until after the wrapper function returns.
9926 throw_exception (JNIEnv *env, const char *msg)
9929 cl = (*env)->FindClass (env,
9930 \"com/redhat/et/libguestfs/LibGuestFSException\");
9931 (*env)->ThrowNew (env, cl, msg);
9934 JNIEXPORT jlong JNICALL
9935 Java_com_redhat_et_libguestfs_GuestFS__1create
9936 (JNIEnv *env, jobject obj)
9940 g = guestfs_create ();
9942 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9945 guestfs_set_error_handler (g, NULL, NULL);
9946 return (jlong) (long) g;
9949 JNIEXPORT void JNICALL
9950 Java_com_redhat_et_libguestfs_GuestFS__1close
9951 (JNIEnv *env, jobject obj, jlong jg)
9953 guestfs_h *g = (guestfs_h *) (long) jg;
9960 fun (name, style, _, _, _, _, _) ->
9962 (match fst style with
9963 | RErr -> pr "void ";
9964 | RInt _ -> pr "jint ";
9965 | RInt64 _ -> pr "jlong ";
9966 | RBool _ -> pr "jboolean ";
9967 | RConstString _ | RConstOptString _ | RString _
9968 | RBufferOut _ -> pr "jstring ";
9969 | RStruct _ | RHashtable _ ->
9971 | RStringList _ | RStructList _ ->
9975 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9976 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9978 pr " (JNIEnv *env, jobject obj, jlong jg";
9982 | Device n | Dev_or_Path n
9987 pr ", jstring j%s" n
9988 | StringList n | DeviceList n ->
9989 pr ", jobjectArray j%s" n
9991 pr ", jboolean j%s" n
9999 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10000 let error_code, no_ret =
10001 match fst style with
10002 | RErr -> pr " int r;\n"; "-1", ""
10004 | RInt _ -> pr " int r;\n"; "-1", "0"
10005 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10006 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10007 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10009 pr " jstring jr;\n";
10010 pr " char *r;\n"; "NULL", "NULL"
10012 pr " jobjectArray jr;\n";
10013 pr " int r_len;\n";
10014 pr " jclass cl;\n";
10015 pr " jstring jstr;\n";
10016 pr " char **r;\n"; "NULL", "NULL"
10017 | RStruct (_, typ) ->
10018 pr " jobject jr;\n";
10019 pr " jclass cl;\n";
10020 pr " jfieldID fl;\n";
10021 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10022 | RStructList (_, typ) ->
10023 pr " jobjectArray jr;\n";
10024 pr " jclass cl;\n";
10025 pr " jfieldID fl;\n";
10026 pr " jobject jfl;\n";
10027 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10028 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10030 pr " jstring jr;\n";
10032 pr " size_t size;\n";
10037 | Device n | Dev_or_Path n
10042 pr " const char *%s;\n" n
10043 | StringList n | DeviceList n ->
10044 pr " int %s_len;\n" n;
10045 pr " const char **%s;\n" n
10050 pr " int64_t %s;\n" n
10054 (match fst style with
10055 | RStringList _ | RStructList _ -> true
10056 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10057 | RConstOptString _
10058 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10059 List.exists (function
10060 | StringList _ -> true
10061 | DeviceList _ -> true
10062 | _ -> false) (snd style) in
10068 (* Get the parameters. *)
10072 | Device n | Dev_or_Path n
10076 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10078 (* This is completely undocumented, but Java null becomes
10079 * a NULL parameter.
10081 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10082 | StringList n | DeviceList n ->
10083 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10084 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10085 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10086 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10088 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10090 pr " %s[%s_len] = NULL;\n" n n;
10094 pr " %s = j%s;\n" n n
10097 (* Make the call. *)
10098 pr " r = guestfs_%s " name;
10099 generate_c_call_args ~handle:"g" style;
10102 (* Release the parameters. *)
10106 | Device n | Dev_or_Path n
10110 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10112 pr " if (j%s)\n" n;
10113 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10114 | StringList n | DeviceList n ->
10115 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10116 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10118 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10120 pr " free (%s);\n" n
10126 (* Check for errors. *)
10127 pr " if (r == %s) {\n" error_code;
10128 pr " throw_exception (env, guestfs_last_error (g));\n";
10129 pr " return %s;\n" no_ret;
10132 (* Return value. *)
10133 (match fst style with
10135 | RInt _ -> pr " return (jint) r;\n"
10136 | RBool _ -> pr " return (jboolean) r;\n"
10137 | RInt64 _ -> pr " return (jlong) r;\n"
10138 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10139 | RConstOptString _ ->
10140 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10142 pr " jr = (*env)->NewStringUTF (env, r);\n";
10146 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10147 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10148 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10149 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10150 pr " for (i = 0; i < r_len; ++i) {\n";
10151 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10152 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10153 pr " free (r[i]);\n";
10157 | RStruct (_, typ) ->
10158 let jtyp = java_name_of_struct typ in
10159 let cols = cols_of_struct typ in
10160 generate_java_struct_return typ jtyp cols
10161 | RStructList (_, typ) ->
10162 let jtyp = java_name_of_struct typ in
10163 let cols = cols_of_struct typ in
10164 generate_java_struct_list_return typ jtyp cols
10167 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10168 pr " return NULL;\n"
10170 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10179 and generate_java_struct_return typ jtyp cols =
10180 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10181 pr " jr = (*env)->AllocObject (env, cl);\n";
10185 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10186 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10189 pr " char s[33];\n";
10190 pr " memcpy (s, r->%s, 32);\n" name;
10191 pr " s[32] = 0;\n";
10192 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10193 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10197 pr " int len = r->%s_len;\n" name;
10198 pr " char s[len+1];\n";
10199 pr " memcpy (s, r->%s, len);\n" name;
10200 pr " s[len] = 0;\n";
10201 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10202 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10204 | name, (FBytes|FUInt64|FInt64) ->
10205 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10206 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10207 | name, (FUInt32|FInt32) ->
10208 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10209 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10210 | name, FOptPercent ->
10211 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10212 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10214 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10215 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10220 and generate_java_struct_list_return typ jtyp cols =
10221 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10222 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10223 pr " for (i = 0; i < r->len; ++i) {\n";
10224 pr " jfl = (*env)->AllocObject (env, cl);\n";
10228 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10229 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10232 pr " char s[33];\n";
10233 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10234 pr " s[32] = 0;\n";
10235 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10236 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10240 pr " int len = r->val[i].%s_len;\n" name;
10241 pr " char s[len+1];\n";
10242 pr " memcpy (s, r->val[i].%s, len);\n" name;
10243 pr " s[len] = 0;\n";
10244 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10245 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10247 | name, (FBytes|FUInt64|FInt64) ->
10248 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10249 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10250 | name, (FUInt32|FInt32) ->
10251 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10252 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10253 | name, FOptPercent ->
10254 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10255 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10257 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10258 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10260 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10262 pr " guestfs_free_%s_list (r);\n" typ;
10265 and generate_java_makefile_inc () =
10266 generate_header HashStyle GPLv2plus;
10268 pr "java_built_sources = \\\n";
10271 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10273 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10275 and generate_haskell_hs () =
10276 generate_header HaskellStyle LGPLv2plus;
10278 (* XXX We only know how to generate partial FFI for Haskell
10279 * at the moment. Please help out!
10281 let can_generate style =
10285 | RInt64 _, _ -> true
10287 | RConstString _, _
10288 | RConstOptString _, _
10294 | RBufferOut _, _ -> false in
10297 {-# INCLUDE <guestfs.h> #-}
10298 {-# LANGUAGE ForeignFunctionInterface #-}
10303 (* List out the names of the actions we want to export. *)
10305 fun (name, style, _, _, _, _, _) ->
10306 if can_generate style then pr ",\n %s" name
10312 -- Unfortunately some symbols duplicate ones already present
10313 -- in Prelude. We don't know which, so we hard-code a list
10315 import Prelude hiding (truncate)
10319 import Foreign.C.Types
10321 import Control.Exception
10322 import Data.Typeable
10324 data GuestfsS = GuestfsS -- represents the opaque C struct
10325 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10326 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10328 -- XXX define properly later XXX
10332 data IntBool = IntBool
10334 data StatVFS = StatVFS
10335 data Hashtable = Hashtable
10337 foreign import ccall unsafe \"guestfs_create\" c_create
10339 foreign import ccall unsafe \"&guestfs_close\" c_close
10340 :: FunPtr (GuestfsP -> IO ())
10341 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10342 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10344 create :: IO GuestfsH
10347 c_set_error_handler p nullPtr nullPtr
10348 h <- newForeignPtr c_close p
10351 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10352 :: GuestfsP -> IO CString
10354 -- last_error :: GuestfsH -> IO (Maybe String)
10355 -- last_error h = do
10356 -- str <- withForeignPtr h (\\p -> c_last_error p)
10357 -- maybePeek peekCString str
10359 last_error :: GuestfsH -> IO (String)
10361 str <- withForeignPtr h (\\p -> c_last_error p)
10362 if (str == nullPtr)
10363 then return \"no error\"
10364 else peekCString str
10368 (* Generate wrappers for each foreign function. *)
10370 fun (name, style, _, _, _, _, _) ->
10371 if can_generate style then (
10372 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10374 generate_haskell_prototype ~handle:"GuestfsP" style;
10378 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10380 pr "%s %s = do\n" name
10381 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10383 (* Convert pointer arguments using with* functions. *)
10388 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10389 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10390 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10391 | Bool _ | Int _ | Int64 _ -> ()
10393 (* Convert integer arguments. *)
10397 | Bool n -> sprintf "(fromBool %s)" n
10398 | Int n -> sprintf "(fromIntegral %s)" n
10399 | Int64 n -> sprintf "(fromIntegral %s)" n
10400 | FileIn n | FileOut n
10401 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10403 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10404 (String.concat " " ("p" :: args));
10405 (match fst style with
10406 | RErr | RInt _ | RInt64 _ | RBool _ ->
10407 pr " if (r == -1)\n";
10409 pr " err <- last_error h\n";
10411 | RConstString _ | RConstOptString _ | RString _
10412 | RStringList _ | RStruct _
10413 | RStructList _ | RHashtable _ | RBufferOut _ ->
10414 pr " if (r == nullPtr)\n";
10416 pr " err <- last_error h\n";
10419 (match fst style with
10421 pr " else return ()\n"
10423 pr " else return (fromIntegral r)\n"
10425 pr " else return (fromIntegral r)\n"
10427 pr " else return (toBool r)\n"
10429 | RConstOptString _
10436 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10442 and generate_haskell_prototype ~handle ?(hs = false) style =
10443 pr "%s -> " handle;
10444 let string = if hs then "String" else "CString" in
10445 let int = if hs then "Int" else "CInt" in
10446 let bool = if hs then "Bool" else "CInt" in
10447 let int64 = if hs then "Integer" else "Int64" in
10451 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10452 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10453 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10454 | Bool _ -> pr "%s" bool
10455 | Int _ -> pr "%s" int
10456 | Int64 _ -> pr "%s" int
10457 | FileIn _ -> pr "%s" string
10458 | FileOut _ -> pr "%s" string
10463 (match fst style with
10464 | RErr -> if not hs then pr "CInt"
10465 | RInt _ -> pr "%s" int
10466 | RInt64 _ -> pr "%s" int64
10467 | RBool _ -> pr "%s" bool
10468 | RConstString _ -> pr "%s" string
10469 | RConstOptString _ -> pr "Maybe %s" string
10470 | RString _ -> pr "%s" string
10471 | RStringList _ -> pr "[%s]" string
10472 | RStruct (_, typ) ->
10473 let name = java_name_of_struct typ in
10475 | RStructList (_, typ) ->
10476 let name = java_name_of_struct typ in
10478 | RHashtable _ -> pr "Hashtable"
10479 | RBufferOut _ -> pr "%s" string
10483 and generate_csharp () =
10484 generate_header CPlusPlusStyle LGPLv2plus;
10486 (* XXX Make this configurable by the C# assembly users. *)
10487 let library = "libguestfs.so.0" in
10490 // These C# bindings are highly experimental at present.
10492 // Firstly they only work on Linux (ie. Mono). In order to get them
10493 // to work on Windows (ie. .Net) you would need to port the library
10494 // itself to Windows first.
10496 // The second issue is that some calls are known to be incorrect and
10497 // can cause Mono to segfault. Particularly: calls which pass or
10498 // return string[], or return any structure value. This is because
10499 // we haven't worked out the correct way to do this from C#.
10501 // The third issue is that when compiling you get a lot of warnings.
10502 // We are not sure whether the warnings are important or not.
10504 // Fourthly we do not routinely build or test these bindings as part
10505 // of the make && make check cycle, which means that regressions might
10508 // Suggestions and patches are welcome.
10512 // gmcs Libguestfs.cs
10513 // mono Libguestfs.exe
10515 // (You'll probably want to add a Test class / static main function
10516 // otherwise this won't do anything useful).
10520 using System.Runtime.InteropServices;
10521 using System.Runtime.Serialization;
10522 using System.Collections;
10526 class Error : System.ApplicationException
10528 public Error (string message) : base (message) {}
10529 protected Error (SerializationInfo info, StreamingContext context) {}
10536 [DllImport (\"%s\")]
10537 static extern IntPtr guestfs_create ();
10541 _handle = guestfs_create ();
10542 if (_handle == IntPtr.Zero)
10543 throw new Error (\"could not create guestfs handle\");
10546 [DllImport (\"%s\")]
10547 static extern void guestfs_close (IntPtr h);
10551 guestfs_close (_handle);
10554 [DllImport (\"%s\")]
10555 static extern string guestfs_last_error (IntPtr h);
10557 " library library library;
10559 (* Generate C# structure bindings. We prefix struct names with
10560 * underscore because C# cannot have conflicting struct names and
10561 * method names (eg. "class stat" and "stat").
10565 pr " [StructLayout (LayoutKind.Sequential)]\n";
10566 pr " public class _%s {\n" typ;
10569 | name, FChar -> pr " char %s;\n" name
10570 | name, FString -> pr " string %s;\n" name
10572 pr " uint %s_len;\n" name;
10573 pr " string %s;\n" name
10575 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10576 pr " string %s;\n" name
10577 | name, FUInt32 -> pr " uint %s;\n" name
10578 | name, FInt32 -> pr " int %s;\n" name
10579 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10580 | name, FInt64 -> pr " long %s;\n" name
10581 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10587 (* Generate C# function bindings. *)
10589 fun (name, style, _, _, _, shortdesc, _) ->
10590 let rec csharp_return_type () =
10591 match fst style with
10593 | RBool n -> "bool"
10595 | RInt64 n -> "long"
10597 | RConstOptString n
10599 | RBufferOut n -> "string"
10600 | RStruct (_,n) -> "_" ^ n
10601 | RHashtable n -> "Hashtable"
10602 | RStringList n -> "string[]"
10603 | RStructList (_,n) -> sprintf "_%s[]" n
10605 and c_return_type () =
10606 match fst style with
10610 | RInt64 _ -> "long"
10612 | RConstOptString _
10614 | RBufferOut _ -> "string"
10615 | RStruct (_,n) -> "_" ^ n
10617 | RStringList _ -> "string[]"
10618 | RStructList (_,n) -> sprintf "_%s[]" n
10620 and c_error_comparison () =
10621 match fst style with
10625 | RInt64 _ -> "== -1"
10627 | RConstOptString _
10633 | RStructList (_,_) -> "== null"
10635 and generate_extern_prototype () =
10636 pr " static extern %s guestfs_%s (IntPtr h"
10637 (c_return_type ()) name;
10640 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10641 | FileIn n | FileOut n ->
10642 pr ", [In] string %s" n
10643 | StringList n | DeviceList n ->
10644 pr ", [In] string[] %s" n
10654 and generate_public_prototype () =
10655 pr " public %s %s (" (csharp_return_type ()) name;
10656 let comma = ref false in
10658 if !comma then pr ", ";
10663 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10664 | FileIn n | FileOut n ->
10665 next (); pr "string %s" n
10666 | StringList n | DeviceList n ->
10667 next (); pr "string[] %s" n
10669 next (); pr "bool %s" n
10671 next (); pr "int %s" n
10673 next (); pr "long %s" n
10677 and generate_call () =
10678 pr "guestfs_%s (_handle" name;
10679 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10683 pr " [DllImport (\"%s\")]\n" library;
10684 generate_extern_prototype ();
10686 pr " /// <summary>\n";
10687 pr " /// %s\n" shortdesc;
10688 pr " /// </summary>\n";
10689 generate_public_prototype ();
10691 pr " %s r;\n" (c_return_type ());
10694 pr " if (r %s)\n" (c_error_comparison ());
10695 pr " throw new Error (guestfs_last_error (_handle));\n";
10696 (match fst style with
10699 pr " return r != 0 ? true : false;\n"
10701 pr " Hashtable rr = new Hashtable ();\n";
10702 pr " for (int i = 0; i < r.Length; i += 2)\n";
10703 pr " rr.Add (r[i], r[i+1]);\n";
10705 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10706 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10712 ) all_functions_sorted;
10718 and generate_bindtests () =
10719 generate_header CStyle LGPLv2plus;
10723 #include <stdlib.h>
10724 #include <inttypes.h>
10725 #include <string.h>
10727 #include \"guestfs.h\"
10728 #include \"guestfs-internal.h\"
10729 #include \"guestfs-internal-actions.h\"
10730 #include \"guestfs_protocol.h\"
10732 #define error guestfs_error
10733 #define safe_calloc guestfs_safe_calloc
10734 #define safe_malloc guestfs_safe_malloc
10737 print_strings (char *const *argv)
10742 for (argc = 0; argv[argc] != NULL; ++argc) {
10743 if (argc > 0) printf (\", \");
10744 printf (\"\\\"%%s\\\"\", argv[argc]);
10749 /* The test0 function prints its parameters to stdout. */
10753 match test_functions with
10754 | [] -> assert false
10755 | test0 :: tests -> test0, tests in
10758 let (name, style, _, _, _, _, _) = test0 in
10759 generate_prototype ~extern:false ~semicolon:false ~newline:true
10760 ~handle:"g" ~prefix:"guestfs__" name style;
10765 | Device n | Dev_or_Path n
10768 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10769 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10770 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10771 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10772 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10773 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10775 pr " /* Java changes stdout line buffering so we need this: */\n";
10776 pr " fflush (stdout);\n";
10782 fun (name, style, _, _, _, _, _) ->
10783 if String.sub name (String.length name - 3) 3 <> "err" then (
10784 pr "/* Test normal return. */\n";
10785 generate_prototype ~extern:false ~semicolon:false ~newline:true
10786 ~handle:"g" ~prefix:"guestfs__" name style;
10788 (match fst style with
10793 pr " sscanf (val, \"%%d\", &r);\n";
10796 pr " int64_t r;\n";
10797 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10800 pr " return STREQ (val, \"true\");\n"
10802 | RConstOptString _ ->
10803 (* Can't return the input string here. Return a static
10804 * string so we ensure we get a segfault if the caller
10805 * tries to free it.
10807 pr " return \"static string\";\n"
10809 pr " return strdup (val);\n"
10811 pr " char **strs;\n";
10813 pr " sscanf (val, \"%%d\", &n);\n";
10814 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10815 pr " for (i = 0; i < n; ++i) {\n";
10816 pr " strs[i] = safe_malloc (g, 16);\n";
10817 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10819 pr " strs[n] = NULL;\n";
10820 pr " return strs;\n"
10821 | RStruct (_, typ) ->
10822 pr " struct guestfs_%s *r;\n" typ;
10823 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10825 | RStructList (_, typ) ->
10826 pr " struct guestfs_%s_list *r;\n" typ;
10827 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10828 pr " sscanf (val, \"%%d\", &r->len);\n";
10829 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10832 pr " char **strs;\n";
10834 pr " sscanf (val, \"%%d\", &n);\n";
10835 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10836 pr " for (i = 0; i < n; ++i) {\n";
10837 pr " strs[i*2] = safe_malloc (g, 16);\n";
10838 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10839 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10840 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10842 pr " strs[n*2] = NULL;\n";
10843 pr " return strs;\n"
10845 pr " return strdup (val);\n"
10850 pr "/* Test error return. */\n";
10851 generate_prototype ~extern:false ~semicolon:false ~newline:true
10852 ~handle:"g" ~prefix:"guestfs__" name style;
10854 pr " error (g, \"error\");\n";
10855 (match fst style with
10856 | RErr | RInt _ | RInt64 _ | RBool _ ->
10858 | RConstString _ | RConstOptString _
10859 | RString _ | RStringList _ | RStruct _
10863 pr " return NULL;\n"
10870 and generate_ocaml_bindtests () =
10871 generate_header OCamlStyle GPLv2plus;
10875 let g = Guestfs.create () in
10879 String.concat " " (
10882 | CallString s -> "\"" ^ s ^ "\""
10883 | CallOptString None -> "None"
10884 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10885 | CallStringList xs ->
10886 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10887 | CallInt i when i >= 0 -> string_of_int i
10888 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10889 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10890 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10891 | CallBool b -> string_of_bool b
10896 generate_lang_bindtests (
10897 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10900 pr "print_endline \"EOF\"\n"
10902 and generate_perl_bindtests () =
10903 pr "#!/usr/bin/perl -w\n";
10904 generate_header HashStyle GPLv2plus;
10911 my $g = Sys::Guestfs->new ();
10915 String.concat ", " (
10918 | CallString s -> "\"" ^ s ^ "\""
10919 | CallOptString None -> "undef"
10920 | CallOptString (Some s) -> sprintf "\"%s\"" s
10921 | CallStringList xs ->
10922 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10923 | CallInt i -> string_of_int i
10924 | CallInt64 i -> Int64.to_string i
10925 | CallBool b -> if b then "1" else "0"
10930 generate_lang_bindtests (
10931 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10934 pr "print \"EOF\\n\"\n"
10936 and generate_python_bindtests () =
10937 generate_header HashStyle GPLv2plus;
10942 g = guestfs.GuestFS ()
10946 String.concat ", " (
10949 | CallString s -> "\"" ^ s ^ "\""
10950 | CallOptString None -> "None"
10951 | CallOptString (Some s) -> sprintf "\"%s\"" s
10952 | CallStringList xs ->
10953 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10954 | CallInt i -> string_of_int i
10955 | CallInt64 i -> Int64.to_string i
10956 | CallBool b -> if b then "1" else "0"
10961 generate_lang_bindtests (
10962 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10965 pr "print \"EOF\"\n"
10967 and generate_ruby_bindtests () =
10968 generate_header HashStyle GPLv2plus;
10973 g = Guestfs::create()
10977 String.concat ", " (
10980 | CallString s -> "\"" ^ s ^ "\""
10981 | CallOptString None -> "nil"
10982 | CallOptString (Some s) -> sprintf "\"%s\"" s
10983 | CallStringList xs ->
10984 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10985 | CallInt i -> string_of_int i
10986 | CallInt64 i -> Int64.to_string i
10987 | CallBool b -> string_of_bool b
10992 generate_lang_bindtests (
10993 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10996 pr "print \"EOF\\n\"\n"
10998 and generate_java_bindtests () =
10999 generate_header CStyle GPLv2plus;
11002 import com.redhat.et.libguestfs.*;
11004 public class Bindtests {
11005 public static void main (String[] argv)
11008 GuestFS g = new GuestFS ();
11012 String.concat ", " (
11015 | CallString s -> "\"" ^ s ^ "\""
11016 | CallOptString None -> "null"
11017 | CallOptString (Some s) -> sprintf "\"%s\"" s
11018 | CallStringList xs ->
11020 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11021 | CallInt i -> string_of_int i
11022 | CallInt64 i -> Int64.to_string i
11023 | CallBool b -> string_of_bool b
11028 generate_lang_bindtests (
11029 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11033 System.out.println (\"EOF\");
11035 catch (Exception exn) {
11036 System.err.println (exn);
11043 and generate_haskell_bindtests () =
11044 generate_header HaskellStyle GPLv2plus;
11047 module Bindtests where
11048 import qualified Guestfs
11051 g <- Guestfs.create
11055 String.concat " " (
11058 | CallString s -> "\"" ^ s ^ "\""
11059 | CallOptString None -> "Nothing"
11060 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11061 | CallStringList xs ->
11062 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11063 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11064 | CallInt i -> string_of_int i
11065 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11066 | CallInt64 i -> Int64.to_string i
11067 | CallBool true -> "True"
11068 | CallBool false -> "False"
11073 generate_lang_bindtests (
11074 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11077 pr " putStrLn \"EOF\"\n"
11079 (* Language-independent bindings tests - we do it this way to
11080 * ensure there is parity in testing bindings across all languages.
11082 and generate_lang_bindtests call =
11083 call "test0" [CallString "abc"; CallOptString (Some "def");
11084 CallStringList []; CallBool false;
11085 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086 call "test0" [CallString "abc"; CallOptString None;
11087 CallStringList []; CallBool false;
11088 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089 call "test0" [CallString ""; CallOptString (Some "def");
11090 CallStringList []; CallBool false;
11091 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092 call "test0" [CallString ""; CallOptString (Some "");
11093 CallStringList []; CallBool false;
11094 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095 call "test0" [CallString "abc"; CallOptString (Some "def");
11096 CallStringList ["1"]; CallBool false;
11097 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11098 call "test0" [CallString "abc"; CallOptString (Some "def");
11099 CallStringList ["1"; "2"]; CallBool false;
11100 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11101 call "test0" [CallString "abc"; CallOptString (Some "def");
11102 CallStringList ["1"]; CallBool true;
11103 CallInt 0; CallInt64 0L; 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 1; CallInt64 1L; CallString "123"; CallString "456"];
11113 call "test0" [CallString "abc"; CallOptString (Some "def");
11114 CallStringList ["1"]; CallBool false;
11115 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11116 call "test0" [CallString "abc"; CallOptString (Some "def");
11117 CallStringList ["1"]; CallBool false;
11118 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11119 call "test0" [CallString "abc"; CallOptString (Some "def");
11120 CallStringList ["1"]; CallBool false;
11121 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11123 (* XXX Add here tests of the return and error functions. *)
11125 (* Code to generator bindings for virt-inspector. Currently only
11126 * implemented for OCaml code (for virt-p2v 2.0).
11128 let rng_input = "inspector/virt-inspector.rng"
11130 (* Read the input file and parse it into internal structures. This is
11131 * by no means a complete RELAX NG parser, but is just enough to be
11132 * able to parse the specific input file.
11135 | Element of string * rng list (* <element name=name/> *)
11136 | Attribute of string * rng list (* <attribute name=name/> *)
11137 | Interleave of rng list (* <interleave/> *)
11138 | ZeroOrMore of rng (* <zeroOrMore/> *)
11139 | OneOrMore of rng (* <oneOrMore/> *)
11140 | Optional of rng (* <optional/> *)
11141 | Choice of string list (* <choice><value/>*</choice> *)
11142 | Value of string (* <value>str</value> *)
11143 | Text (* <text/> *)
11145 let rec string_of_rng = function
11146 | Element (name, xs) ->
11147 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11148 | Attribute (name, xs) ->
11149 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11150 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11151 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11152 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11153 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11154 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11155 | Value value -> "Value \"" ^ value ^ "\""
11158 and string_of_rng_list xs =
11159 String.concat ", " (List.map string_of_rng xs)
11161 let rec parse_rng ?defines context = function
11163 | Xml.Element ("element", ["name", name], children) :: rest ->
11164 Element (name, parse_rng ?defines context children)
11165 :: parse_rng ?defines context rest
11166 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11167 Attribute (name, parse_rng ?defines context children)
11168 :: parse_rng ?defines context rest
11169 | Xml.Element ("interleave", [], children) :: rest ->
11170 Interleave (parse_rng ?defines context children)
11171 :: parse_rng ?defines context rest
11172 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11173 let rng = parse_rng ?defines context [child] in
11175 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11177 failwithf "%s: <zeroOrMore> contains more than one child element"
11180 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11181 let rng = parse_rng ?defines context [child] in
11183 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11185 failwithf "%s: <oneOrMore> contains more than one child element"
11188 | Xml.Element ("optional", [], [child]) :: rest ->
11189 let rng = parse_rng ?defines context [child] in
11191 | [child] -> Optional child :: parse_rng ?defines context rest
11193 failwithf "%s: <optional> contains more than one child element"
11196 | Xml.Element ("choice", [], children) :: rest ->
11197 let values = List.map (
11198 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11200 failwithf "%s: can't handle anything except <value> in <choice>"
11204 :: parse_rng ?defines context rest
11205 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11206 Value value :: parse_rng ?defines context rest
11207 | Xml.Element ("text", [], []) :: rest ->
11208 Text :: parse_rng ?defines context rest
11209 | Xml.Element ("ref", ["name", name], []) :: rest ->
11210 (* Look up the reference. Because of limitations in this parser,
11211 * we can't handle arbitrarily nested <ref> yet. You can only
11212 * use <ref> from inside <start>.
11214 (match defines with
11216 failwithf "%s: contains <ref>, but no refs are defined yet" context
11218 let rng = StringMap.find name map in
11219 rng @ parse_rng ?defines context rest
11222 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11225 let xml = Xml.parse_file rng_input in
11227 | Xml.Element ("grammar", _,
11228 Xml.Element ("start", _, gram) :: defines) ->
11229 (* The <define/> elements are referenced in the <start> section,
11230 * so build a map of those first.
11232 let defines = List.fold_left (
11234 function Xml.Element ("define", ["name", name], defn) ->
11235 StringMap.add name defn map
11237 failwithf "%s: expected <define name=name/>" rng_input
11238 ) StringMap.empty defines in
11239 let defines = StringMap.mapi parse_rng defines in
11241 (* Parse the <start> clause, passing the defines. *)
11242 parse_rng ~defines "<start>" gram
11244 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11247 let name_of_field = function
11248 | Element (name, _) | Attribute (name, _)
11249 | ZeroOrMore (Element (name, _))
11250 | OneOrMore (Element (name, _))
11251 | Optional (Element (name, _)) -> name
11252 | Optional (Attribute (name, _)) -> name
11253 | Text -> (* an unnamed field in an element *)
11256 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11258 (* At the moment this function only generates OCaml types. However we
11259 * should parameterize it later so it can generate types/structs in a
11260 * variety of languages.
11262 let generate_types xs =
11263 (* A simple type is one that can be printed out directly, eg.
11264 * "string option". A complex type is one which has a name and has
11265 * to be defined via another toplevel definition, eg. a struct.
11267 * generate_type generates code for either simple or complex types.
11268 * In the simple case, it returns the string ("string option"). In
11269 * the complex case, it returns the name ("mountpoint"). In the
11270 * complex case it has to print out the definition before returning,
11271 * so it should only be called when we are at the beginning of a
11272 * new line (BOL context).
11274 let rec generate_type = function
11275 | Text -> (* string *)
11277 | Choice values -> (* [`val1|`val2|...] *)
11278 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11279 | ZeroOrMore rng -> (* <rng> list *)
11280 let t, is_simple = generate_type rng in
11281 t ^ " list (* 0 or more *)", is_simple
11282 | OneOrMore rng -> (* <rng> list *)
11283 let t, is_simple = generate_type rng in
11284 t ^ " list (* 1 or more *)", is_simple
11285 (* virt-inspector hack: bool *)
11286 | Optional (Attribute (name, [Value "1"])) ->
11288 | Optional rng -> (* <rng> list *)
11289 let t, is_simple = generate_type rng in
11290 t ^ " option", is_simple
11291 (* type name = { fields ... } *)
11292 | Element (name, fields) when is_attrs_interleave fields ->
11293 generate_type_struct name (get_attrs_interleave fields)
11294 | Element (name, [field]) (* type name = field *)
11295 | Attribute (name, [field]) ->
11296 let t, is_simple = generate_type field in
11297 if is_simple then (t, true)
11299 pr "type %s = %s\n" name t;
11302 | Element (name, fields) -> (* type name = { fields ... } *)
11303 generate_type_struct name fields
11305 failwithf "generate_type failed at: %s" (string_of_rng rng)
11307 and is_attrs_interleave = function
11308 | [Interleave _] -> true
11309 | Attribute _ :: fields -> is_attrs_interleave fields
11310 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11313 and get_attrs_interleave = function
11314 | [Interleave fields] -> fields
11315 | ((Attribute _) as field) :: fields
11316 | ((Optional (Attribute _)) as field) :: fields ->
11317 field :: get_attrs_interleave fields
11318 | _ -> assert false
11320 and generate_types xs =
11321 List.iter (fun x -> ignore (generate_type x)) xs
11323 and generate_type_struct name fields =
11324 (* Calculate the types of the fields first. We have to do this
11325 * before printing anything so we are still in BOL context.
11327 let types = List.map fst (List.map generate_type fields) in
11329 (* Special case of a struct containing just a string and another
11330 * field. Turn it into an assoc list.
11333 | ["string"; other] ->
11334 let fname1, fname2 =
11336 | [f1; f2] -> name_of_field f1, name_of_field f2
11337 | _ -> assert false in
11338 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11342 pr "type %s = {\n" name;
11344 fun (field, ftype) ->
11345 let fname = name_of_field field in
11346 pr " %s_%s : %s;\n" name fname ftype
11347 ) (List.combine fields types);
11349 (* Return the name of this type, and
11350 * false because it's not a simple type.
11357 let generate_parsers xs =
11358 (* As for generate_type above, generate_parser makes a parser for
11359 * some type, and returns the name of the parser it has generated.
11360 * Because it (may) need to print something, it should always be
11361 * called in BOL context.
11363 let rec generate_parser = function
11364 | Text -> (* string *)
11365 "string_child_or_empty"
11366 | Choice values -> (* [`val1|`val2|...] *)
11367 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11369 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11370 | ZeroOrMore rng -> (* <rng> list *)
11371 let pa = generate_parser rng in
11372 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11373 | OneOrMore rng -> (* <rng> list *)
11374 let pa = generate_parser rng in
11375 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11376 (* virt-inspector hack: bool *)
11377 | Optional (Attribute (name, [Value "1"])) ->
11378 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11379 | Optional rng -> (* <rng> list *)
11380 let pa = generate_parser rng in
11381 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11382 (* type name = { fields ... } *)
11383 | Element (name, fields) when is_attrs_interleave fields ->
11384 generate_parser_struct name (get_attrs_interleave fields)
11385 | Element (name, [field]) -> (* type name = field *)
11386 let pa = generate_parser field in
11387 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11388 pr "let %s =\n" parser_name;
11390 pr "let parse_%s = %s\n" name parser_name;
11392 | Attribute (name, [field]) ->
11393 let pa = generate_parser field in
11394 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11395 pr "let %s =\n" parser_name;
11397 pr "let parse_%s = %s\n" name parser_name;
11399 | Element (name, fields) -> (* type name = { fields ... } *)
11400 generate_parser_struct name ([], fields)
11402 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11404 and is_attrs_interleave = function
11405 | [Interleave _] -> true
11406 | Attribute _ :: fields -> is_attrs_interleave fields
11407 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11410 and get_attrs_interleave = function
11411 | [Interleave fields] -> [], fields
11412 | ((Attribute _) as field) :: fields
11413 | ((Optional (Attribute _)) as field) :: fields ->
11414 let attrs, interleaves = get_attrs_interleave fields in
11415 (field :: attrs), interleaves
11416 | _ -> assert false
11418 and generate_parsers xs =
11419 List.iter (fun x -> ignore (generate_parser x)) xs
11421 and generate_parser_struct name (attrs, interleaves) =
11422 (* Generate parsers for the fields first. We have to do this
11423 * before printing anything so we are still in BOL context.
11425 let fields = attrs @ interleaves in
11426 let pas = List.map generate_parser fields in
11428 (* Generate an intermediate tuple from all the fields first.
11429 * If the type is just a string + another field, then we will
11430 * return this directly, otherwise it is turned into a record.
11432 * RELAX NG note: This code treats <interleave> and plain lists of
11433 * fields the same. In other words, it doesn't bother enforcing
11434 * any ordering of fields in the XML.
11436 pr "let parse_%s x =\n" name;
11437 pr " let t = (\n ";
11438 let comma = ref false in
11441 if !comma then pr ",\n ";
11444 | Optional (Attribute (fname, [field])), pa ->
11446 | Optional (Element (fname, [field])), pa ->
11447 pr "%s (optional_child %S x)" pa fname
11448 | Attribute (fname, [Text]), _ ->
11449 pr "attribute %S x" fname
11450 | (ZeroOrMore _ | OneOrMore _), pa ->
11455 let fname = name_of_field field in
11456 pr "%s (child %S x)" pa fname
11457 ) (List.combine fields pas);
11461 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11465 pr " (Obj.magic t : %s)\n" name
11469 | (Optional (Attribute (fname, [field])), pa) ->
11470 pr " %s_%s =\n" name fname;
11472 | (Optional (Element (fname, [field])), pa) ->
11473 pr " %s_%s =\n" name fname;
11474 pr " (let x = optional_child %S x in\n" fname;
11477 let fname = name_of_field field in
11478 pr " %s_%s =\n" name fname;
11479 pr " (let x = child %S x in\n" fname;
11481 ) (List.combine fields pas);
11485 sprintf "parse_%s" name
11488 generate_parsers xs
11490 (* Generate ocaml/guestfs_inspector.mli. *)
11491 let generate_ocaml_inspector_mli () =
11492 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11495 (** This is an OCaml language binding to the external [virt-inspector]
11498 For more information, please read the man page [virt-inspector(1)].
11503 generate_types grammar;
11504 pr "(** The nested information returned from the {!inspect} function. *)\n";
11508 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11509 (** To inspect a libvirt domain called [name], pass a singleton
11510 list: [inspect [name]]. When using libvirt only, you may
11511 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11513 To inspect a disk image or images, pass a list of the filenames
11514 of the disk images: [inspect filenames]
11516 This function inspects the given guest or disk images and
11517 returns a list of operating system(s) found and a large amount
11518 of information about them. In the vast majority of cases,
11519 a virtual machine only contains a single operating system.
11521 If the optional [~xml] parameter is given, then this function
11522 skips running the external virt-inspector program and just
11523 parses the given XML directly (which is expected to be XML
11524 produced from a previous run of virt-inspector). The list of
11525 names and connect URI are ignored in this case.
11527 This function can throw a wide variety of exceptions, for example
11528 if the external virt-inspector program cannot be found, or if
11529 it doesn't generate valid XML.
11533 (* Generate ocaml/guestfs_inspector.ml. *)
11534 let generate_ocaml_inspector_ml () =
11535 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11540 generate_types grammar;
11544 (* Misc functions which are used by the parser code below. *)
11545 let first_child = function
11546 | Xml.Element (_, _, c::_) -> c
11547 | Xml.Element (name, _, []) ->
11548 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11549 | Xml.PCData str ->
11550 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11552 let string_child_or_empty = function
11553 | Xml.Element (_, _, [Xml.PCData s]) -> s
11554 | Xml.Element (_, _, []) -> \"\"
11555 | Xml.Element (x, _, _) ->
11556 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11558 | Xml.PCData str ->
11559 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11561 let optional_child name xml =
11562 let children = Xml.children xml in
11564 Some (List.find (function
11565 | Xml.Element (n, _, _) when n = name -> true
11566 | _ -> false) children)
11570 let child name xml =
11571 match optional_child name xml with
11574 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11576 let attribute name xml =
11577 try Xml.attrib xml name
11578 with Xml.No_attribute _ ->
11579 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11583 generate_parsers grammar;
11587 (* Run external virt-inspector, then use parser to parse the XML. *)
11588 let inspect ?connect ?xml names =
11592 if names = [] then invalid_arg \"inspect: no names given\";
11593 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11594 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11596 let cmd = List.map Filename.quote cmd in
11597 let cmd = String.concat \" \" cmd in
11598 let chan = open_process_in cmd in
11599 let xml = Xml.parse_in chan in
11600 (match close_process_in chan with
11602 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11603 | WSIGNALED i | WSTOPPED i ->
11604 failwith (\"external virt-inspector command died or stopped on sig \" ^
11609 Xml.parse_string doc in
11610 parse_operatingsystems xml
11613 (* This is used to generate the src/MAX_PROC_NR file which
11614 * contains the maximum procedure number, a surrogate for the
11615 * ABI version number. See src/Makefile.am for the details.
11617 and generate_max_proc_nr () =
11618 let proc_nrs = List.map (
11619 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11620 ) daemon_functions in
11622 let max_proc_nr = List.fold_left max 0 proc_nrs in
11624 pr "%d\n" max_proc_nr
11626 let output_to filename k =
11627 let filename_new = filename ^ ".new" in
11628 chan := open_out filename_new;
11631 chan := Pervasives.stdout;
11633 (* Is the new file different from the current file? *)
11634 if Sys.file_exists filename && files_equal filename filename_new then
11635 unlink filename_new (* same, so skip it *)
11637 (* different, overwrite old one *)
11638 (try chmod filename 0o644 with Unix_error _ -> ());
11639 rename filename_new filename;
11640 chmod filename 0o444;
11641 printf "written %s\n%!" filename;
11644 let perror msg = function
11645 | Unix_error (err, _, _) ->
11646 eprintf "%s: %s\n" msg (error_message err)
11648 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11650 (* Main program. *)
11653 try openfile "HACKING" [O_RDWR] 0
11655 | Unix_error (ENOENT, _, _) ->
11657 You are probably running this from the wrong directory.
11658 Run it from the top source directory using the command
11663 perror "open: HACKING" exn;
11666 (* Acquire a lock so parallel builds won't try to run the generator
11667 * twice at the same time. Subsequent builds will wait for the first
11668 * one to finish. Note the lock is released implicitly when the
11671 (try lockf lock_fd F_LOCK 1
11673 perror "lock: HACKING" exn;
11676 check_functions ();
11678 output_to "src/guestfs_protocol.x" generate_xdr;
11679 output_to "src/guestfs-structs.h" generate_structs_h;
11680 output_to "src/guestfs-actions.h" generate_actions_h;
11681 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11682 output_to "src/guestfs-actions.c" generate_client_actions;
11683 output_to "src/guestfs-bindtests.c" generate_bindtests;
11684 output_to "src/guestfs-structs.pod" generate_structs_pod;
11685 output_to "src/guestfs-actions.pod" generate_actions_pod;
11686 output_to "src/guestfs-availability.pod" generate_availability_pod;
11687 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11688 output_to "src/libguestfs.syms" generate_linker_script;
11689 output_to "daemon/actions.h" generate_daemon_actions_h;
11690 output_to "daemon/stubs.c" generate_daemon_actions;
11691 output_to "daemon/names.c" generate_daemon_names;
11692 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11693 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11694 output_to "capitests/tests.c" generate_tests;
11695 output_to "fish/cmds.c" generate_fish_cmds;
11696 output_to "fish/completion.c" generate_fish_completion;
11697 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11698 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11699 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11700 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11701 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11702 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11703 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11704 output_to "perl/Guestfs.xs" generate_perl_xs;
11705 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11706 output_to "perl/bindtests.pl" generate_perl_bindtests;
11707 output_to "python/guestfs-py.c" generate_python_c;
11708 output_to "python/guestfs.py" generate_python_py;
11709 output_to "python/bindtests.py" generate_python_bindtests;
11710 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11711 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11712 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11716 let cols = cols_of_struct typ in
11717 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11718 output_to filename (generate_java_struct jtyp cols);
11721 output_to "java/Makefile.inc" generate_java_makefile_inc;
11722 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11723 output_to "java/Bindtests.java" generate_java_bindtests;
11724 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11725 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11726 output_to "csharp/Libguestfs.cs" generate_csharp;
11728 (* Always generate this file last, and unconditionally. It's used
11729 * by the Makefile to know when we must re-run the generator.
11731 let chan = open_out "src/stamp-generator" in
11732 fprintf chan "1\n";
11735 printf "generated %d lines of code\n" !lines