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 (* Test for RHBZ#579608, absolute symbolic links. *)
2451 InitISOFS, Always, TestRun (
2452 [["strings"; "/abssymlink"]])],
2453 "print the printable strings in a file",
2455 This runs the L<strings(1)> command on a file and returns
2456 the list of printable strings found.");
2458 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2459 [InitISOFS, Always, TestOutputList (
2460 [["strings_e"; "b"; "/known-5"]], []);
2461 InitBasicFS, Disabled, TestOutputList (
2462 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2463 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2464 "print the printable strings in a file",
2466 This is like the C<guestfs_strings> command, but allows you to
2467 specify the encoding.
2469 See the L<strings(1)> manpage for the full list of encodings.
2471 Commonly useful encodings are C<l> (lower case L) which will
2472 show strings inside Windows/x86 files.
2474 The returned strings are transcoded to UTF-8.");
2476 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2477 [InitISOFS, Always, TestOutput (
2478 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2479 (* Test for RHBZ#501888c2 regression which caused large hexdump
2480 * commands to segfault.
2482 InitISOFS, Always, TestRun (
2483 [["hexdump"; "/100krandom"]]);
2484 (* Test for RHBZ#579608, absolute symbolic links. *)
2485 InitISOFS, Always, TestRun (
2486 [["hexdump"; "/abssymlink"]])],
2487 "dump a file in hexadecimal",
2489 This runs C<hexdump -C> on the given C<path>. The result is
2490 the human-readable, canonical hex dump of the file.");
2492 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2493 [InitNone, Always, TestOutput (
2494 [["part_disk"; "/dev/sda"; "mbr"];
2495 ["mkfs"; "ext3"; "/dev/sda1"];
2496 ["mount_options"; ""; "/dev/sda1"; "/"];
2497 ["write_file"; "/new"; "test file"; "0"];
2498 ["umount"; "/dev/sda1"];
2499 ["zerofree"; "/dev/sda1"];
2500 ["mount_options"; ""; "/dev/sda1"; "/"];
2501 ["cat"; "/new"]], "test file")],
2502 "zero unused inodes and disk blocks on ext2/3 filesystem",
2504 This runs the I<zerofree> program on C<device>. This program
2505 claims to zero unused inodes and disk blocks on an ext2/3
2506 filesystem, thus making it possible to compress the filesystem
2509 You should B<not> run this program if the filesystem is
2512 It is possible that using this program can damage the filesystem
2513 or data on the filesystem.");
2515 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2517 "resize an LVM physical volume",
2519 This resizes (expands or shrinks) an existing LVM physical
2520 volume to match the new size of the underlying device.");
2522 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2523 Int "cyls"; Int "heads"; Int "sectors";
2524 String "line"]), 99, [DangerWillRobinson],
2526 "modify a single partition on a block device",
2528 This runs L<sfdisk(8)> option to modify just the single
2529 partition C<n> (note: C<n> counts from 1).
2531 For other parameters, see C<guestfs_sfdisk>. You should usually
2532 pass C<0> for the cyls/heads/sectors parameters.
2534 See also: C<guestfs_part_add>");
2536 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2538 "display the partition table",
2540 This displays the partition table on C<device>, in the
2541 human-readable output of the L<sfdisk(8)> command. It is
2542 not intended to be parsed.
2544 See also: C<guestfs_part_list>");
2546 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2548 "display the kernel geometry",
2550 This displays the kernel's idea of the geometry of C<device>.
2552 The result is in human-readable format, and not designed to
2555 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2557 "display the disk geometry from the partition table",
2559 This displays the disk geometry of C<device> read from the
2560 partition table. Especially in the case where the underlying
2561 block device has been resized, this can be different from the
2562 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2564 The result is in human-readable format, and not designed to
2567 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2569 "activate or deactivate all volume groups",
2571 This command activates or (if C<activate> is false) deactivates
2572 all logical volumes in all volume groups.
2573 If activated, then they are made known to the
2574 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2575 then those devices disappear.
2577 This command is the same as running C<vgchange -a y|n>");
2579 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2581 "activate or deactivate some volume groups",
2583 This command activates or (if C<activate> is false) deactivates
2584 all logical volumes in the listed volume groups C<volgroups>.
2585 If activated, then they are made known to the
2586 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2587 then those devices disappear.
2589 This command is the same as running C<vgchange -a y|n volgroups...>
2591 Note that if C<volgroups> is an empty list then B<all> volume groups
2592 are activated or deactivated.");
2594 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2595 [InitNone, Always, TestOutput (
2596 [["part_disk"; "/dev/sda"; "mbr"];
2597 ["pvcreate"; "/dev/sda1"];
2598 ["vgcreate"; "VG"; "/dev/sda1"];
2599 ["lvcreate"; "LV"; "VG"; "10"];
2600 ["mkfs"; "ext2"; "/dev/VG/LV"];
2601 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2602 ["write_file"; "/new"; "test content"; "0"];
2604 ["lvresize"; "/dev/VG/LV"; "20"];
2605 ["e2fsck_f"; "/dev/VG/LV"];
2606 ["resize2fs"; "/dev/VG/LV"];
2607 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2608 ["cat"; "/new"]], "test content");
2609 InitNone, Always, TestRun (
2610 (* Make an LV smaller to test RHBZ#587484. *)
2611 [["part_disk"; "/dev/sda"; "mbr"];
2612 ["pvcreate"; "/dev/sda1"];
2613 ["vgcreate"; "VG"; "/dev/sda1"];
2614 ["lvcreate"; "LV"; "VG"; "20"];
2615 ["lvresize"; "/dev/VG/LV"; "10"]])],
2616 "resize an LVM logical volume",
2618 This resizes (expands or shrinks) an existing LVM logical
2619 volume to C<mbytes>. When reducing, data in the reduced part
2622 ("resize2fs", (RErr, [Device "device"]), 106, [],
2623 [], (* lvresize tests this *)
2624 "resize an ext2/ext3 filesystem",
2626 This resizes an ext2 or ext3 filesystem to match the size of
2627 the underlying device.
2629 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2630 on the C<device> before calling this command. For unknown reasons
2631 C<resize2fs> sometimes gives an error about this and sometimes not.
2632 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2633 calling this function.");
2635 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2636 [InitBasicFS, Always, TestOutputList (
2637 [["find"; "/"]], ["lost+found"]);
2638 InitBasicFS, Always, TestOutputList (
2642 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2643 InitBasicFS, Always, TestOutputList (
2644 [["mkdir_p"; "/a/b/c"];
2645 ["touch"; "/a/b/c/d"];
2646 ["find"; "/a/b/"]], ["c"; "c/d"])],
2647 "find all files and directories",
2649 This command lists out all files and directories, recursively,
2650 starting at C<directory>. It is essentially equivalent to
2651 running the shell command C<find directory -print> but some
2652 post-processing happens on the output, described below.
2654 This returns a list of strings I<without any prefix>. Thus
2655 if the directory structure was:
2661 then the returned list from C<guestfs_find> C</tmp> would be
2669 If C<directory> is not a directory, then this command returns
2672 The returned list is sorted.
2674 See also C<guestfs_find0>.");
2676 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2677 [], (* lvresize tests this *)
2678 "check an ext2/ext3 filesystem",
2680 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2681 filesystem checker on C<device>, noninteractively (C<-p>),
2682 even if the filesystem appears to be clean (C<-f>).
2684 This command is only needed because of C<guestfs_resize2fs>
2685 (q.v.). Normally you should use C<guestfs_fsck>.");
2687 ("sleep", (RErr, [Int "secs"]), 109, [],
2688 [InitNone, Always, TestRun (
2690 "sleep for some seconds",
2692 Sleep for C<secs> seconds.");
2694 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2695 [InitNone, Always, TestOutputInt (
2696 [["part_disk"; "/dev/sda"; "mbr"];
2697 ["mkfs"; "ntfs"; "/dev/sda1"];
2698 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2699 InitNone, Always, TestOutputInt (
2700 [["part_disk"; "/dev/sda"; "mbr"];
2701 ["mkfs"; "ext2"; "/dev/sda1"];
2702 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2703 "probe NTFS volume",
2705 This command runs the L<ntfs-3g.probe(8)> command which probes
2706 an NTFS C<device> for mountability. (Not all NTFS volumes can
2707 be mounted read-write, and some cannot be mounted at all).
2709 C<rw> is a boolean flag. Set it to true if you want to test
2710 if the volume can be mounted read-write. Set it to false if
2711 you want to test if the volume can be mounted read-only.
2713 The return value is an integer which C<0> if the operation
2714 would succeed, or some non-zero value documented in the
2715 L<ntfs-3g.probe(8)> manual page.");
2717 ("sh", (RString "output", [String "command"]), 111, [],
2718 [], (* XXX needs tests *)
2719 "run a command via the shell",
2721 This call runs a command from the guest filesystem via the
2724 This is like C<guestfs_command>, but passes the command to:
2726 /bin/sh -c \"command\"
2728 Depending on the guest's shell, this usually results in
2729 wildcards being expanded, shell expressions being interpolated
2732 All the provisos about C<guestfs_command> apply to this call.");
2734 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2735 [], (* XXX needs tests *)
2736 "run a command via the shell returning lines",
2738 This is the same as C<guestfs_sh>, but splits the result
2739 into a list of lines.
2741 See also: C<guestfs_command_lines>");
2743 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2744 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2745 * code in stubs.c, since all valid glob patterns must start with "/".
2746 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2748 [InitBasicFS, Always, TestOutputList (
2749 [["mkdir_p"; "/a/b/c"];
2750 ["touch"; "/a/b/c/d"];
2751 ["touch"; "/a/b/c/e"];
2752 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2753 InitBasicFS, Always, TestOutputList (
2754 [["mkdir_p"; "/a/b/c"];
2755 ["touch"; "/a/b/c/d"];
2756 ["touch"; "/a/b/c/e"];
2757 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758 InitBasicFS, Always, TestOutputList (
2759 [["mkdir_p"; "/a/b/c"];
2760 ["touch"; "/a/b/c/d"];
2761 ["touch"; "/a/b/c/e"];
2762 ["glob_expand"; "/a/*/x/*"]], [])],
2763 "expand a wildcard path",
2765 This command searches for all the pathnames matching
2766 C<pattern> according to the wildcard expansion rules
2769 If no paths match, then this returns an empty list
2770 (note: not an error).
2772 It is just a wrapper around the C L<glob(3)> function
2773 with flags C<GLOB_MARK|GLOB_BRACE>.
2774 See that manual page for more details.");
2776 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2777 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2778 [["scrub_device"; "/dev/sdc"]])],
2779 "scrub (securely wipe) a device",
2781 This command writes patterns over C<device> to make data retrieval
2784 It is an interface to the L<scrub(1)> program. See that
2785 manual page for more details.");
2787 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2788 [InitBasicFS, Always, TestRun (
2789 [["write_file"; "/file"; "content"; "0"];
2790 ["scrub_file"; "/file"]])],
2791 "scrub (securely wipe) a file",
2793 This command writes patterns over a file to make data retrieval
2796 The file is I<removed> after scrubbing.
2798 It is an interface to the L<scrub(1)> program. See that
2799 manual page for more details.");
2801 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2802 [], (* XXX needs testing *)
2803 "scrub (securely wipe) free space",
2805 This command creates the directory C<dir> and then fills it
2806 with files until the filesystem is full, and scrubs the files
2807 as for C<guestfs_scrub_file>, and deletes them.
2808 The intention is to scrub any free space on the partition
2811 It is an interface to the L<scrub(1)> program. See that
2812 manual page for more details.");
2814 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2815 [InitBasicFS, Always, TestRun (
2817 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2818 "create a temporary directory",
2820 This command creates a temporary directory. The
2821 C<template> parameter should be a full pathname for the
2822 temporary directory name with the final six characters being
2825 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2826 the second one being suitable for Windows filesystems.
2828 The name of the temporary directory that was created
2831 The temporary directory is created with mode 0700
2832 and is owned by root.
2834 The caller is responsible for deleting the temporary
2835 directory and its contents after use.
2837 See also: L<mkdtemp(3)>");
2839 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2840 [InitISOFS, Always, TestOutputInt (
2841 [["wc_l"; "/10klines"]], 10000)],
2842 "count lines in a file",
2844 This command counts the lines in a file, using the
2845 C<wc -l> external command.");
2847 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2848 [InitISOFS, Always, TestOutputInt (
2849 [["wc_w"; "/10klines"]], 10000)],
2850 "count words in a file",
2852 This command counts the words in a file, using the
2853 C<wc -w> external command.");
2855 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2856 [InitISOFS, Always, TestOutputInt (
2857 [["wc_c"; "/100kallspaces"]], 102400)],
2858 "count characters in a file",
2860 This command counts the characters in a file, using the
2861 C<wc -c> external command.");
2863 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2864 [InitISOFS, Always, TestOutputList (
2865 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2866 (* Test for RHBZ#579608, absolute symbolic links. *)
2867 InitISOFS, Always, TestOutputList (
2868 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2869 "return first 10 lines of a file",
2871 This command returns up to the first 10 lines of a file as
2872 a list of strings.");
2874 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2875 [InitISOFS, Always, TestOutputList (
2876 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2877 InitISOFS, Always, TestOutputList (
2878 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2879 InitISOFS, Always, TestOutputList (
2880 [["head_n"; "0"; "/10klines"]], [])],
2881 "return first N lines of a file",
2883 If the parameter C<nrlines> is a positive number, this returns the first
2884 C<nrlines> lines of the file C<path>.
2886 If the parameter C<nrlines> is a negative number, this returns lines
2887 from the file C<path>, excluding the last C<nrlines> lines.
2889 If the parameter C<nrlines> is zero, this returns an empty list.");
2891 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2892 [InitISOFS, Always, TestOutputList (
2893 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2894 "return last 10 lines of a file",
2896 This command returns up to the last 10 lines of a file as
2897 a list of strings.");
2899 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2900 [InitISOFS, Always, TestOutputList (
2901 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2902 InitISOFS, Always, TestOutputList (
2903 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2904 InitISOFS, Always, TestOutputList (
2905 [["tail_n"; "0"; "/10klines"]], [])],
2906 "return last N lines of a file",
2908 If the parameter C<nrlines> is a positive number, this returns the last
2909 C<nrlines> lines of the file C<path>.
2911 If the parameter C<nrlines> is a negative number, this returns lines
2912 from the file C<path>, starting with the C<-nrlines>th line.
2914 If the parameter C<nrlines> is zero, this returns an empty list.");
2916 ("df", (RString "output", []), 125, [],
2917 [], (* XXX Tricky to test because it depends on the exact format
2918 * of the 'df' command and other imponderables.
2920 "report file system disk space usage",
2922 This command runs the C<df> command to report disk space used.
2924 This command is mostly useful for interactive sessions. It
2925 is I<not> intended that you try to parse the output string.
2926 Use C<statvfs> from programs.");
2928 ("df_h", (RString "output", []), 126, [],
2929 [], (* XXX Tricky to test because it depends on the exact format
2930 * of the 'df' command and other imponderables.
2932 "report file system disk space usage (human readable)",
2934 This command runs the C<df -h> command to report disk space used
2935 in human-readable format.
2937 This command is mostly useful for interactive sessions. It
2938 is I<not> intended that you try to parse the output string.
2939 Use C<statvfs> from programs.");
2941 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2942 [InitISOFS, Always, TestOutputInt (
2943 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2944 "estimate file space usage",
2946 This command runs the C<du -s> command to estimate file space
2949 C<path> can be a file or a directory. If C<path> is a directory
2950 then the estimate includes the contents of the directory and all
2951 subdirectories (recursively).
2953 The result is the estimated size in I<kilobytes>
2954 (ie. units of 1024 bytes).");
2956 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2957 [InitISOFS, Always, TestOutputList (
2958 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2959 "list files in an initrd",
2961 This command lists out files contained in an initrd.
2963 The files are listed without any initial C</> character. The
2964 files are listed in the order they appear (not necessarily
2965 alphabetical). Directory names are listed as separate items.
2967 Old Linux kernels (2.4 and earlier) used a compressed ext2
2968 filesystem as initrd. We I<only> support the newer initramfs
2969 format (compressed cpio files).");
2971 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2973 "mount a file using the loop device",
2975 This command lets you mount C<file> (a filesystem image
2976 in a file) on a mount point. It is entirely equivalent to
2977 the command C<mount -o loop file mountpoint>.");
2979 ("mkswap", (RErr, [Device "device"]), 130, [],
2980 [InitEmpty, Always, TestRun (
2981 [["part_disk"; "/dev/sda"; "mbr"];
2982 ["mkswap"; "/dev/sda1"]])],
2983 "create a swap partition",
2985 Create a swap partition on C<device>.");
2987 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2988 [InitEmpty, Always, TestRun (
2989 [["part_disk"; "/dev/sda"; "mbr"];
2990 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2991 "create a swap partition with a label",
2993 Create a swap partition on C<device> with label C<label>.
2995 Note that you cannot attach a swap label to a block device
2996 (eg. C</dev/sda>), just to a partition. This appears to be
2997 a limitation of the kernel or swap tools.");
2999 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3000 (let uuid = uuidgen () in
3001 [InitEmpty, Always, TestRun (
3002 [["part_disk"; "/dev/sda"; "mbr"];
3003 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3004 "create a swap partition with an explicit UUID",
3006 Create a swap partition on C<device> with UUID C<uuid>.");
3008 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3009 [InitBasicFS, Always, TestOutputStruct (
3010 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3011 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3012 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3013 InitBasicFS, Always, TestOutputStruct (
3014 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3015 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3016 "make block, character or FIFO devices",
3018 This call creates block or character special devices, or
3019 named pipes (FIFOs).
3021 The C<mode> parameter should be the mode, using the standard
3022 constants. C<devmajor> and C<devminor> are the
3023 device major and minor numbers, only used when creating block
3024 and character special devices.
3026 Note that, just like L<mknod(2)>, the mode must be bitwise
3027 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3028 just creates a regular file). These constants are
3029 available in the standard Linux header files, or you can use
3030 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3031 which are wrappers around this command which bitwise OR
3032 in the appropriate constant for you.
3034 The mode actually set is affected by the umask.");
3036 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3037 [InitBasicFS, Always, TestOutputStruct (
3038 [["mkfifo"; "0o777"; "/node"];
3039 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3040 "make FIFO (named pipe)",
3042 This call creates a FIFO (named pipe) called C<path> with
3043 mode C<mode>. It is just a convenient wrapper around
3046 The mode actually set is affected by the umask.");
3048 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3049 [InitBasicFS, Always, TestOutputStruct (
3050 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3051 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3052 "make block device node",
3054 This call creates a block device node called C<path> with
3055 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3056 It is just a convenient wrapper around C<guestfs_mknod>.
3058 The mode actually set is affected by the umask.");
3060 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3061 [InitBasicFS, Always, TestOutputStruct (
3062 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3063 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3064 "make char device node",
3066 This call creates a char device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3070 The mode actually set is affected by the umask.");
3072 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3073 [InitEmpty, Always, TestOutputInt (
3074 [["umask"; "0o22"]], 0o22)],
3075 "set file mode creation mask (umask)",
3077 This function sets the mask used for creating new files and
3078 device nodes to C<mask & 0777>.
3080 Typical umask values would be C<022> which creates new files
3081 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3082 C<002> which creates new files with permissions like
3083 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3085 The default umask is C<022>. This is important because it
3086 means that directories and device nodes will be created with
3087 C<0644> or C<0755> mode even if you specify C<0777>.
3089 See also C<guestfs_get_umask>,
3090 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3092 This call returns the previous umask.");
3094 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3096 "read directories entries",
3098 This returns the list of directory entries in directory C<dir>.
3100 All entries in the directory are returned, including C<.> and
3101 C<..>. The entries are I<not> sorted, but returned in the same
3102 order as the underlying filesystem.
3104 Also this call returns basic file type information about each
3105 file. The C<ftyp> field will contain one of the following characters:
3143 The L<readdir(3)> returned a C<d_type> field with an
3148 This function is primarily intended for use by programs. To
3149 get a simple list of names, use C<guestfs_ls>. To get a printable
3150 directory for human consumption, use C<guestfs_ll>.");
3152 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3154 "create partitions on a block device",
3156 This is a simplified interface to the C<guestfs_sfdisk>
3157 command, where partition sizes are specified in megabytes
3158 only (rounded to the nearest cylinder) and you don't need
3159 to specify the cyls, heads and sectors parameters which
3160 were rarely if ever used anyway.
3162 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3163 and C<guestfs_part_disk>");
3165 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3167 "determine file type inside a compressed file",
3169 This command runs C<file> after first decompressing C<path>
3172 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3174 Since 1.0.63, use C<guestfs_file> instead which can now
3175 process compressed files.");
3177 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3179 "list extended attributes of a file or directory",
3181 This call lists the extended attributes of the file or directory
3184 At the system call level, this is a combination of the
3185 L<listxattr(2)> and L<getxattr(2)> calls.
3187 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3189 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3191 "list extended attributes of a file or directory",
3193 This is the same as C<guestfs_getxattrs>, but if C<path>
3194 is a symbolic link, then it returns the extended attributes
3195 of the link itself.");
3197 ("setxattr", (RErr, [String "xattr";
3198 String "val"; Int "vallen"; (* will be BufferIn *)
3199 Pathname "path"]), 143, [Optional "linuxxattrs"],
3201 "set extended attribute of a file or directory",
3203 This call sets the extended attribute named C<xattr>
3204 of the file C<path> to the value C<val> (of length C<vallen>).
3205 The value is arbitrary 8 bit data.
3207 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3209 ("lsetxattr", (RErr, [String "xattr";
3210 String "val"; Int "vallen"; (* will be BufferIn *)
3211 Pathname "path"]), 144, [Optional "linuxxattrs"],
3213 "set extended attribute of a file or directory",
3215 This is the same as C<guestfs_setxattr>, but if C<path>
3216 is a symbolic link, then it sets an extended attribute
3217 of the link itself.");
3219 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3221 "remove extended attribute of a file or directory",
3223 This call removes the extended attribute named C<xattr>
3224 of the file C<path>.
3226 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3228 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3230 "remove extended attribute of a file or directory",
3232 This is the same as C<guestfs_removexattr>, but if C<path>
3233 is a symbolic link, then it removes an extended attribute
3234 of the link itself.");
3236 ("mountpoints", (RHashtable "mps", []), 147, [],
3240 This call is similar to C<guestfs_mounts>. That call returns
3241 a list of devices. This one returns a hash table (map) of
3242 device name to directory where the device is mounted.");
3244 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3245 (* This is a special case: while you would expect a parameter
3246 * of type "Pathname", that doesn't work, because it implies
3247 * NEED_ROOT in the generated calling code in stubs.c, and
3248 * this function cannot use NEED_ROOT.
3251 "create a mountpoint",
3253 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3254 specialized calls that can be used to create extra mountpoints
3255 before mounting the first filesystem.
3257 These calls are I<only> necessary in some very limited circumstances,
3258 mainly the case where you want to mount a mix of unrelated and/or
3259 read-only filesystems together.
3261 For example, live CDs often contain a \"Russian doll\" nest of
3262 filesystems, an ISO outer layer, with a squashfs image inside, with
3263 an ext2/3 image inside that. You can unpack this as follows
3266 add-ro Fedora-11-i686-Live.iso
3269 mkmountpoint /squash
3272 mount-loop /cd/LiveOS/squashfs.img /squash
3273 mount-loop /squash/LiveOS/ext3fs.img /ext3
3275 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3277 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3279 "remove a mountpoint",
3281 This calls removes a mountpoint that was previously created
3282 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3283 for full details.");
3285 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3286 [InitISOFS, Always, TestOutputBuffer (
3287 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3290 This calls returns the contents of the file C<path> as a
3293 Unlike C<guestfs_cat>, this function can correctly
3294 handle files that contain embedded ASCII NUL characters.
3295 However unlike C<guestfs_download>, this function is limited
3296 in the total size of file that can be handled.");
3298 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3299 [InitISOFS, Always, TestOutputList (
3300 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3301 InitISOFS, Always, TestOutputList (
3302 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3303 (* Test for RHBZ#579608, absolute symbolic links. *)
3304 InitISOFS, Always, TestOutputList (
3305 [["grep"; "nomatch"; "/abssymlink"]], [])],
3306 "return lines matching a pattern",
3308 This calls the external C<grep> program and returns the
3311 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3312 [InitISOFS, Always, TestOutputList (
3313 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3314 "return lines matching a pattern",
3316 This calls the external C<egrep> program and returns the
3319 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3320 [InitISOFS, Always, TestOutputList (
3321 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3322 "return lines matching a pattern",
3324 This calls the external C<fgrep> program and returns the
3327 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3328 [InitISOFS, Always, TestOutputList (
3329 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3330 "return lines matching a pattern",
3332 This calls the external C<grep -i> program and returns the
3335 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3336 [InitISOFS, Always, TestOutputList (
3337 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3338 "return lines matching a pattern",
3340 This calls the external C<egrep -i> program and returns the
3343 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3344 [InitISOFS, Always, TestOutputList (
3345 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3346 "return lines matching a pattern",
3348 This calls the external C<fgrep -i> program and returns the
3351 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3352 [InitISOFS, Always, TestOutputList (
3353 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3354 "return lines matching a pattern",
3356 This calls the external C<zgrep> program and returns the
3359 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3360 [InitISOFS, Always, TestOutputList (
3361 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3362 "return lines matching a pattern",
3364 This calls the external C<zegrep> program and returns the
3367 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3368 [InitISOFS, Always, TestOutputList (
3369 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3370 "return lines matching a pattern",
3372 This calls the external C<zfgrep> program and returns the
3375 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3376 [InitISOFS, Always, TestOutputList (
3377 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3378 "return lines matching a pattern",
3380 This calls the external C<zgrep -i> program and returns the
3383 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3384 [InitISOFS, Always, TestOutputList (
3385 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3386 "return lines matching a pattern",
3388 This calls the external C<zegrep -i> program and returns the
3391 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3392 [InitISOFS, Always, TestOutputList (
3393 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3394 "return lines matching a pattern",
3396 This calls the external C<zfgrep -i> program and returns the
3399 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3400 [InitISOFS, Always, TestOutput (
3401 [["realpath"; "/../directory"]], "/directory")],
3402 "canonicalized absolute pathname",
3404 Return the canonicalized absolute pathname of C<path>. The
3405 returned path has no C<.>, C<..> or symbolic link path elements.");
3407 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3408 [InitBasicFS, Always, TestOutputStruct (
3411 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3412 "create a hard link",
3414 This command creates a hard link using the C<ln> command.");
3416 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3417 [InitBasicFS, Always, TestOutputStruct (
3420 ["ln_f"; "/a"; "/b"];
3421 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3422 "create a hard link",
3424 This command creates a hard link using the C<ln -f> command.
3425 The C<-f> option removes the link (C<linkname>) if it exists already.");
3427 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3428 [InitBasicFS, Always, TestOutputStruct (
3430 ["ln_s"; "a"; "/b"];
3431 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3432 "create a symbolic link",
3434 This command creates a symbolic link using the C<ln -s> command.");
3436 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3437 [InitBasicFS, Always, TestOutput (
3438 [["mkdir_p"; "/a/b"];
3439 ["touch"; "/a/b/c"];
3440 ["ln_sf"; "../d"; "/a/b/c"];
3441 ["readlink"; "/a/b/c"]], "../d")],
3442 "create a symbolic link",
3444 This command creates a symbolic link using the C<ln -sf> command,
3445 The C<-f> option removes the link (C<linkname>) if it exists already.");
3447 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3448 [] (* XXX tested above *),
3449 "read the target of a symbolic link",
3451 This command reads the target of a symbolic link.");
3453 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3454 [InitBasicFS, Always, TestOutputStruct (
3455 [["fallocate"; "/a"; "1000000"];
3456 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3457 "preallocate a file in the guest filesystem",
3459 This command preallocates a file (containing zero bytes) named
3460 C<path> of size C<len> bytes. If the file exists already, it
3463 Do not confuse this with the guestfish-specific
3464 C<alloc> command which allocates a file in the host and
3465 attaches it as a device.");
3467 ("swapon_device", (RErr, [Device "device"]), 170, [],
3468 [InitPartition, Always, TestRun (
3469 [["mkswap"; "/dev/sda1"];
3470 ["swapon_device"; "/dev/sda1"];
3471 ["swapoff_device"; "/dev/sda1"]])],
3472 "enable swap on device",
3474 This command enables the libguestfs appliance to use the
3475 swap device or partition named C<device>. The increased
3476 memory is made available for all commands, for example
3477 those run using C<guestfs_command> or C<guestfs_sh>.
3479 Note that you should not swap to existing guest swap
3480 partitions unless you know what you are doing. They may
3481 contain hibernation information, or other information that
3482 the guest doesn't want you to trash. You also risk leaking
3483 information about the host to the guest this way. Instead,
3484 attach a new host device to the guest and swap on that.");
3486 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3487 [], (* XXX tested by swapon_device *)
3488 "disable swap on device",
3490 This command disables the libguestfs appliance swap
3491 device or partition named C<device>.
3492 See C<guestfs_swapon_device>.");
3494 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3495 [InitBasicFS, Always, TestRun (
3496 [["fallocate"; "/swap"; "8388608"];
3497 ["mkswap_file"; "/swap"];
3498 ["swapon_file"; "/swap"];
3499 ["swapoff_file"; "/swap"]])],
3500 "enable swap on file",
3502 This command enables swap to a file.
3503 See C<guestfs_swapon_device> for other notes.");
3505 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3506 [], (* XXX tested by swapon_file *)
3507 "disable swap on file",
3509 This command disables the libguestfs appliance swap on file.");
3511 ("swapon_label", (RErr, [String "label"]), 174, [],
3512 [InitEmpty, Always, TestRun (
3513 [["part_disk"; "/dev/sdb"; "mbr"];
3514 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3515 ["swapon_label"; "swapit"];
3516 ["swapoff_label"; "swapit"];
3517 ["zero"; "/dev/sdb"];
3518 ["blockdev_rereadpt"; "/dev/sdb"]])],
3519 "enable swap on labeled swap partition",
3521 This command enables swap to a labeled swap partition.
3522 See C<guestfs_swapon_device> for other notes.");
3524 ("swapoff_label", (RErr, [String "label"]), 175, [],
3525 [], (* XXX tested by swapon_label *)
3526 "disable swap on labeled swap partition",
3528 This command disables the libguestfs appliance swap on
3529 labeled swap partition.");
3531 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3532 (let uuid = uuidgen () in
3533 [InitEmpty, Always, TestRun (
3534 [["mkswap_U"; uuid; "/dev/sdb"];
3535 ["swapon_uuid"; uuid];
3536 ["swapoff_uuid"; uuid]])]),
3537 "enable swap on swap partition by UUID",
3539 This command enables swap to a swap partition with the given UUID.
3540 See C<guestfs_swapon_device> for other notes.");
3542 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3543 [], (* XXX tested by swapon_uuid *)
3544 "disable swap on swap partition by UUID",
3546 This command disables the libguestfs appliance swap partition
3547 with the given UUID.");
3549 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3550 [InitBasicFS, Always, TestRun (
3551 [["fallocate"; "/swap"; "8388608"];
3552 ["mkswap_file"; "/swap"]])],
3553 "create a swap file",
3557 This command just writes a swap file signature to an existing
3558 file. To create the file itself, use something like C<guestfs_fallocate>.");
3560 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3561 [InitISOFS, Always, TestRun (
3562 [["inotify_init"; "0"]])],
3563 "create an inotify handle",
3565 This command creates a new inotify handle.
3566 The inotify subsystem can be used to notify events which happen to
3567 objects in the guest filesystem.
3569 C<maxevents> is the maximum number of events which will be
3570 queued up between calls to C<guestfs_inotify_read> or
3571 C<guestfs_inotify_files>.
3572 If this is passed as C<0>, then the kernel (or previously set)
3573 default is used. For Linux 2.6.29 the default was 16384 events.
3574 Beyond this limit, the kernel throws away events, but records
3575 the fact that it threw them away by setting a flag
3576 C<IN_Q_OVERFLOW> in the returned structure list (see
3577 C<guestfs_inotify_read>).
3579 Before any events are generated, you have to add some
3580 watches to the internal watch list. See:
3581 C<guestfs_inotify_add_watch>,
3582 C<guestfs_inotify_rm_watch> and
3583 C<guestfs_inotify_watch_all>.
3585 Queued up events should be read periodically by calling
3586 C<guestfs_inotify_read>
3587 (or C<guestfs_inotify_files> which is just a helpful
3588 wrapper around C<guestfs_inotify_read>). If you don't
3589 read the events out often enough then you risk the internal
3592 The handle should be closed after use by calling
3593 C<guestfs_inotify_close>. This also removes any
3594 watches automatically.
3596 See also L<inotify(7)> for an overview of the inotify interface
3597 as exposed by the Linux kernel, which is roughly what we expose
3598 via libguestfs. Note that there is one global inotify handle
3599 per libguestfs instance.");
3601 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3602 [InitBasicFS, Always, TestOutputList (
3603 [["inotify_init"; "0"];
3604 ["inotify_add_watch"; "/"; "1073741823"];
3607 ["inotify_files"]], ["a"; "b"])],
3608 "add an inotify watch",
3610 Watch C<path> for the events listed in C<mask>.
3612 Note that if C<path> is a directory then events within that
3613 directory are watched, but this does I<not> happen recursively
3614 (in subdirectories).
3616 Note for non-C or non-Linux callers: the inotify events are
3617 defined by the Linux kernel ABI and are listed in
3618 C</usr/include/sys/inotify.h>.");
3620 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3622 "remove an inotify watch",
3624 Remove a previously defined inotify watch.
3625 See C<guestfs_inotify_add_watch>.");
3627 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3629 "return list of inotify events",
3631 Return the complete queue of events that have happened
3632 since the previous read call.
3634 If no events have happened, this returns an empty list.
3636 I<Note>: In order to make sure that all events have been
3637 read, you must call this function repeatedly until it
3638 returns an empty list. The reason is that the call will
3639 read events up to the maximum appliance-to-host message
3640 size and leave remaining events in the queue.");
3642 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3644 "return list of watched files that had events",
3646 This function is a helpful wrapper around C<guestfs_inotify_read>
3647 which just returns a list of pathnames of objects that were
3648 touched. The returned pathnames are sorted and deduplicated.");
3650 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3652 "close the inotify handle",
3654 This closes the inotify handle which was previously
3655 opened by inotify_init. It removes all watches, throws
3656 away any pending events, and deallocates all resources.");
3658 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3660 "set SELinux security context",
3662 This sets the SELinux security context of the daemon
3663 to the string C<context>.
3665 See the documentation about SELINUX in L<guestfs(3)>.");
3667 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3669 "get SELinux security context",
3671 This gets the SELinux security context of the daemon.
3673 See the documentation about SELINUX in L<guestfs(3)>,
3674 and C<guestfs_setcon>");
3676 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3677 [InitEmpty, Always, TestOutput (
3678 [["part_disk"; "/dev/sda"; "mbr"];
3679 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3680 ["mount_options"; ""; "/dev/sda1"; "/"];
3681 ["write_file"; "/new"; "new file contents"; "0"];
3682 ["cat"; "/new"]], "new file contents")],
3683 "make a filesystem with block size",
3685 This call is similar to C<guestfs_mkfs>, but it allows you to
3686 control the block size of the resulting filesystem. Supported
3687 block sizes depend on the filesystem type, but typically they
3688 are C<1024>, C<2048> or C<4096> only.");
3690 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3691 [InitEmpty, Always, TestOutput (
3692 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3693 ["mke2journal"; "4096"; "/dev/sda1"];
3694 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3695 ["mount_options"; ""; "/dev/sda2"; "/"];
3696 ["write_file"; "/new"; "new file contents"; "0"];
3697 ["cat"; "/new"]], "new file contents")],
3698 "make ext2/3/4 external journal",
3700 This creates an ext2 external journal on C<device>. It is equivalent
3703 mke2fs -O journal_dev -b blocksize device");
3705 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3706 [InitEmpty, Always, TestOutput (
3707 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3708 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3709 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3710 ["mount_options"; ""; "/dev/sda2"; "/"];
3711 ["write_file"; "/new"; "new file contents"; "0"];
3712 ["cat"; "/new"]], "new file contents")],
3713 "make ext2/3/4 external journal with label",
3715 This creates an ext2 external journal on C<device> with label C<label>.");
3717 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3718 (let uuid = uuidgen () in
3719 [InitEmpty, Always, TestOutput (
3720 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3721 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3722 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3723 ["mount_options"; ""; "/dev/sda2"; "/"];
3724 ["write_file"; "/new"; "new file contents"; "0"];
3725 ["cat"; "/new"]], "new file contents")]),
3726 "make ext2/3/4 external journal with UUID",
3728 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3730 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3732 "make ext2/3/4 filesystem with external journal",
3734 This creates an ext2/3/4 filesystem on C<device> with
3735 an external journal on C<journal>. It is equivalent
3738 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3740 See also C<guestfs_mke2journal>.");
3742 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3744 "make ext2/3/4 filesystem with external journal",
3746 This creates an ext2/3/4 filesystem on C<device> with
3747 an external journal on the journal labeled C<label>.
3749 See also C<guestfs_mke2journal_L>.");
3751 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3753 "make ext2/3/4 filesystem with external journal",
3755 This creates an ext2/3/4 filesystem on C<device> with
3756 an external journal on the journal with UUID C<uuid>.
3758 See also C<guestfs_mke2journal_U>.");
3760 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3761 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3762 "load a kernel module",
3764 This loads a kernel module in the appliance.
3766 The kernel module must have been whitelisted when libguestfs
3767 was built (see C<appliance/kmod.whitelist.in> in the source).");
3769 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3770 [InitNone, Always, TestOutput (
3771 [["echo_daemon"; "This is a test"]], "This is a test"
3773 "echo arguments back to the client",
3775 This command concatenate the list of C<words> passed with single spaces between
3776 them and returns the resulting string.
3778 You can use this command to test the connection through to the daemon.
3780 See also C<guestfs_ping_daemon>.");
3782 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3783 [], (* There is a regression test for this. *)
3784 "find all files and directories, returning NUL-separated list",
3786 This command lists out all files and directories, recursively,
3787 starting at C<directory>, placing the resulting list in the
3788 external file called C<files>.
3790 This command works the same way as C<guestfs_find> with the
3791 following exceptions:
3797 The resulting list is written to an external file.
3801 Items (filenames) in the result are separated
3802 by C<\\0> characters. See L<find(1)> option I<-print0>.
3806 This command is not limited in the number of names that it
3811 The result list is not sorted.
3815 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3816 [InitISOFS, Always, TestOutput (
3817 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3818 InitISOFS, Always, TestOutput (
3819 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3820 InitISOFS, Always, TestOutput (
3821 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3822 InitISOFS, Always, TestLastFail (
3823 [["case_sensitive_path"; "/Known-1/"]]);
3824 InitBasicFS, Always, TestOutput (
3826 ["mkdir"; "/a/bbb"];
3827 ["touch"; "/a/bbb/c"];
3828 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3829 InitBasicFS, Always, TestOutput (
3831 ["mkdir"; "/a/bbb"];
3832 ["touch"; "/a/bbb/c"];
3833 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3834 InitBasicFS, Always, TestLastFail (
3836 ["mkdir"; "/a/bbb"];
3837 ["touch"; "/a/bbb/c"];
3838 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3839 "return true path on case-insensitive filesystem",
3841 This can be used to resolve case insensitive paths on
3842 a filesystem which is case sensitive. The use case is
3843 to resolve paths which you have read from Windows configuration
3844 files or the Windows Registry, to the true path.
3846 The command handles a peculiarity of the Linux ntfs-3g
3847 filesystem driver (and probably others), which is that although
3848 the underlying filesystem is case-insensitive, the driver
3849 exports the filesystem to Linux as case-sensitive.
3851 One consequence of this is that special directories such
3852 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3853 (or other things) depending on the precise details of how
3854 they were created. In Windows itself this would not be
3857 Bug or feature? You decide:
3858 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3860 This function resolves the true case of each element in the
3861 path and returns the case-sensitive path.
3863 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3864 might return C<\"/WINDOWS/system32\"> (the exact return value
3865 would depend on details of how the directories were originally
3866 created under Windows).
3869 This function does not handle drive names, backslashes etc.
3871 See also C<guestfs_realpath>.");
3873 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3874 [InitBasicFS, Always, TestOutput (
3875 [["vfs_type"; "/dev/sda1"]], "ext2")],
3876 "get the Linux VFS type corresponding to a mounted device",
3878 This command gets the block device type corresponding to
3879 a mounted device called C<device>.
3881 Usually the result is the name of the Linux VFS module that
3882 is used to mount this device (probably determined automatically
3883 if you used the C<guestfs_mount> call).");
3885 ("truncate", (RErr, [Pathname "path"]), 199, [],
3886 [InitBasicFS, Always, TestOutputStruct (
3887 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3888 ["truncate"; "/test"];
3889 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3890 "truncate a file to zero size",
3892 This command truncates C<path> to a zero-length file. The
3893 file must exist already.");
3895 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3896 [InitBasicFS, Always, TestOutputStruct (
3897 [["touch"; "/test"];
3898 ["truncate_size"; "/test"; "1000"];
3899 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3900 "truncate a file to a particular size",
3902 This command truncates C<path> to size C<size> bytes. The file
3903 must exist already. If the file is smaller than C<size> then
3904 the file is extended to the required size with null bytes.");
3906 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3907 [InitBasicFS, Always, TestOutputStruct (
3908 [["touch"; "/test"];
3909 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3910 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3911 "set timestamp of a file with nanosecond precision",
3913 This command sets the timestamps of a file with nanosecond
3916 C<atsecs, atnsecs> are the last access time (atime) in secs and
3917 nanoseconds from the epoch.
3919 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3920 secs and nanoseconds from the epoch.
3922 If the C<*nsecs> field contains the special value C<-1> then
3923 the corresponding timestamp is set to the current time. (The
3924 C<*secs> field is ignored in this case).
3926 If the C<*nsecs> field contains the special value C<-2> then
3927 the corresponding timestamp is left unchanged. (The
3928 C<*secs> field is ignored in this case).");
3930 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3931 [InitBasicFS, Always, TestOutputStruct (
3932 [["mkdir_mode"; "/test"; "0o111"];
3933 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3934 "create a directory with a particular mode",
3936 This command creates a directory, setting the initial permissions
3937 of the directory to C<mode>.
3939 For common Linux filesystems, the actual mode which is set will
3940 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3941 interpret the mode in other ways.
3943 See also C<guestfs_mkdir>, C<guestfs_umask>");
3945 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3947 "change file owner and group",
3949 Change the file owner to C<owner> and group to C<group>.
3950 This is like C<guestfs_chown> but if C<path> is a symlink then
3951 the link itself is changed, not the target.
3953 Only numeric uid and gid are supported. If you want to use
3954 names, you will need to locate and parse the password file
3955 yourself (Augeas support makes this relatively easy).");
3957 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3959 "lstat on multiple files",
3961 This call allows you to perform the C<guestfs_lstat> operation
3962 on multiple files, where all files are in the directory C<path>.
3963 C<names> is the list of files from this directory.
3965 On return you get a list of stat structs, with a one-to-one
3966 correspondence to the C<names> list. If any name did not exist
3967 or could not be lstat'd, then the C<ino> field of that structure
3970 This call is intended for programs that want to efficiently
3971 list a directory contents without making many round-trips.
3972 See also C<guestfs_lxattrlist> for a similarly efficient call
3973 for getting extended attributes. Very long directory listings
3974 might cause the protocol message size to be exceeded, causing
3975 this call to fail. The caller must split up such requests
3976 into smaller groups of names.");
3978 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3980 "lgetxattr on multiple files",
3982 This call allows you to get the extended attributes
3983 of multiple files, where all files are in the directory C<path>.
3984 C<names> is the list of files from this directory.
3986 On return you get a flat list of xattr structs which must be
3987 interpreted sequentially. The first xattr struct always has a zero-length
3988 C<attrname>. C<attrval> in this struct is zero-length
3989 to indicate there was an error doing C<lgetxattr> for this
3990 file, I<or> is a C string which is a decimal number
3991 (the number of following attributes for this file, which could
3992 be C<\"0\">). Then after the first xattr struct are the
3993 zero or more attributes for the first named file.
3994 This repeats for the second and subsequent files.
3996 This call is intended for programs that want to efficiently
3997 list a directory contents without making many round-trips.
3998 See also C<guestfs_lstatlist> for a similarly efficient call
3999 for getting standard stats. Very long directory listings
4000 might cause the protocol message size to be exceeded, causing
4001 this call to fail. The caller must split up such requests
4002 into smaller groups of names.");
4004 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4006 "readlink on multiple files",
4008 This call allows you to do a C<readlink> operation
4009 on multiple files, where all files are in the directory C<path>.
4010 C<names> is the list of files from this directory.
4012 On return you get a list of strings, with a one-to-one
4013 correspondence to the C<names> list. Each string is the
4014 value of the symbol link.
4016 If the C<readlink(2)> operation fails on any name, then
4017 the corresponding result string is the empty string C<\"\">.
4018 However the whole operation is completed even if there
4019 were C<readlink(2)> errors, and so you can call this
4020 function with names where you don't know if they are
4021 symbolic links already (albeit slightly less efficient).
4023 This call is intended for programs that want to efficiently
4024 list a directory contents without making many round-trips.
4025 Very long directory listings might cause the protocol
4026 message size to be exceeded, causing
4027 this call to fail. The caller must split up such requests
4028 into smaller groups of names.");
4030 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4031 [InitISOFS, Always, TestOutputBuffer (
4032 [["pread"; "/known-4"; "1"; "3"]], "\n");
4033 InitISOFS, Always, TestOutputBuffer (
4034 [["pread"; "/empty"; "0"; "100"]], "")],
4035 "read part of a file",
4037 This command lets you read part of a file. It reads C<count>
4038 bytes of the file, starting at C<offset>, from file C<path>.
4040 This may read fewer bytes than requested. For further details
4041 see the L<pread(2)> system call.");
4043 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4044 [InitEmpty, Always, TestRun (
4045 [["part_init"; "/dev/sda"; "gpt"]])],
4046 "create an empty partition table",
4048 This creates an empty partition table on C<device> of one of the
4049 partition types listed below. Usually C<parttype> should be
4050 either C<msdos> or C<gpt> (for large disks).
4052 Initially there are no partitions. Following this, you should
4053 call C<guestfs_part_add> for each partition required.
4055 Possible values for C<parttype> are:
4059 =item B<efi> | B<gpt>
4061 Intel EFI / GPT partition table.
4063 This is recommended for >= 2 TB partitions that will be accessed
4064 from Linux and Intel-based Mac OS X. It also has limited backwards
4065 compatibility with the C<mbr> format.
4067 =item B<mbr> | B<msdos>
4069 The standard PC \"Master Boot Record\" (MBR) format used
4070 by MS-DOS and Windows. This partition type will B<only> work
4071 for device sizes up to 2 TB. For large disks we recommend
4076 Other partition table types that may work but are not
4085 =item B<amiga> | B<rdb>
4087 Amiga \"Rigid Disk Block\" format.
4095 DASD, used on IBM mainframes.
4103 Old Mac partition format. Modern Macs use C<gpt>.
4107 NEC PC-98 format, common in Japan apparently.
4115 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4116 [InitEmpty, Always, TestRun (
4117 [["part_init"; "/dev/sda"; "mbr"];
4118 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4119 InitEmpty, Always, TestRun (
4120 [["part_init"; "/dev/sda"; "gpt"];
4121 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4122 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4123 InitEmpty, Always, TestRun (
4124 [["part_init"; "/dev/sda"; "mbr"];
4125 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4126 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4127 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4128 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4129 "add a partition to the device",
4131 This command adds a partition to C<device>. If there is no partition
4132 table on the device, call C<guestfs_part_init> first.
4134 The C<prlogex> parameter is the type of partition. Normally you
4135 should pass C<p> or C<primary> here, but MBR partition tables also
4136 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4139 C<startsect> and C<endsect> are the start and end of the partition
4140 in I<sectors>. C<endsect> may be negative, which means it counts
4141 backwards from the end of the disk (C<-1> is the last sector).
4143 Creating a partition which covers the whole disk is not so easy.
4144 Use C<guestfs_part_disk> to do that.");
4146 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4147 [InitEmpty, Always, TestRun (
4148 [["part_disk"; "/dev/sda"; "mbr"]]);
4149 InitEmpty, Always, TestRun (
4150 [["part_disk"; "/dev/sda"; "gpt"]])],
4151 "partition whole disk with a single primary partition",
4153 This command is simply a combination of C<guestfs_part_init>
4154 followed by C<guestfs_part_add> to create a single primary partition
4155 covering the whole disk.
4157 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4158 but other possible values are described in C<guestfs_part_init>.");
4160 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4161 [InitEmpty, Always, TestRun (
4162 [["part_disk"; "/dev/sda"; "mbr"];
4163 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4164 "make a partition bootable",
4166 This sets the bootable flag on partition numbered C<partnum> on
4167 device C<device>. Note that partitions are numbered from 1.
4169 The bootable flag is used by some operating systems (notably
4170 Windows) to determine which partition to boot from. It is by
4171 no means universally recognized.");
4173 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4174 [InitEmpty, Always, TestRun (
4175 [["part_disk"; "/dev/sda"; "gpt"];
4176 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4177 "set partition name",
4179 This sets the partition name on partition numbered C<partnum> on
4180 device C<device>. Note that partitions are numbered from 1.
4182 The partition name can only be set on certain types of partition
4183 table. This works on C<gpt> but not on C<mbr> partitions.");
4185 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4186 [], (* XXX Add a regression test for this. *)
4187 "list partitions on a device",
4189 This command parses the partition table on C<device> and
4190 returns the list of partitions found.
4192 The fields in the returned structure are:
4198 Partition number, counting from 1.
4202 Start of the partition I<in bytes>. To get sectors you have to
4203 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4207 End of the partition in bytes.
4211 Size of the partition in bytes.
4215 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4216 [InitEmpty, Always, TestOutput (
4217 [["part_disk"; "/dev/sda"; "gpt"];
4218 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4219 "get the partition table type",
4221 This command examines the partition table on C<device> and
4222 returns the partition table type (format) being used.
4224 Common return values include: C<msdos> (a DOS/Windows style MBR
4225 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4226 values are possible, although unusual. See C<guestfs_part_init>
4229 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4230 [InitBasicFS, Always, TestOutputBuffer (
4231 [["fill"; "0x63"; "10"; "/test"];
4232 ["read_file"; "/test"]], "cccccccccc")],
4233 "fill a file with octets",
4235 This command creates a new file called C<path>. The initial
4236 content of the file is C<len> octets of C<c>, where C<c>
4237 must be a number in the range C<[0..255]>.
4239 To fill a file with zero bytes (sparsely), it is
4240 much more efficient to use C<guestfs_truncate_size>.");
4242 ("available", (RErr, [StringList "groups"]), 216, [],
4243 [InitNone, Always, TestRun [["available"; ""]]],
4244 "test availability of some parts of the API",
4246 This command is used to check the availability of some
4247 groups of functionality in the appliance, which not all builds of
4248 the libguestfs appliance will be able to provide.
4250 The libguestfs groups, and the functions that those
4251 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4253 The argument C<groups> is a list of group names, eg:
4254 C<[\"inotify\", \"augeas\"]> would check for the availability of
4255 the Linux inotify functions and Augeas (configuration file
4258 The command returns no error if I<all> requested groups are available.
4260 It fails with an error if one or more of the requested
4261 groups is unavailable in the appliance.
4263 If an unknown group name is included in the
4264 list of groups then an error is always returned.
4272 You must call C<guestfs_launch> before calling this function.
4274 The reason is because we don't know what groups are
4275 supported by the appliance/daemon until it is running and can
4280 If a group of functions is available, this does not necessarily
4281 mean that they will work. You still have to check for errors
4282 when calling individual API functions even if they are
4287 It is usually the job of distro packagers to build
4288 complete functionality into the libguestfs appliance.
4289 Upstream libguestfs, if built from source with all
4290 requirements satisfied, will support everything.
4294 This call was added in version C<1.0.80>. In previous
4295 versions of libguestfs all you could do would be to speculatively
4296 execute a command to find out if the daemon implemented it.
4297 See also C<guestfs_version>.
4301 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4302 [InitBasicFS, Always, TestOutputBuffer (
4303 [["write_file"; "/src"; "hello, world"; "0"];
4304 ["dd"; "/src"; "/dest"];
4305 ["read_file"; "/dest"]], "hello, world")],
4306 "copy from source to destination using dd",
4308 This command copies from one source device or file C<src>
4309 to another destination device or file C<dest>. Normally you
4310 would use this to copy to or from a device or partition, for
4311 example to duplicate a filesystem.
4313 If the destination is a device, it must be as large or larger
4314 than the source file or device, otherwise the copy will fail.
4315 This command cannot do partial copies (see C<guestfs_copy_size>).");
4317 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4318 [InitBasicFS, Always, TestOutputInt (
4319 [["write_file"; "/file"; "hello, world"; "0"];
4320 ["filesize"; "/file"]], 12)],
4321 "return the size of the file in bytes",
4323 This command returns the size of C<file> in bytes.
4325 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4326 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4327 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4329 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4330 [InitBasicFSonLVM, Always, TestOutputList (
4331 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4332 ["lvs"]], ["/dev/VG/LV2"])],
4333 "rename an LVM logical volume",
4335 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4337 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4338 [InitBasicFSonLVM, Always, TestOutputList (
4340 ["vg_activate"; "false"; "VG"];
4341 ["vgrename"; "VG"; "VG2"];
4342 ["vg_activate"; "true"; "VG2"];
4343 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4344 ["vgs"]], ["VG2"])],
4345 "rename an LVM volume group",
4347 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4349 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4350 [InitISOFS, Always, TestOutputBuffer (
4351 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4352 "list the contents of a single file in an initrd",
4354 This command unpacks the file C<filename> from the initrd file
4355 called C<initrdpath>. The filename must be given I<without> the
4356 initial C</> character.
4358 For example, in guestfish you could use the following command
4359 to examine the boot script (usually called C</init>)
4360 contained in a Linux initrd or initramfs image:
4362 initrd-cat /boot/initrd-<version>.img init
4364 See also C<guestfs_initrd_list>.");
4366 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4368 "get the UUID of a physical volume",
4370 This command returns the UUID of the LVM PV C<device>.");
4372 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4374 "get the UUID of a volume group",
4376 This command returns the UUID of the LVM VG named C<vgname>.");
4378 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4380 "get the UUID of a logical volume",
4382 This command returns the UUID of the LVM LV C<device>.");
4384 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4386 "get the PV UUIDs containing the volume group",
4388 Given a VG called C<vgname>, this returns the UUIDs of all
4389 the physical volumes that this volume group resides on.
4391 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4392 calls to associate physical volumes and volume groups.
4394 See also C<guestfs_vglvuuids>.");
4396 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4398 "get the LV UUIDs of all LVs in the volume group",
4400 Given a VG called C<vgname>, this returns the UUIDs of all
4401 the logical volumes created in this volume group.
4403 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4404 calls to associate logical volumes and volume groups.
4406 See also C<guestfs_vgpvuuids>.");
4408 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4409 [InitBasicFS, Always, TestOutputBuffer (
4410 [["write_file"; "/src"; "hello, world"; "0"];
4411 ["copy_size"; "/src"; "/dest"; "5"];
4412 ["read_file"; "/dest"]], "hello")],
4413 "copy size bytes from source to destination using dd",
4415 This command copies exactly C<size> bytes from one source device
4416 or file C<src> to another destination device or file C<dest>.
4418 Note this will fail if the source is too short or if the destination
4419 is not large enough.");
4421 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4422 [InitBasicFSonLVM, Always, TestRun (
4423 [["zero_device"; "/dev/VG/LV"]])],
4424 "write zeroes to an entire device",
4426 This command writes zeroes over the entire C<device>. Compare
4427 with C<guestfs_zero> which just zeroes the first few blocks of
4430 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4431 [InitBasicFS, Always, TestOutput (
4432 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4433 ["cat"; "/hello"]], "hello\n")],
4434 "unpack compressed tarball to directory",
4436 This command uploads and unpacks local file C<tarball> (an
4437 I<xz compressed> tar file) into C<directory>.");
4439 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4441 "pack directory into compressed tarball",
4443 This command packs the contents of C<directory> and downloads
4444 it to local file C<tarball> (as an xz compressed tar archive).");
4446 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4448 "resize an NTFS filesystem",
4450 This command resizes an NTFS filesystem, expanding or
4451 shrinking it to the size of the underlying device.
4452 See also L<ntfsresize(8)>.");
4454 ("vgscan", (RErr, []), 232, [],
4455 [InitEmpty, Always, TestRun (
4457 "rescan for LVM physical volumes, volume groups and logical volumes",
4459 This rescans all block devices and rebuilds the list of LVM
4460 physical volumes, volume groups and logical volumes.");
4462 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4463 [InitEmpty, Always, TestRun (
4464 [["part_init"; "/dev/sda"; "mbr"];
4465 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4466 ["part_del"; "/dev/sda"; "1"]])],
4467 "delete a partition",
4469 This command deletes the partition numbered C<partnum> on C<device>.
4471 Note that in the case of MBR partitioning, deleting an
4472 extended partition also deletes any logical partitions
4475 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4476 [InitEmpty, Always, TestOutputTrue (
4477 [["part_init"; "/dev/sda"; "mbr"];
4478 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4479 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4480 ["part_get_bootable"; "/dev/sda"; "1"]])],
4481 "return true if a partition is bootable",
4483 This command returns true if the partition C<partnum> on
4484 C<device> has the bootable flag set.
4486 See also C<guestfs_part_set_bootable>.");
4488 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4489 [InitEmpty, Always, TestOutputInt (
4490 [["part_init"; "/dev/sda"; "mbr"];
4491 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4492 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4493 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4494 "get the MBR type byte (ID byte) from a partition",
4496 Returns the MBR type byte (also known as the ID byte) from
4497 the numbered partition C<partnum>.
4499 Note that only MBR (old DOS-style) partitions have type bytes.
4500 You will get undefined results for other partition table
4501 types (see C<guestfs_part_get_parttype>).");
4503 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4504 [], (* tested by part_get_mbr_id *)
4505 "set the MBR type byte (ID byte) of a partition",
4507 Sets the MBR type byte (also known as the ID byte) of
4508 the numbered partition C<partnum> to C<idbyte>. Note
4509 that the type bytes quoted in most documentation are
4510 in fact hexadecimal numbers, but usually documented
4511 without any leading \"0x\" which might be confusing.
4513 Note that only MBR (old DOS-style) partitions have type bytes.
4514 You will get undefined results for other partition table
4515 types (see C<guestfs_part_get_parttype>).");
4517 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4518 [InitISOFS, Always, TestOutput (
4519 [["checksum_device"; "md5"; "/dev/sdd"]],
4520 (Digest.to_hex (Digest.file "images/test.iso")))],
4521 "compute MD5, SHAx or CRC checksum of the contents of a device",
4523 This call computes the MD5, SHAx or CRC checksum of the
4524 contents of the device named C<device>. For the types of
4525 checksums supported see the C<guestfs_checksum> command.");
4527 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4528 [InitNone, Always, TestRun (
4529 [["part_disk"; "/dev/sda"; "mbr"];
4530 ["pvcreate"; "/dev/sda1"];
4531 ["vgcreate"; "VG"; "/dev/sda1"];
4532 ["lvcreate"; "LV"; "VG"; "10"];
4533 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4534 "expand an LV to fill free space",
4536 This expands an existing logical volume C<lv> so that it fills
4537 C<pc>% of the remaining free space in the volume group. Commonly
4538 you would call this with pc = 100 which expands the logical volume
4539 as much as possible, using all remaining free space in the volume
4542 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4543 [], (* XXX Augeas code needs tests. *)
4544 "clear Augeas path",
4546 Set the value associated with C<path> to C<NULL>. This
4547 is the same as the L<augtool(1)> C<clear> command.");
4549 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4550 [InitEmpty, Always, TestOutputInt (
4551 [["get_umask"]], 0o22)],
4552 "get the current umask",
4554 Return the current umask. By default the umask is C<022>
4555 unless it has been set by calling C<guestfs_umask>.");
4557 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4559 "upload a file to the appliance (internal use only)",
4561 The C<guestfs_debug_upload> command uploads a file to
4562 the libguestfs appliance.
4564 There is no comprehensive help for this command. You have
4565 to look at the file C<daemon/debug.c> in the libguestfs source
4566 to find out what it is for.");
4568 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4569 [InitBasicFS, Always, TestOutput (
4570 [["base64_in"; "../images/hello.b64"; "/hello"];
4571 ["cat"; "/hello"]], "hello\n")],
4572 "upload base64-encoded data to file",
4574 This command uploads base64-encoded data from C<base64file>
4577 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4579 "download file and encode as base64",
4581 This command downloads the contents of C<filename>, writing
4582 it out to local file C<base64file> encoded as base64.");
4584 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4586 "compute MD5, SHAx or CRC checksum of files in a directory",
4588 This command computes the checksums of all regular files in
4589 C<directory> and then emits a list of those checksums to
4590 the local output file C<sumsfile>.
4592 This can be used for verifying the integrity of a virtual
4593 machine. However to be properly secure you should pay
4594 attention to the output of the checksum command (it uses
4595 the ones from GNU coreutils). In particular when the
4596 filename is not printable, coreutils uses a special
4597 backslash syntax. For more information, see the GNU
4598 coreutils info file.");
4602 let all_functions = non_daemon_functions @ daemon_functions
4604 (* In some places we want the functions to be displayed sorted
4605 * alphabetically, so this is useful:
4607 let all_functions_sorted =
4608 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4609 compare n1 n2) all_functions
4611 (* Field types for structures. *)
4613 | FChar (* C 'char' (really, a 7 bit byte). *)
4614 | FString (* nul-terminated ASCII string, NOT NULL. *)
4615 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4620 | FBytes (* Any int measure that counts bytes. *)
4621 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4622 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4624 (* Because we generate extra parsing code for LVM command line tools,
4625 * we have to pull out the LVM columns separately here.
4635 "pv_attr", FString (* XXX *);
4636 "pv_pe_count", FInt64;
4637 "pv_pe_alloc_count", FInt64;
4640 "pv_mda_count", FInt64;
4641 "pv_mda_free", FBytes;
4642 (* Not in Fedora 10:
4643 "pv_mda_size", FBytes;
4650 "vg_attr", FString (* XXX *);
4653 "vg_sysid", FString;
4654 "vg_extent_size", FBytes;
4655 "vg_extent_count", FInt64;
4656 "vg_free_count", FInt64;
4661 "snap_count", FInt64;
4664 "vg_mda_count", FInt64;
4665 "vg_mda_free", FBytes;
4666 (* Not in Fedora 10:
4667 "vg_mda_size", FBytes;
4673 "lv_attr", FString (* XXX *);
4676 "lv_kernel_major", FInt64;
4677 "lv_kernel_minor", FInt64;
4679 "seg_count", FInt64;
4681 "snap_percent", FOptPercent;
4682 "copy_percent", FOptPercent;
4685 "mirror_log", FString;
4689 (* Names and fields in all structures (in RStruct and RStructList)
4693 (* The old RIntBool return type, only ever used for aug_defnode. Do
4694 * not use this struct in any new code.
4697 "i", FInt32; (* for historical compatibility *)
4698 "b", FInt32; (* for historical compatibility *)
4701 (* LVM PVs, VGs, LVs. *)
4702 "lvm_pv", lvm_pv_cols;
4703 "lvm_vg", lvm_vg_cols;
4704 "lvm_lv", lvm_lv_cols;
4706 (* Column names and types from stat structures.
4707 * NB. Can't use things like 'st_atime' because glibc header files
4708 * define some of these as macros. Ugh.
4739 (* Column names in dirent structure. *)
4742 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4747 (* Version numbers. *)
4755 (* Extended attribute. *)
4757 "attrname", FString;
4761 (* Inotify events. *)
4765 "in_cookie", FUInt32;
4769 (* Partition table entry. *)
4772 "part_start", FBytes;
4774 "part_size", FBytes;
4776 ] (* end of structs *)
4778 (* Ugh, Java has to be different ..
4779 * These names are also used by the Haskell bindings.
4781 let java_structs = [
4782 "int_bool", "IntBool";
4787 "statvfs", "StatVFS";
4789 "version", "Version";
4791 "inotify_event", "INotifyEvent";
4792 "partition", "Partition";
4795 (* What structs are actually returned. *)
4796 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4798 (* Returns a list of RStruct/RStructList structs that are returned
4799 * by any function. Each element of returned list is a pair:
4801 * (structname, RStructOnly)
4802 * == there exists function which returns RStruct (_, structname)
4803 * (structname, RStructListOnly)
4804 * == there exists function which returns RStructList (_, structname)
4805 * (structname, RStructAndList)
4806 * == there are functions returning both RStruct (_, structname)
4807 * and RStructList (_, structname)
4809 let rstructs_used_by functions =
4810 (* ||| is a "logical OR" for rstructs_used_t *)
4814 | _, RStructAndList -> RStructAndList
4815 | RStructOnly, RStructListOnly
4816 | RStructListOnly, RStructOnly -> RStructAndList
4817 | RStructOnly, RStructOnly -> RStructOnly
4818 | RStructListOnly, RStructListOnly -> RStructListOnly
4821 let h = Hashtbl.create 13 in
4823 (* if elem->oldv exists, update entry using ||| operator,
4824 * else just add elem->newv to the hash
4826 let update elem newv =
4827 try let oldv = Hashtbl.find h elem in
4828 Hashtbl.replace h elem (newv ||| oldv)
4829 with Not_found -> Hashtbl.add h elem newv
4833 fun (_, style, _, _, _, _, _) ->
4834 match fst style with
4835 | RStruct (_, structname) -> update structname RStructOnly
4836 | RStructList (_, structname) -> update structname RStructListOnly
4840 (* return key->values as a list of (key,value) *)
4841 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4843 (* Used for testing language bindings. *)
4845 | CallString of string
4846 | CallOptString of string option
4847 | CallStringList of string list
4849 | CallInt64 of int64
4852 (* Used to memoize the result of pod2text. *)
4853 let pod2text_memo_filename = "src/.pod2text.data"
4854 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4856 let chan = open_in pod2text_memo_filename in
4857 let v = input_value chan in
4861 _ -> Hashtbl.create 13
4862 let pod2text_memo_updated () =
4863 let chan = open_out pod2text_memo_filename in
4864 output_value chan pod2text_memo;
4867 (* Useful functions.
4868 * Note we don't want to use any external OCaml libraries which
4869 * makes this a bit harder than it should be.
4871 module StringMap = Map.Make (String)
4873 let failwithf fs = ksprintf failwith fs
4875 let unique = let i = ref 0 in fun () -> incr i; !i
4877 let replace_char s c1 c2 =
4878 let s2 = String.copy s in
4879 let r = ref false in
4880 for i = 0 to String.length s2 - 1 do
4881 if String.unsafe_get s2 i = c1 then (
4882 String.unsafe_set s2 i c2;
4886 if not !r then s else s2
4890 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4892 let triml ?(test = isspace) str =
4894 let n = ref (String.length str) in
4895 while !n > 0 && test str.[!i]; do
4900 else String.sub str !i !n
4902 let trimr ?(test = isspace) str =
4903 let n = ref (String.length str) in
4904 while !n > 0 && test str.[!n-1]; do
4907 if !n = String.length str then str
4908 else String.sub str 0 !n
4910 let trim ?(test = isspace) str =
4911 trimr ~test (triml ~test str)
4913 let rec find s sub =
4914 let len = String.length s in
4915 let sublen = String.length sub in
4917 if i <= len-sublen then (
4919 if j < sublen then (
4920 if s.[i+j] = sub.[j] then loop2 (j+1)
4926 if r = -1 then loop (i+1) else r
4932 let rec replace_str s s1 s2 =
4933 let len = String.length s in
4934 let sublen = String.length s1 in
4935 let i = find s s1 in
4938 let s' = String.sub s 0 i in
4939 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4940 s' ^ s2 ^ replace_str s'' s1 s2
4943 let rec string_split sep str =
4944 let len = String.length str in
4945 let seplen = String.length sep in
4946 let i = find str sep in
4947 if i = -1 then [str]
4949 let s' = String.sub str 0 i in
4950 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4951 s' :: string_split sep s''
4954 let files_equal n1 n2 =
4955 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4956 match Sys.command cmd with
4959 | i -> failwithf "%s: failed with error code %d" cmd i
4961 let rec filter_map f = function
4965 | Some y -> y :: filter_map f xs
4966 | None -> filter_map f xs
4968 let rec find_map f = function
4969 | [] -> raise Not_found
4973 | None -> find_map f xs
4976 let rec loop i = function
4978 | x :: xs -> f i x; loop (i+1) xs
4983 let rec loop i = function
4985 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4989 let count_chars c str =
4990 let count = ref 0 in
4991 for i = 0 to String.length str - 1 do
4992 if c = String.unsafe_get str i then incr count
4996 let name_of_argt = function
4997 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4998 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4999 | FileIn n | FileOut n -> n
5001 let java_name_of_struct typ =
5002 try List.assoc typ java_structs
5005 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5007 let cols_of_struct typ =
5008 try List.assoc typ structs
5010 failwithf "cols_of_struct: unknown struct %s" typ
5012 let seq_of_test = function
5013 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5014 | TestOutputListOfDevices (s, _)
5015 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5016 | TestOutputTrue s | TestOutputFalse s
5017 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5018 | TestOutputStruct (s, _)
5019 | TestLastFail s -> s
5021 (* Handling for function flags. *)
5022 let protocol_limit_warning =
5023 "Because of the message protocol, there is a transfer limit
5024 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5026 let danger_will_robinson =
5027 "B<This command is dangerous. Without careful use you
5028 can easily destroy all your data>."
5030 let deprecation_notice flags =
5033 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5035 sprintf "This function is deprecated.
5036 In new code, use the C<%s> call instead.
5038 Deprecated functions will not be removed from the API, but the
5039 fact that they are deprecated indicates that there are problems
5040 with correct use of these functions." alt in
5045 (* Create list of optional groups. *)
5047 let h = Hashtbl.create 13 in
5049 fun (name, _, _, flags, _, _, _) ->
5053 let names = try Hashtbl.find h group with Not_found -> [] in
5054 Hashtbl.replace h group (name :: names)
5058 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5061 fun group -> group, List.sort compare (Hashtbl.find h group)
5063 List.sort (fun x y -> compare (fst x) (fst y)) groups
5065 (* Check function names etc. for consistency. *)
5066 let check_functions () =
5067 let contains_uppercase str =
5068 let len = String.length str in
5070 if i >= len then false
5073 if c >= 'A' && c <= 'Z' then true
5080 (* Check function names. *)
5082 fun (name, _, _, _, _, _, _) ->
5083 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5084 failwithf "function name %s does not need 'guestfs' prefix" name;
5086 failwithf "function name is empty";
5087 if name.[0] < 'a' || name.[0] > 'z' then
5088 failwithf "function name %s must start with lowercase a-z" name;
5089 if String.contains name '-' then
5090 failwithf "function name %s should not contain '-', use '_' instead."
5094 (* Check function parameter/return names. *)
5096 fun (name, style, _, _, _, _, _) ->
5097 let check_arg_ret_name n =
5098 if contains_uppercase n then
5099 failwithf "%s param/ret %s should not contain uppercase chars"
5101 if String.contains n '-' || String.contains n '_' then
5102 failwithf "%s param/ret %s should not contain '-' or '_'"
5105 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;
5106 if n = "int" || n = "char" || n = "short" || n = "long" then
5107 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5108 if n = "i" || n = "n" then
5109 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5110 if n = "argv" || n = "args" then
5111 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5113 (* List Haskell, OCaml and C keywords here.
5114 * http://www.haskell.org/haskellwiki/Keywords
5115 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5116 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5117 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5118 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5119 * Omitting _-containing words, since they're handled above.
5120 * Omitting the OCaml reserved word, "val", is ok,
5121 * and saves us from renaming several parameters.
5124 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5125 "char"; "class"; "const"; "constraint"; "continue"; "data";
5126 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5127 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5128 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5129 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5130 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5132 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5133 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5134 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5135 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5136 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5137 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5138 "volatile"; "when"; "where"; "while";
5140 if List.mem n reserved then
5141 failwithf "%s has param/ret using reserved word %s" name n;
5144 (match fst style with
5146 | RInt n | RInt64 n | RBool n
5147 | RConstString n | RConstOptString n | RString n
5148 | RStringList n | RStruct (n, _) | RStructList (n, _)
5149 | RHashtable n | RBufferOut n ->
5150 check_arg_ret_name n
5152 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5155 (* Check short descriptions. *)
5157 fun (name, _, _, _, _, shortdesc, _) ->
5158 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5159 failwithf "short description of %s should begin with lowercase." name;
5160 let c = shortdesc.[String.length shortdesc-1] in
5161 if c = '\n' || c = '.' then
5162 failwithf "short description of %s should not end with . or \\n." name
5165 (* Check long descriptions. *)
5167 fun (name, _, _, _, _, _, longdesc) ->
5168 if longdesc.[String.length longdesc-1] = '\n' then
5169 failwithf "long description of %s should not end with \\n." name
5172 (* Check proc_nrs. *)
5174 fun (name, _, proc_nr, _, _, _, _) ->
5175 if proc_nr <= 0 then
5176 failwithf "daemon function %s should have proc_nr > 0" name
5180 fun (name, _, proc_nr, _, _, _, _) ->
5181 if proc_nr <> -1 then
5182 failwithf "non-daemon function %s should have proc_nr -1" name
5183 ) non_daemon_functions;
5186 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5189 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5190 let rec loop = function
5193 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5195 | (name1,nr1) :: (name2,nr2) :: _ ->
5196 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5204 (* Ignore functions that have no tests. We generate a
5205 * warning when the user does 'make check' instead.
5207 | name, _, _, _, [], _, _ -> ()
5208 | name, _, _, _, tests, _, _ ->
5212 match seq_of_test test with
5214 failwithf "%s has a test containing an empty sequence" name
5215 | cmds -> List.map List.hd cmds
5217 let funcs = List.flatten funcs in
5219 let tested = List.mem name funcs in
5222 failwithf "function %s has tests but does not test itself" name
5225 (* 'pr' prints to the current output file. *)
5226 let chan = ref Pervasives.stdout
5231 let i = count_chars '\n' str in
5232 lines := !lines + i;
5233 output_string !chan str
5236 let copyright_years =
5237 let this_year = 1900 + (localtime (time ())).tm_year in
5238 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5240 (* Generate a header block in a number of standard styles. *)
5241 type comment_style =
5242 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5243 type license = GPLv2plus | LGPLv2plus
5245 let generate_header ?(extra_inputs = []) comment license =
5246 let inputs = "src/generator.ml" :: extra_inputs in
5247 let c = match comment with
5248 | CStyle -> pr "/* "; " *"
5249 | CPlusPlusStyle -> pr "// "; "//"
5250 | HashStyle -> pr "# "; "#"
5251 | OCamlStyle -> pr "(* "; " *"
5252 | HaskellStyle -> pr "{- "; " " in
5253 pr "libguestfs generated file\n";
5254 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5255 List.iter (pr "%s %s\n" c) inputs;
5256 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5258 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5262 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5263 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5264 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5265 pr "%s (at your option) any later version.\n" c;
5267 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5268 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5269 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5270 pr "%s GNU General Public License for more details.\n" c;
5272 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5273 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5274 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5277 pr "%s This library is free software; you can redistribute it and/or\n" c;
5278 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5279 pr "%s License as published by the Free Software Foundation; either\n" c;
5280 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5282 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5283 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5284 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5285 pr "%s Lesser General Public License for more details.\n" c;
5287 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5288 pr "%s License along with this library; if not, write to the Free Software\n" c;
5289 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5292 | CStyle -> pr " */\n"
5295 | OCamlStyle -> pr " *)\n"
5296 | HaskellStyle -> pr "-}\n"
5300 (* Start of main code generation functions below this line. *)
5302 (* Generate the pod documentation for the C API. *)
5303 let rec generate_actions_pod () =
5305 fun (shortname, style, _, flags, _, _, longdesc) ->
5306 if not (List.mem NotInDocs flags) then (
5307 let name = "guestfs_" ^ shortname in
5308 pr "=head2 %s\n\n" name;
5310 generate_prototype ~extern:false ~handle:"g" name style;
5312 pr "%s\n\n" longdesc;
5313 (match fst style with
5315 pr "This function returns 0 on success or -1 on error.\n\n"
5317 pr "On error this function returns -1.\n\n"
5319 pr "On error this function returns -1.\n\n"
5321 pr "This function returns a C truth value on success or -1 on error.\n\n"
5323 pr "This function returns a string, or NULL on error.
5324 The string is owned by the guest handle and must I<not> be freed.\n\n"
5325 | RConstOptString _ ->
5326 pr "This function returns a string which may be NULL.
5327 There is way to return an error from this function.
5328 The string is owned by the guest handle and must I<not> be freed.\n\n"
5330 pr "This function returns a string, or NULL on error.
5331 I<The caller must free the returned string after use>.\n\n"
5333 pr "This function returns a NULL-terminated array of strings
5334 (like L<environ(3)>), or NULL if there was an error.
5335 I<The caller must free the strings and the array after use>.\n\n"
5336 | RStruct (_, typ) ->
5337 pr "This function returns a C<struct guestfs_%s *>,
5338 or NULL if there was an error.
5339 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5340 | RStructList (_, typ) ->
5341 pr "This function returns a C<struct guestfs_%s_list *>
5342 (see E<lt>guestfs-structs.hE<gt>),
5343 or NULL if there was an error.
5344 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5346 pr "This function returns a NULL-terminated array of
5347 strings, or NULL if there was an error.
5348 The array of strings will always have length C<2n+1>, where
5349 C<n> keys and values alternate, followed by the trailing NULL entry.
5350 I<The caller must free the strings and the array after use>.\n\n"
5352 pr "This function returns a buffer, or NULL on error.
5353 The size of the returned buffer is written to C<*size_r>.
5354 I<The caller must free the returned buffer after use>.\n\n"
5356 if List.mem ProtocolLimitWarning flags then
5357 pr "%s\n\n" protocol_limit_warning;
5358 if List.mem DangerWillRobinson flags then
5359 pr "%s\n\n" danger_will_robinson;
5360 match deprecation_notice flags with
5362 | Some txt -> pr "%s\n\n" txt
5364 ) all_functions_sorted
5366 and generate_structs_pod () =
5367 (* Structs documentation. *)
5370 pr "=head2 guestfs_%s\n" typ;
5372 pr " struct guestfs_%s {\n" typ;
5375 | name, FChar -> pr " char %s;\n" name
5376 | name, FUInt32 -> pr " uint32_t %s;\n" name
5377 | name, FInt32 -> pr " int32_t %s;\n" name
5378 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5379 | name, FInt64 -> pr " int64_t %s;\n" name
5380 | name, FString -> pr " char *%s;\n" name
5382 pr " /* The next two fields describe a byte array. */\n";
5383 pr " uint32_t %s_len;\n" name;
5384 pr " char *%s;\n" name
5386 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5387 pr " char %s[32];\n" name
5388 | name, FOptPercent ->
5389 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5390 pr " float %s;\n" name
5394 pr " struct guestfs_%s_list {\n" typ;
5395 pr " uint32_t len; /* Number of elements in list. */\n";
5396 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5399 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5400 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5405 and generate_availability_pod () =
5406 (* Availability documentation. *)
5410 fun (group, functions) ->
5411 pr "=item B<%s>\n" group;
5413 pr "The following functions:\n";
5414 List.iter (pr "L</guestfs_%s>\n") functions;
5420 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5421 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5423 * We have to use an underscore instead of a dash because otherwise
5424 * rpcgen generates incorrect code.
5426 * This header is NOT exported to clients, but see also generate_structs_h.
5428 and generate_xdr () =
5429 generate_header CStyle LGPLv2plus;
5431 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5432 pr "typedef string str<>;\n";
5435 (* Internal structures. *)
5439 pr "struct guestfs_int_%s {\n" typ;
5441 | name, FChar -> pr " char %s;\n" name
5442 | name, FString -> pr " string %s<>;\n" name
5443 | name, FBuffer -> pr " opaque %s<>;\n" name
5444 | name, FUUID -> pr " opaque %s[32];\n" name
5445 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5446 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5447 | name, FOptPercent -> pr " float %s;\n" name
5451 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5456 fun (shortname, style, _, _, _, _, _) ->
5457 let name = "guestfs_" ^ shortname in
5459 (match snd style with
5462 pr "struct %s_args {\n" name;
5465 | Pathname n | Device n | Dev_or_Path n | String n ->
5466 pr " string %s<>;\n" n
5467 | OptString n -> pr " str *%s;\n" n
5468 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5469 | Bool n -> pr " bool %s;\n" n
5470 | Int n -> pr " int %s;\n" n
5471 | Int64 n -> pr " hyper %s;\n" n
5472 | FileIn _ | FileOut _ -> ()
5476 (match fst style with
5479 pr "struct %s_ret {\n" name;
5483 pr "struct %s_ret {\n" name;
5484 pr " hyper %s;\n" n;
5487 pr "struct %s_ret {\n" name;
5490 | RConstString _ | RConstOptString _ ->
5491 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5493 pr "struct %s_ret {\n" name;
5494 pr " string %s<>;\n" n;
5497 pr "struct %s_ret {\n" name;
5498 pr " str %s<>;\n" n;
5500 | RStruct (n, typ) ->
5501 pr "struct %s_ret {\n" name;
5502 pr " guestfs_int_%s %s;\n" typ n;
5504 | RStructList (n, typ) ->
5505 pr "struct %s_ret {\n" name;
5506 pr " guestfs_int_%s_list %s;\n" typ n;
5509 pr "struct %s_ret {\n" name;
5510 pr " str %s<>;\n" n;
5513 pr "struct %s_ret {\n" name;
5514 pr " opaque %s<>;\n" n;
5519 (* Table of procedure numbers. *)
5520 pr "enum guestfs_procedure {\n";
5522 fun (shortname, _, proc_nr, _, _, _, _) ->
5523 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5525 pr " GUESTFS_PROC_NR_PROCS\n";
5529 (* Having to choose a maximum message size is annoying for several
5530 * reasons (it limits what we can do in the API), but it (a) makes
5531 * the protocol a lot simpler, and (b) provides a bound on the size
5532 * of the daemon which operates in limited memory space.
5534 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5537 (* Message header, etc. *)
5539 /* The communication protocol is now documented in the guestfs(3)
5543 const GUESTFS_PROGRAM = 0x2000F5F5;
5544 const GUESTFS_PROTOCOL_VERSION = 1;
5546 /* These constants must be larger than any possible message length. */
5547 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5548 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5550 enum guestfs_message_direction {
5551 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5552 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5555 enum guestfs_message_status {
5556 GUESTFS_STATUS_OK = 0,
5557 GUESTFS_STATUS_ERROR = 1
5560 const GUESTFS_ERROR_LEN = 256;
5562 struct guestfs_message_error {
5563 string error_message<GUESTFS_ERROR_LEN>;
5566 struct guestfs_message_header {
5567 unsigned prog; /* GUESTFS_PROGRAM */
5568 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5569 guestfs_procedure proc; /* GUESTFS_PROC_x */
5570 guestfs_message_direction direction;
5571 unsigned serial; /* message serial number */
5572 guestfs_message_status status;
5575 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5577 struct guestfs_chunk {
5578 int cancel; /* if non-zero, transfer is cancelled */
5579 /* data size is 0 bytes if the transfer has finished successfully */
5580 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5584 (* Generate the guestfs-structs.h file. *)
5585 and generate_structs_h () =
5586 generate_header CStyle LGPLv2plus;
5588 (* This is a public exported header file containing various
5589 * structures. The structures are carefully written to have
5590 * exactly the same in-memory format as the XDR structures that
5591 * we use on the wire to the daemon. The reason for creating
5592 * copies of these structures here is just so we don't have to
5593 * export the whole of guestfs_protocol.h (which includes much
5594 * unrelated and XDR-dependent stuff that we don't want to be
5595 * public, or required by clients).
5597 * To reiterate, we will pass these structures to and from the
5598 * client with a simple assignment or memcpy, so the format
5599 * must be identical to what rpcgen / the RFC defines.
5602 (* Public structures. *)
5605 pr "struct guestfs_%s {\n" typ;
5608 | name, FChar -> pr " char %s;\n" name
5609 | name, FString -> pr " char *%s;\n" name
5611 pr " uint32_t %s_len;\n" name;
5612 pr " char *%s;\n" name
5613 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5614 | name, FUInt32 -> pr " uint32_t %s;\n" name
5615 | name, FInt32 -> pr " int32_t %s;\n" name
5616 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5617 | name, FInt64 -> pr " int64_t %s;\n" name
5618 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5622 pr "struct guestfs_%s_list {\n" typ;
5623 pr " uint32_t len;\n";
5624 pr " struct guestfs_%s *val;\n" typ;
5627 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5628 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5632 (* Generate the guestfs-actions.h file. *)
5633 and generate_actions_h () =
5634 generate_header CStyle LGPLv2plus;
5636 fun (shortname, style, _, _, _, _, _) ->
5637 let name = "guestfs_" ^ shortname in
5638 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5642 (* Generate the guestfs-internal-actions.h file. *)
5643 and generate_internal_actions_h () =
5644 generate_header CStyle LGPLv2plus;
5646 fun (shortname, style, _, _, _, _, _) ->
5647 let name = "guestfs__" ^ shortname in
5648 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5650 ) non_daemon_functions
5652 (* Generate the client-side dispatch stubs. *)
5653 and generate_client_actions () =
5654 generate_header CStyle LGPLv2plus;
5661 #include <inttypes.h>
5663 #include \"guestfs.h\"
5664 #include \"guestfs-internal.h\"
5665 #include \"guestfs-internal-actions.h\"
5666 #include \"guestfs_protocol.h\"
5668 #define error guestfs_error
5669 //#define perrorf guestfs_perrorf
5670 #define safe_malloc guestfs_safe_malloc
5671 #define safe_realloc guestfs_safe_realloc
5672 //#define safe_strdup guestfs_safe_strdup
5673 #define safe_memdup guestfs_safe_memdup
5675 /* Check the return message from a call for validity. */
5677 check_reply_header (guestfs_h *g,
5678 const struct guestfs_message_header *hdr,
5679 unsigned int proc_nr, unsigned int serial)
5681 if (hdr->prog != GUESTFS_PROGRAM) {
5682 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5685 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5686 error (g, \"wrong protocol version (%%d/%%d)\",
5687 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5690 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5691 error (g, \"unexpected message direction (%%d/%%d)\",
5692 hdr->direction, GUESTFS_DIRECTION_REPLY);
5695 if (hdr->proc != proc_nr) {
5696 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5699 if (hdr->serial != serial) {
5700 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5707 /* Check we are in the right state to run a high-level action. */
5709 check_state (guestfs_h *g, const char *caller)
5711 if (!guestfs__is_ready (g)) {
5712 if (guestfs__is_config (g) || guestfs__is_launching (g))
5713 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5716 error (g, \"%%s called from the wrong state, %%d != READY\",
5717 caller, guestfs__get_state (g));
5725 (* Generate code to generate guestfish call traces. *)
5726 let trace_call shortname style =
5727 pr " if (guestfs__get_trace (g)) {\n";
5730 List.exists (function
5731 | StringList _ | DeviceList _ -> true
5732 | _ -> false) (snd style) in
5738 pr " printf (\"%s\");\n" shortname;
5741 | String n (* strings *)
5747 (* guestfish doesn't support string escaping, so neither do we *)
5748 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5749 | OptString n -> (* string option *)
5750 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5751 pr " else printf (\" null\");\n"
5753 | DeviceList n -> (* string list *)
5754 pr " putchar (' ');\n";
5755 pr " putchar ('\"');\n";
5756 pr " for (i = 0; %s[i]; ++i) {\n" n;
5757 pr " if (i > 0) putchar (' ');\n";
5758 pr " fputs (%s[i], stdout);\n" n;
5760 pr " putchar ('\"');\n";
5761 | Bool n -> (* boolean *)
5762 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5763 | Int n -> (* int *)
5764 pr " printf (\" %%d\", %s);\n" n
5766 pr " printf (\" %%\" PRIi64, %s);\n" n
5768 pr " putchar ('\\n');\n";
5773 (* For non-daemon functions, generate a wrapper around each function. *)
5775 fun (shortname, style, _, _, _, _, _) ->
5776 let name = "guestfs_" ^ shortname in
5778 generate_prototype ~extern:false ~semicolon:false ~newline:true
5779 ~handle:"g" name style;
5781 trace_call shortname style;
5782 pr " return guestfs__%s " shortname;
5783 generate_c_call_args ~handle:"g" style;
5787 ) non_daemon_functions;
5789 (* Client-side stubs for each function. *)
5791 fun (shortname, style, _, _, _, _, _) ->
5792 let name = "guestfs_" ^ shortname in
5794 (* Generate the action stub. *)
5795 generate_prototype ~extern:false ~semicolon:false ~newline:true
5796 ~handle:"g" name style;
5799 match fst style with
5800 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5801 | RConstString _ | RConstOptString _ ->
5802 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5803 | RString _ | RStringList _
5804 | RStruct _ | RStructList _
5805 | RHashtable _ | RBufferOut _ ->
5810 (match snd style with
5812 | _ -> pr " struct %s_args args;\n" name
5815 pr " guestfs_message_header hdr;\n";
5816 pr " guestfs_message_error err;\n";
5818 match fst style with
5820 | RConstString _ | RConstOptString _ ->
5821 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5823 | RBool _ | RString _ | RStringList _
5824 | RStruct _ | RStructList _
5825 | RHashtable _ | RBufferOut _ ->
5826 pr " struct %s_ret ret;\n" name;
5829 pr " int serial;\n";
5832 trace_call shortname style;
5833 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5834 shortname error_code;
5835 pr " guestfs___set_busy (g);\n";
5838 (* Send the main header and arguments. *)
5839 (match snd style with
5841 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5842 (String.uppercase shortname)
5846 | Pathname n | Device n | Dev_or_Path n | String n ->
5847 pr " args.%s = (char *) %s;\n" n n
5849 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5850 | StringList n | DeviceList n ->
5851 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5852 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5854 pr " args.%s = %s;\n" n n
5856 pr " args.%s = %s;\n" n n
5858 pr " args.%s = %s;\n" n n
5859 | FileIn _ | FileOut _ -> ()
5861 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5862 (String.uppercase shortname);
5863 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5866 pr " if (serial == -1) {\n";
5867 pr " guestfs___end_busy (g);\n";
5868 pr " return %s;\n" error_code;
5872 (* Send any additional files (FileIn) requested. *)
5873 let need_read_reply_label = ref false in
5877 pr " r = guestfs___send_file (g, %s);\n" n;
5878 pr " if (r == -1) {\n";
5879 pr " guestfs___end_busy (g);\n";
5880 pr " return %s;\n" error_code;
5882 pr " if (r == -2) /* daemon cancelled */\n";
5883 pr " goto read_reply;\n";
5884 need_read_reply_label := true;
5889 (* Wait for the reply from the remote end. *)
5890 if !need_read_reply_label then pr " read_reply:\n";
5891 pr " memset (&hdr, 0, sizeof hdr);\n";
5892 pr " memset (&err, 0, sizeof err);\n";
5893 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5895 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5899 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5902 pr " if (r == -1) {\n";
5903 pr " guestfs___end_busy (g);\n";
5904 pr " return %s;\n" error_code;
5908 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5909 (String.uppercase shortname);
5910 pr " guestfs___end_busy (g);\n";
5911 pr " return %s;\n" error_code;
5915 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5916 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5917 pr " free (err.error_message);\n";
5918 pr " guestfs___end_busy (g);\n";
5919 pr " return %s;\n" error_code;
5923 (* Expecting to receive further files (FileOut)? *)
5927 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5928 pr " guestfs___end_busy (g);\n";
5929 pr " return %s;\n" error_code;
5935 pr " guestfs___end_busy (g);\n";
5937 (match fst style with
5938 | RErr -> pr " return 0;\n"
5939 | RInt n | RInt64 n | RBool n ->
5940 pr " return ret.%s;\n" n
5941 | RConstString _ | RConstOptString _ ->
5942 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5944 pr " return ret.%s; /* caller will free */\n" n
5945 | RStringList n | RHashtable n ->
5946 pr " /* caller will free this, but we need to add a NULL entry */\n";
5947 pr " ret.%s.%s_val =\n" n n;
5948 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5949 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5951 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5952 pr " return ret.%s.%s_val;\n" n n
5954 pr " /* caller will free this */\n";
5955 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5956 | RStructList (n, _) ->
5957 pr " /* caller will free this */\n";
5958 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5960 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5961 pr " * _val might be NULL here. To make the API saner for\n";
5962 pr " * callers, we turn this case into a unique pointer (using\n";
5963 pr " * malloc(1)).\n";
5965 pr " if (ret.%s.%s_len > 0) {\n" n n;
5966 pr " *size_r = ret.%s.%s_len;\n" n n;
5967 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5969 pr " free (ret.%s.%s_val);\n" n n;
5970 pr " char *p = safe_malloc (g, 1);\n";
5971 pr " *size_r = ret.%s.%s_len;\n" n n;
5979 (* Functions to free structures. *)
5980 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5981 pr " * structure format is identical to the XDR format. See note in\n";
5982 pr " * generator.ml.\n";
5989 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5991 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5997 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5999 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6006 (* Generate daemon/actions.h. *)
6007 and generate_daemon_actions_h () =
6008 generate_header CStyle GPLv2plus;
6010 pr "#include \"../src/guestfs_protocol.h\"\n";
6014 fun (name, style, _, _, _, _, _) ->
6016 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6020 (* Generate the linker script which controls the visibility of
6021 * symbols in the public ABI and ensures no other symbols get
6022 * exported accidentally.
6024 and generate_linker_script () =
6025 generate_header HashStyle GPLv2plus;
6030 "guestfs_get_error_handler";
6031 "guestfs_get_out_of_memory_handler";
6032 "guestfs_last_error";
6033 "guestfs_set_error_handler";
6034 "guestfs_set_launch_done_callback";
6035 "guestfs_set_log_message_callback";
6036 "guestfs_set_out_of_memory_handler";
6037 "guestfs_set_subprocess_quit_callback";
6039 (* Unofficial parts of the API: the bindings code use these
6040 * functions, so it is useful to export them.
6042 "guestfs_safe_calloc";
6043 "guestfs_safe_malloc";
6046 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6050 List.map (fun (typ, _) ->
6051 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6054 let globals = List.sort compare (globals @ functions @ structs) in
6058 List.iter (pr " %s;\n") globals;
6065 (* Generate the server-side stubs. *)
6066 and generate_daemon_actions () =
6067 generate_header CStyle GPLv2plus;
6069 pr "#include <config.h>\n";
6071 pr "#include <stdio.h>\n";
6072 pr "#include <stdlib.h>\n";
6073 pr "#include <string.h>\n";
6074 pr "#include <inttypes.h>\n";
6075 pr "#include <rpc/types.h>\n";
6076 pr "#include <rpc/xdr.h>\n";
6078 pr "#include \"daemon.h\"\n";
6079 pr "#include \"c-ctype.h\"\n";
6080 pr "#include \"../src/guestfs_protocol.h\"\n";
6081 pr "#include \"actions.h\"\n";
6085 fun (name, style, _, _, _, _, _) ->
6086 (* Generate server-side stubs. *)
6087 pr "static void %s_stub (XDR *xdr_in)\n" name;
6090 match fst style with
6091 | RErr | RInt _ -> pr " int r;\n"; "-1"
6092 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6093 | RBool _ -> pr " int r;\n"; "-1"
6094 | RConstString _ | RConstOptString _ ->
6095 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6096 | RString _ -> pr " char *r;\n"; "NULL"
6097 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6098 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6099 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6101 pr " size_t size = 1;\n";
6105 (match snd style with
6108 pr " struct guestfs_%s_args args;\n" name;
6111 | Device n | Dev_or_Path n
6114 | OptString n -> pr " char *%s;\n" n
6115 | StringList n | DeviceList n -> pr " char **%s;\n" n
6116 | Bool n -> pr " int %s;\n" n
6117 | Int n -> pr " int %s;\n" n
6118 | Int64 n -> pr " int64_t %s;\n" n
6119 | FileIn _ | FileOut _ -> ()
6125 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6127 (match snd style with
6130 pr " memset (&args, 0, sizeof args);\n";
6132 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6134 pr " cancel_receive ();\n";
6135 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6139 pr " char *%s = args.%s;\n" n n
6141 let pr_list_handling_code n =
6142 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6143 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6144 pr " if (%s == NULL) {\n" n;
6146 pr " cancel_receive ();\n";
6147 pr " reply_with_perror (\"realloc\");\n";
6150 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6151 pr " args.%s.%s_val = %s;\n" n n n;
6157 pr " ABS_PATH (%s, %s, goto done);\n"
6158 n (if is_filein then "cancel_receive ()" else "");
6161 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6162 n (if is_filein then "cancel_receive ()" else "");
6165 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6166 n (if is_filein then "cancel_receive ()" else "");
6167 | String n -> pr_args n
6168 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6170 pr_list_handling_code n;
6172 pr_list_handling_code n;
6173 pr " /* Ensure that each is a device,\n";
6174 pr " * and perform device name translation. */\n";
6175 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6176 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6177 (if is_filein then "cancel_receive ()" else "");
6179 | Bool n -> pr " %s = args.%s;\n" n n
6180 | Int n -> pr " %s = args.%s;\n" n n
6181 | Int64 n -> pr " %s = args.%s;\n" n n
6182 | FileIn _ | FileOut _ -> ()
6188 (* this is used at least for do_equal *)
6189 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6190 (* Emit NEED_ROOT just once, even when there are two or
6191 more Pathname args *)
6192 pr " NEED_ROOT (%s, goto done);\n"
6193 (if is_filein then "cancel_receive ()" else "");
6196 (* Don't want to call the impl with any FileIn or FileOut
6197 * parameters, since these go "outside" the RPC protocol.
6200 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6202 pr " r = do_%s " name;
6203 generate_c_call_args (fst style, args');
6206 (match fst style with
6207 | RErr | RInt _ | RInt64 _ | RBool _
6208 | RConstString _ | RConstOptString _
6209 | RString _ | RStringList _ | RHashtable _
6210 | RStruct (_, _) | RStructList (_, _) ->
6211 pr " if (r == %s)\n" error_code;
6212 pr " /* do_%s has already called reply_with_error */\n" name;
6216 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6217 pr " * an ordinary zero-length buffer), so be careful ...\n";
6219 pr " if (size == 1 && r == %s)\n" error_code;
6220 pr " /* do_%s has already called reply_with_error */\n" name;
6225 (* If there are any FileOut parameters, then the impl must
6226 * send its own reply.
6229 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6231 pr " /* do_%s has already sent a reply */\n" name
6233 match fst style with
6234 | RErr -> pr " reply (NULL, NULL);\n"
6235 | RInt n | RInt64 n | RBool n ->
6236 pr " struct guestfs_%s_ret ret;\n" name;
6237 pr " ret.%s = r;\n" n;
6238 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6240 | RConstString _ | RConstOptString _ ->
6241 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6243 pr " struct guestfs_%s_ret ret;\n" name;
6244 pr " ret.%s = r;\n" n;
6245 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6248 | RStringList n | RHashtable n ->
6249 pr " struct guestfs_%s_ret ret;\n" name;
6250 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6251 pr " ret.%s.%s_val = r;\n" n n;
6252 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6254 pr " free_strings (r);\n"
6256 pr " struct guestfs_%s_ret ret;\n" name;
6257 pr " ret.%s = *r;\n" n;
6258 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6260 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6262 | RStructList (n, _) ->
6263 pr " struct guestfs_%s_ret ret;\n" name;
6264 pr " ret.%s = *r;\n" n;
6265 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6267 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6270 pr " struct guestfs_%s_ret ret;\n" name;
6271 pr " ret.%s.%s_val = r;\n" n n;
6272 pr " ret.%s.%s_len = size;\n" n n;
6273 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6278 (* Free the args. *)
6280 (match snd style with
6283 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6290 (* Dispatch function. *)
6291 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6293 pr " switch (proc_nr) {\n";
6296 fun (name, style, _, _, _, _, _) ->
6297 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6298 pr " %s_stub (xdr_in);\n" name;
6303 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";
6308 (* LVM columns and tokenization functions. *)
6309 (* XXX This generates crap code. We should rethink how we
6315 pr "static const char *lvm_%s_cols = \"%s\";\n"
6316 typ (String.concat "," (List.map fst cols));
6319 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6321 pr " char *tok, *p, *next;\n";
6325 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6328 pr " if (!str) {\n";
6329 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6332 pr " if (!*str || c_isspace (*str)) {\n";
6333 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6338 fun (name, coltype) ->
6339 pr " if (!tok) {\n";
6340 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6343 pr " p = strchrnul (tok, ',');\n";
6344 pr " if (*p) next = p+1; else next = NULL;\n";
6345 pr " *p = '\\0';\n";
6348 pr " r->%s = strdup (tok);\n" name;
6349 pr " if (r->%s == NULL) {\n" name;
6350 pr " perror (\"strdup\");\n";
6354 pr " for (i = j = 0; i < 32; ++j) {\n";
6355 pr " if (tok[j] == '\\0') {\n";
6356 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6358 pr " } else if (tok[j] != '-')\n";
6359 pr " r->%s[i++] = tok[j];\n" name;
6362 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6363 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6367 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6368 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6372 pr " if (tok[0] == '\\0')\n";
6373 pr " r->%s = -1;\n" name;
6374 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6375 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6378 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6379 assert false (* can never be an LVM column *)
6381 pr " tok = next;\n";
6384 pr " if (tok != NULL) {\n";
6385 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6392 pr "guestfs_int_lvm_%s_list *\n" typ;
6393 pr "parse_command_line_%ss (void)\n" typ;
6395 pr " char *out, *err;\n";
6396 pr " char *p, *pend;\n";
6398 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6399 pr " void *newp;\n";
6401 pr " ret = malloc (sizeof *ret);\n";
6402 pr " if (!ret) {\n";
6403 pr " reply_with_perror (\"malloc\");\n";
6404 pr " return NULL;\n";
6407 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6408 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6410 pr " r = command (&out, &err,\n";
6411 pr " \"lvm\", \"%ss\",\n" typ;
6412 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6413 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6414 pr " if (r == -1) {\n";
6415 pr " reply_with_error (\"%%s\", err);\n";
6416 pr " free (out);\n";
6417 pr " free (err);\n";
6418 pr " free (ret);\n";
6419 pr " return NULL;\n";
6422 pr " free (err);\n";
6424 pr " /* Tokenize each line of the output. */\n";
6427 pr " while (p) {\n";
6428 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6429 pr " if (pend) {\n";
6430 pr " *pend = '\\0';\n";
6434 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6437 pr " if (!*p) { /* Empty line? Skip it. */\n";
6442 pr " /* Allocate some space to store this next entry. */\n";
6443 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6444 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6445 pr " if (newp == NULL) {\n";
6446 pr " reply_with_perror (\"realloc\");\n";
6447 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6448 pr " free (ret);\n";
6449 pr " free (out);\n";
6450 pr " return NULL;\n";
6452 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6454 pr " /* Tokenize the next entry. */\n";
6455 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6456 pr " if (r == -1) {\n";
6457 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6458 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6459 pr " free (ret);\n";
6460 pr " free (out);\n";
6461 pr " return NULL;\n";
6468 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6470 pr " free (out);\n";
6471 pr " return ret;\n";
6474 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6476 (* Generate a list of function names, for debugging in the daemon.. *)
6477 and generate_daemon_names () =
6478 generate_header CStyle GPLv2plus;
6480 pr "#include <config.h>\n";
6482 pr "#include \"daemon.h\"\n";
6485 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6486 pr "const char *function_names[] = {\n";
6488 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6492 (* Generate the optional groups for the daemon to implement
6493 * guestfs_available.
6495 and generate_daemon_optgroups_c () =
6496 generate_header CStyle GPLv2plus;
6498 pr "#include <config.h>\n";
6500 pr "#include \"daemon.h\"\n";
6501 pr "#include \"optgroups.h\"\n";
6504 pr "struct optgroup optgroups[] = {\n";
6507 pr " { \"%s\", optgroup_%s_available },\n" group group
6509 pr " { NULL, NULL }\n";
6512 and generate_daemon_optgroups_h () =
6513 generate_header CStyle GPLv2plus;
6517 pr "extern int optgroup_%s_available (void);\n" group
6520 (* Generate the tests. *)
6521 and generate_tests () =
6522 generate_header CStyle GPLv2plus;
6529 #include <sys/types.h>
6532 #include \"guestfs.h\"
6533 #include \"guestfs-internal.h\"
6535 static guestfs_h *g;
6536 static int suppress_error = 0;
6538 static void print_error (guestfs_h *g, void *data, const char *msg)
6540 if (!suppress_error)
6541 fprintf (stderr, \"%%s\\n\", msg);
6544 /* FIXME: nearly identical code appears in fish.c */
6545 static void print_strings (char *const *argv)
6549 for (argc = 0; argv[argc] != NULL; ++argc)
6550 printf (\"\\t%%s\\n\", argv[argc]);
6554 static void print_table (char const *const *argv)
6558 for (i = 0; argv[i] != NULL; i += 2)
6559 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6565 (* Generate a list of commands which are not tested anywhere. *)
6566 pr "static void no_test_warnings (void)\n";
6569 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6571 fun (_, _, _, _, tests, _, _) ->
6572 let tests = filter_map (
6574 | (_, (Always|If _|Unless _), test) -> Some test
6575 | (_, Disabled, _) -> None
6577 let seq = List.concat (List.map seq_of_test tests) in
6578 let cmds_tested = List.map List.hd seq in
6579 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6583 fun (name, _, _, _, _, _, _) ->
6584 if not (Hashtbl.mem hash name) then
6585 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6591 (* Generate the actual tests. Note that we generate the tests
6592 * in reverse order, deliberately, so that (in general) the
6593 * newest tests run first. This makes it quicker and easier to
6598 fun (name, _, _, flags, tests, _, _) ->
6599 mapi (generate_one_test name flags) tests
6600 ) (List.rev all_functions) in
6601 let test_names = List.concat test_names in
6602 let nr_tests = List.length test_names in
6605 int main (int argc, char *argv[])
6608 unsigned long int n_failed = 0;
6609 const char *filename;
6611 int nr_tests, test_num = 0;
6613 setbuf (stdout, NULL);
6615 no_test_warnings ();
6617 g = guestfs_create ();
6619 printf (\"guestfs_create FAILED\\n\");
6620 exit (EXIT_FAILURE);
6623 guestfs_set_error_handler (g, print_error, NULL);
6625 guestfs_set_path (g, \"../appliance\");
6627 filename = \"test1.img\";
6628 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6631 exit (EXIT_FAILURE);
6633 if (lseek (fd, %d, SEEK_SET) == -1) {
6637 exit (EXIT_FAILURE);
6639 if (write (fd, &c, 1) == -1) {
6643 exit (EXIT_FAILURE);
6645 if (close (fd) == -1) {
6648 exit (EXIT_FAILURE);
6650 if (guestfs_add_drive (g, filename) == -1) {
6651 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6652 exit (EXIT_FAILURE);
6655 filename = \"test2.img\";
6656 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6659 exit (EXIT_FAILURE);
6661 if (lseek (fd, %d, SEEK_SET) == -1) {
6665 exit (EXIT_FAILURE);
6667 if (write (fd, &c, 1) == -1) {
6671 exit (EXIT_FAILURE);
6673 if (close (fd) == -1) {
6676 exit (EXIT_FAILURE);
6678 if (guestfs_add_drive (g, filename) == -1) {
6679 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6680 exit (EXIT_FAILURE);
6683 filename = \"test3.img\";
6684 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6687 exit (EXIT_FAILURE);
6689 if (lseek (fd, %d, SEEK_SET) == -1) {
6693 exit (EXIT_FAILURE);
6695 if (write (fd, &c, 1) == -1) {
6699 exit (EXIT_FAILURE);
6701 if (close (fd) == -1) {
6704 exit (EXIT_FAILURE);
6706 if (guestfs_add_drive (g, filename) == -1) {
6707 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6708 exit (EXIT_FAILURE);
6711 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6712 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6713 exit (EXIT_FAILURE);
6716 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6719 if (guestfs_launch (g) == -1) {
6720 printf (\"guestfs_launch FAILED\\n\");
6721 exit (EXIT_FAILURE);
6724 /* Cancel previous alarm. */
6729 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6733 pr " test_num++;\n";
6734 pr " if (guestfs_get_verbose (g))\n";
6735 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6736 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6737 pr " if (%s () == -1) {\n" test_name;
6738 pr " printf (\"%s FAILED\\n\");\n" test_name;
6739 pr " n_failed++;\n";
6744 pr " guestfs_close (g);\n";
6745 pr " unlink (\"test1.img\");\n";
6746 pr " unlink (\"test2.img\");\n";
6747 pr " unlink (\"test3.img\");\n";
6750 pr " if (n_failed > 0) {\n";
6751 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6752 pr " exit (EXIT_FAILURE);\n";
6756 pr " exit (EXIT_SUCCESS);\n";
6759 and generate_one_test name flags i (init, prereq, test) =
6760 let test_name = sprintf "test_%s_%d" name i in
6763 static int %s_skip (void)
6767 str = getenv (\"TEST_ONLY\");
6769 return strstr (str, \"%s\") == NULL;
6770 str = getenv (\"SKIP_%s\");
6771 if (str && STREQ (str, \"1\")) return 1;
6772 str = getenv (\"SKIP_TEST_%s\");
6773 if (str && STREQ (str, \"1\")) return 1;
6777 " test_name name (String.uppercase test_name) (String.uppercase name);
6780 | Disabled | Always -> ()
6781 | If code | Unless code ->
6782 pr "static int %s_prereq (void)\n" test_name;
6790 static int %s (void)
6793 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6797 " test_name test_name test_name;
6799 (* Optional functions should only be tested if the relevant
6800 * support is available in the daemon.
6806 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6808 pr " suppress_error = 1;\n";
6809 pr " r = guestfs_available (g, (char **) groups);\n";
6810 pr " suppress_error = 0;\n";
6811 pr " if (r == -1) {\n";
6812 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6821 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6823 pr " if (! %s_prereq ()) {\n" test_name;
6824 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6828 generate_one_test_body name i test_name init test;
6830 pr " if (%s_prereq ()) {\n" test_name;
6831 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6835 generate_one_test_body name i test_name init test;
6837 generate_one_test_body name i test_name init test
6845 and generate_one_test_body name i test_name init test =
6847 | InitNone (* XXX at some point, InitNone and InitEmpty became
6848 * folded together as the same thing. Really we should
6849 * make InitNone do nothing at all, but the tests may
6850 * need to be checked to make sure this is OK.
6853 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6854 List.iter (generate_test_command_call test_name)
6855 [["blockdev_setrw"; "/dev/sda"];
6859 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6860 List.iter (generate_test_command_call test_name)
6861 [["blockdev_setrw"; "/dev/sda"];
6864 ["part_disk"; "/dev/sda"; "mbr"]]
6866 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6867 List.iter (generate_test_command_call test_name)
6868 [["blockdev_setrw"; "/dev/sda"];
6871 ["part_disk"; "/dev/sda"; "mbr"];
6872 ["mkfs"; "ext2"; "/dev/sda1"];
6873 ["mount_options"; ""; "/dev/sda1"; "/"]]
6874 | InitBasicFSonLVM ->
6875 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6877 List.iter (generate_test_command_call test_name)
6878 [["blockdev_setrw"; "/dev/sda"];
6881 ["part_disk"; "/dev/sda"; "mbr"];
6882 ["pvcreate"; "/dev/sda1"];
6883 ["vgcreate"; "VG"; "/dev/sda1"];
6884 ["lvcreate"; "LV"; "VG"; "8"];
6885 ["mkfs"; "ext2"; "/dev/VG/LV"];
6886 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6888 pr " /* InitISOFS for %s */\n" test_name;
6889 List.iter (generate_test_command_call test_name)
6890 [["blockdev_setrw"; "/dev/sda"];
6893 ["mount_ro"; "/dev/sdd"; "/"]]
6896 let get_seq_last = function
6898 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6901 let seq = List.rev seq in
6902 List.rev (List.tl seq), List.hd seq
6907 pr " /* TestRun for %s (%d) */\n" name i;
6908 List.iter (generate_test_command_call test_name) seq
6909 | TestOutput (seq, expected) ->
6910 pr " /* TestOutput for %s (%d) */\n" name i;
6911 pr " const char *expected = \"%s\";\n" (c_quote expected);
6912 let seq, last = get_seq_last seq in
6914 pr " if (STRNEQ (r, expected)) {\n";
6915 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6919 List.iter (generate_test_command_call test_name) seq;
6920 generate_test_command_call ~test test_name last
6921 | TestOutputList (seq, expected) ->
6922 pr " /* TestOutputList for %s (%d) */\n" name i;
6923 let seq, last = get_seq_last seq in
6927 pr " if (!r[%d]) {\n" i;
6928 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6929 pr " print_strings (r);\n";
6933 pr " const char *expected = \"%s\";\n" (c_quote str);
6934 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6935 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6940 pr " if (r[%d] != NULL) {\n" (List.length expected);
6941 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6943 pr " print_strings (r);\n";
6947 List.iter (generate_test_command_call test_name) seq;
6948 generate_test_command_call ~test test_name last
6949 | TestOutputListOfDevices (seq, expected) ->
6950 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6951 let seq, last = get_seq_last seq in
6955 pr " if (!r[%d]) {\n" i;
6956 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6957 pr " print_strings (r);\n";
6961 pr " const char *expected = \"%s\";\n" (c_quote str);
6962 pr " r[%d][5] = 's';\n" i;
6963 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6964 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6969 pr " if (r[%d] != NULL) {\n" (List.length expected);
6970 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6972 pr " print_strings (r);\n";
6976 List.iter (generate_test_command_call test_name) seq;
6977 generate_test_command_call ~test test_name last
6978 | TestOutputInt (seq, expected) ->
6979 pr " /* TestOutputInt for %s (%d) */\n" name i;
6980 let seq, last = get_seq_last seq in
6982 pr " if (r != %d) {\n" expected;
6983 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6989 List.iter (generate_test_command_call test_name) seq;
6990 generate_test_command_call ~test test_name last
6991 | TestOutputIntOp (seq, op, expected) ->
6992 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6993 let seq, last = get_seq_last seq in
6995 pr " if (! (r %s %d)) {\n" op expected;
6996 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6997 test_name op expected;
7002 List.iter (generate_test_command_call test_name) seq;
7003 generate_test_command_call ~test test_name last
7004 | TestOutputTrue seq ->
7005 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7006 let seq, last = get_seq_last seq in
7009 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7014 List.iter (generate_test_command_call test_name) seq;
7015 generate_test_command_call ~test test_name last
7016 | TestOutputFalse seq ->
7017 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7018 let seq, last = get_seq_last seq in
7021 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7026 List.iter (generate_test_command_call test_name) seq;
7027 generate_test_command_call ~test test_name last
7028 | TestOutputLength (seq, expected) ->
7029 pr " /* TestOutputLength for %s (%d) */\n" name i;
7030 let seq, last = get_seq_last seq in
7033 pr " for (j = 0; j < %d; ++j)\n" expected;
7034 pr " if (r[j] == NULL) {\n";
7035 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7037 pr " print_strings (r);\n";
7040 pr " if (r[j] != NULL) {\n";
7041 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7043 pr " print_strings (r);\n";
7047 List.iter (generate_test_command_call test_name) seq;
7048 generate_test_command_call ~test test_name last
7049 | TestOutputBuffer (seq, expected) ->
7050 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7051 pr " const char *expected = \"%s\";\n" (c_quote expected);
7052 let seq, last = get_seq_last seq in
7053 let len = String.length expected in
7055 pr " if (size != %d) {\n" len;
7056 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7059 pr " if (STRNEQLEN (r, expected, size)) {\n";
7060 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7064 List.iter (generate_test_command_call test_name) seq;
7065 generate_test_command_call ~test test_name last
7066 | TestOutputStruct (seq, checks) ->
7067 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7068 let seq, last = get_seq_last seq in
7072 | CompareWithInt (field, expected) ->
7073 pr " if (r->%s != %d) {\n" field expected;
7074 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7075 test_name field expected;
7076 pr " (int) r->%s);\n" field;
7079 | CompareWithIntOp (field, op, expected) ->
7080 pr " if (!(r->%s %s %d)) {\n" field op expected;
7081 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7082 test_name field op expected;
7083 pr " (int) r->%s);\n" field;
7086 | CompareWithString (field, expected) ->
7087 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7088 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7089 test_name field expected;
7090 pr " r->%s);\n" field;
7093 | CompareFieldsIntEq (field1, field2) ->
7094 pr " if (r->%s != r->%s) {\n" field1 field2;
7095 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7096 test_name field1 field2;
7097 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7100 | CompareFieldsStrEq (field1, field2) ->
7101 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7102 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7103 test_name field1 field2;
7104 pr " r->%s, r->%s);\n" field1 field2;
7109 List.iter (generate_test_command_call test_name) seq;
7110 generate_test_command_call ~test test_name last
7111 | TestLastFail seq ->
7112 pr " /* TestLastFail for %s (%d) */\n" name i;
7113 let seq, last = get_seq_last seq in
7114 List.iter (generate_test_command_call test_name) seq;
7115 generate_test_command_call test_name ~expect_error:true last
7117 (* Generate the code to run a command, leaving the result in 'r'.
7118 * If you expect to get an error then you should set expect_error:true.
7120 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7122 | [] -> assert false
7124 (* Look up the command to find out what args/ret it has. *)
7127 let _, style, _, _, _, _, _ =
7128 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7131 failwithf "%s: in test, command %s was not found" test_name name in
7133 if List.length (snd style) <> List.length args then
7134 failwithf "%s: in test, wrong number of args given to %s"
7141 | OptString n, "NULL" -> ()
7144 | Dev_or_Path n, arg
7146 | OptString n, arg ->
7147 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7151 | FileIn _, _ | FileOut _, _ -> ()
7152 | StringList n, "" | DeviceList n, "" ->
7153 pr " const char *const %s[1] = { NULL };\n" n
7154 | StringList n, arg | DeviceList n, arg ->
7155 let strs = string_split " " arg in
7158 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7160 pr " const char *const %s[] = {\n" n;
7162 fun i _ -> pr " %s_%d,\n" n i
7166 ) (List.combine (snd style) args);
7169 match fst style with
7170 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7171 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7172 | RConstString _ | RConstOptString _ ->
7173 pr " const char *r;\n"; "NULL"
7174 | RString _ -> pr " char *r;\n"; "NULL"
7175 | RStringList _ | RHashtable _ ->
7179 | RStruct (_, typ) ->
7180 pr " struct guestfs_%s *r;\n" typ; "NULL"
7181 | RStructList (_, typ) ->
7182 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7185 pr " size_t size;\n";
7188 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7189 pr " r = guestfs_%s (g" name;
7191 (* Generate the parameters. *)
7194 | OptString _, "NULL" -> pr ", NULL"
7196 | Device n, _ | Dev_or_Path n, _
7200 | FileIn _, arg | FileOut _, arg ->
7201 pr ", \"%s\"" (c_quote arg)
7202 | StringList n, _ | DeviceList n, _ ->
7203 pr ", (char **) %s" n
7206 try int_of_string arg
7207 with Failure "int_of_string" ->
7208 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7212 try Int64.of_string arg
7213 with Failure "int_of_string" ->
7214 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7217 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7218 ) (List.combine (snd style) args);
7220 (match fst style with
7221 | RBufferOut _ -> pr ", &size"
7227 if not expect_error then
7228 pr " if (r == %s)\n" error_code
7230 pr " if (r != %s)\n" error_code;
7233 (* Insert the test code. *)
7239 (match fst style with
7240 | RErr | RInt _ | RInt64 _ | RBool _
7241 | RConstString _ | RConstOptString _ -> ()
7242 | RString _ | RBufferOut _ -> pr " free (r);\n"
7243 | RStringList _ | RHashtable _ ->
7244 pr " for (i = 0; r[i] != NULL; ++i)\n";
7245 pr " free (r[i]);\n";
7247 | RStruct (_, typ) ->
7248 pr " guestfs_free_%s (r);\n" typ
7249 | RStructList (_, typ) ->
7250 pr " guestfs_free_%s_list (r);\n" typ
7256 let str = replace_str str "\r" "\\r" in
7257 let str = replace_str str "\n" "\\n" in
7258 let str = replace_str str "\t" "\\t" in
7259 let str = replace_str str "\000" "\\0" in
7262 (* Generate a lot of different functions for guestfish. *)
7263 and generate_fish_cmds () =
7264 generate_header CStyle GPLv2plus;
7268 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7270 let all_functions_sorted =
7272 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7273 ) all_functions_sorted in
7275 pr "#include <config.h>\n";
7277 pr "#include <stdio.h>\n";
7278 pr "#include <stdlib.h>\n";
7279 pr "#include <string.h>\n";
7280 pr "#include <inttypes.h>\n";
7282 pr "#include <guestfs.h>\n";
7283 pr "#include \"c-ctype.h\"\n";
7284 pr "#include \"full-write.h\"\n";
7285 pr "#include \"xstrtol.h\"\n";
7286 pr "#include \"fish.h\"\n";
7289 (* list_commands function, which implements guestfish -h *)
7290 pr "void list_commands (void)\n";
7292 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7293 pr " list_builtin_commands ();\n";
7295 fun (name, _, _, flags, _, shortdesc, _) ->
7296 let name = replace_char name '_' '-' in
7297 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7299 ) all_functions_sorted;
7300 pr " printf (\" %%s\\n\",";
7301 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7305 (* display_command function, which implements guestfish -h cmd *)
7306 pr "void display_command (const char *cmd)\n";
7309 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7310 let name2 = replace_char name '_' '-' in
7312 try find_map (function FishAlias n -> Some n | _ -> None) flags
7313 with Not_found -> name in
7314 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7316 match snd style with
7320 name2 (String.concat " " (List.map name_of_argt args)) in
7323 if List.mem ProtocolLimitWarning flags then
7324 ("\n\n" ^ protocol_limit_warning)
7327 (* For DangerWillRobinson commands, we should probably have
7328 * guestfish prompt before allowing you to use them (especially
7329 * in interactive mode). XXX
7333 if List.mem DangerWillRobinson flags then
7334 ("\n\n" ^ danger_will_robinson)
7339 match deprecation_notice flags with
7341 | Some txt -> "\n\n" ^ txt in
7343 let describe_alias =
7344 if name <> alias then
7345 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7349 pr "STRCASEEQ (cmd, \"%s\")" name;
7350 if name <> name2 then
7351 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7352 if name <> alias then
7353 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7355 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7357 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7358 "=head1 DESCRIPTION\n\n" ^
7359 longdesc ^ warnings ^ describe_alias);
7362 pr " display_builtin_command (cmd);\n";
7366 let emit_print_list_function typ =
7367 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7370 pr " unsigned int i;\n";
7372 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7373 pr " printf (\"[%%d] = {\\n\", i);\n";
7374 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7375 pr " printf (\"}\\n\");\n";
7381 (* print_* functions *)
7385 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7387 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7390 pr " unsigned int i;\n";
7396 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7398 pr " printf (\"%%s%s: \", indent);\n" name;
7399 pr " for (i = 0; i < 32; ++i)\n";
7400 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7401 pr " printf (\"\\n\");\n"
7403 pr " printf (\"%%s%s: \", indent);\n" name;
7404 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7405 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7406 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7408 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7409 pr " printf (\"\\n\");\n"
7410 | name, (FUInt64|FBytes) ->
7411 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7414 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7417 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7420 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7423 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7425 | name, FOptPercent ->
7426 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7427 typ name name typ name;
7428 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7434 (* Emit a print_TYPE_list function definition only if that function is used. *)
7437 | typ, (RStructListOnly | RStructAndList) ->
7438 (* generate the function for typ *)
7439 emit_print_list_function typ
7440 | typ, _ -> () (* empty *)
7441 ) (rstructs_used_by all_functions);
7443 (* Emit a print_TYPE function definition only if that function is used. *)
7446 | typ, (RStructOnly | RStructAndList) ->
7447 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7449 pr " print_%s_indent (%s, \"\");\n" typ typ;
7452 | typ, _ -> () (* empty *)
7453 ) (rstructs_used_by all_functions);
7455 (* run_<action> actions *)
7457 fun (name, style, _, flags, _, _, _) ->
7458 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7460 (match fst style with
7463 | RBool _ -> pr " int r;\n"
7464 | RInt64 _ -> pr " int64_t r;\n"
7465 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7466 | RString _ -> pr " char *r;\n"
7467 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7468 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7469 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7472 pr " size_t size;\n";
7478 | OptString n -> pr " const char *%s;\n" n
7482 | FileOut n -> pr " char *%s;\n" n
7483 | StringList n | DeviceList n -> pr " char **%s;\n" n
7484 | Bool n -> pr " int %s;\n" n
7485 | Int n -> pr " int %s;\n" n
7486 | Int64 n -> pr " int64_t %s;\n" n
7489 (* Check and convert parameters. *)
7490 let argc_expected = List.length (snd style) in
7491 pr " if (argc != %d) {\n" argc_expected;
7492 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7494 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7498 let parse_integer fn fntyp rtyp range name i =
7500 pr " strtol_error xerr;\n";
7501 pr " %s r;\n" fntyp;
7503 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7504 pr " if (xerr != LONGINT_OK) {\n";
7505 pr " fprintf (stderr,\n";
7506 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7507 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7512 | Some (min, max, comment) ->
7513 pr " /* %s */\n" comment;
7514 pr " if (r < %s || r > %s) {\n" min max;
7515 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7519 pr " /* The check above should ensure this assignment does not overflow. */\n";
7521 pr " %s = r;\n" name;
7530 pr " %s = argv[%d];\n" name i
7532 | Dev_or_Path name ->
7533 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7534 pr " if (%s == NULL) return -1;\n" name
7536 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7539 pr " %s = file_in (argv[%d]);\n" name i;
7540 pr " if (%s == NULL) return -1;\n" name
7542 pr " %s = file_out (argv[%d]);\n" name i;
7543 pr " if (%s == NULL) return -1;\n" name
7544 | StringList name | DeviceList name ->
7545 pr " %s = parse_string_list (argv[%d]);\n" name i;
7546 pr " if (%s == NULL) return -1;\n" name;
7548 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7551 let min = "(-(2LL<<30))"
7552 and max = "((2LL<<30)-1)"
7554 "The Int type in the generator is a signed 31 bit int." in
7555 Some (min, max, comment) in
7556 parse_integer "xstrtoll" "long long" "int" range name i
7558 parse_integer "xstrtoll" "long long" "int64_t" None name i
7561 (* Call C API function. *)
7563 try find_map (function FishAction n -> Some n | _ -> None) flags
7564 with Not_found -> sprintf "guestfs_%s" name in
7566 generate_c_call_args ~handle:"g" style;
7571 | Device name | String name
7572 | OptString name | Bool name
7573 | Int name | Int64 name -> ()
7574 | Pathname name | Dev_or_Path name | FileOut name ->
7575 pr " free (%s);\n" name
7577 pr " free_file_in (%s);\n" name
7578 | StringList name | DeviceList name ->
7579 pr " free_strings (%s);\n" name
7582 (* Any output flags? *)
7584 let flags = filter_map (
7585 function FishOutput flag -> Some flag | _ -> None
7591 failwithf "%s: more than one FishOutput flag is not allowed" name in
7593 (* Check return value for errors and display command results. *)
7594 (match fst style with
7595 | RErr -> pr " return r;\n"
7597 pr " if (r == -1) return -1;\n";
7598 (match fish_output with
7600 pr " printf (\"%%d\\n\", r);\n";
7601 | Some FishOutputOctal ->
7602 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7603 | Some FishOutputHexadecimal ->
7604 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7607 pr " if (r == -1) return -1;\n";
7608 (match fish_output with
7610 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7611 | Some FishOutputOctal ->
7612 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7613 | Some FishOutputHexadecimal ->
7614 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7617 pr " if (r == -1) return -1;\n";
7618 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7621 pr " if (r == NULL) return -1;\n";
7622 pr " printf (\"%%s\\n\", r);\n";
7624 | RConstOptString _ ->
7625 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7628 pr " if (r == NULL) return -1;\n";
7629 pr " printf (\"%%s\\n\", r);\n";
7633 pr " if (r == NULL) return -1;\n";
7634 pr " print_strings (r);\n";
7635 pr " free_strings (r);\n";
7637 | RStruct (_, typ) ->
7638 pr " if (r == NULL) return -1;\n";
7639 pr " print_%s (r);\n" typ;
7640 pr " guestfs_free_%s (r);\n" typ;
7642 | RStructList (_, typ) ->
7643 pr " if (r == NULL) return -1;\n";
7644 pr " print_%s_list (r);\n" typ;
7645 pr " guestfs_free_%s_list (r);\n" typ;
7648 pr " if (r == NULL) return -1;\n";
7649 pr " print_table (r);\n";
7650 pr " free_strings (r);\n";
7653 pr " if (r == NULL) return -1;\n";
7654 pr " if (full_write (1, r, size) != size) {\n";
7655 pr " perror (\"write\");\n";
7666 (* run_action function *)
7667 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7670 fun (name, _, _, flags, _, _, _) ->
7671 let name2 = replace_char name '_' '-' in
7673 try find_map (function FishAlias n -> Some n | _ -> None) flags
7674 with Not_found -> name in
7676 pr "STRCASEEQ (cmd, \"%s\")" name;
7677 if name <> name2 then
7678 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7679 if name <> alias then
7680 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7682 pr " return run_%s (cmd, argc, argv);\n" name;
7686 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7687 pr " if (command_num == 1)\n";
7688 pr " extended_help_message ();\n";
7695 (* Readline completion for guestfish. *)
7696 and generate_fish_completion () =
7697 generate_header CStyle GPLv2plus;
7701 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7711 #ifdef HAVE_LIBREADLINE
7712 #include <readline/readline.h>
7717 #ifdef HAVE_LIBREADLINE
7719 static const char *const commands[] = {
7720 BUILTIN_COMMANDS_FOR_COMPLETION,
7723 (* Get the commands, including the aliases. They don't need to be
7724 * sorted - the generator() function just does a dumb linear search.
7728 fun (name, _, _, flags, _, _, _) ->
7729 let name2 = replace_char name '_' '-' in
7731 try find_map (function FishAlias n -> Some n | _ -> None) flags
7732 with Not_found -> name in
7734 if name <> alias then [name2; alias] else [name2]
7736 let commands = List.flatten commands in
7738 List.iter (pr " \"%s\",\n") commands;
7744 generator (const char *text, int state)
7746 static int index, len;
7751 len = strlen (text);
7754 rl_attempted_completion_over = 1;
7756 while ((name = commands[index]) != NULL) {
7758 if (STRCASEEQLEN (name, text, len))
7759 return strdup (name);
7765 #endif /* HAVE_LIBREADLINE */
7767 #ifdef HAVE_RL_COMPLETION_MATCHES
7768 #define RL_COMPLETION_MATCHES rl_completion_matches
7770 #ifdef HAVE_COMPLETION_MATCHES
7771 #define RL_COMPLETION_MATCHES completion_matches
7773 #endif /* else just fail if we don't have either symbol */
7776 do_completion (const char *text, int start, int end)
7778 char **matches = NULL;
7780 #ifdef HAVE_LIBREADLINE
7781 rl_completion_append_character = ' ';
7784 matches = RL_COMPLETION_MATCHES (text, generator);
7785 else if (complete_dest_paths)
7786 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7793 (* Generate the POD documentation for guestfish. *)
7794 and generate_fish_actions_pod () =
7795 let all_functions_sorted =
7797 fun (_, _, _, flags, _, _, _) ->
7798 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7799 ) all_functions_sorted in
7801 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7804 fun (name, style, _, flags, _, _, longdesc) ->
7806 Str.global_substitute rex (
7809 try Str.matched_group 1 s
7811 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7812 "C<" ^ replace_char sub '_' '-' ^ ">"
7814 let name = replace_char name '_' '-' in
7816 try find_map (function FishAlias n -> Some n | _ -> None) flags
7817 with Not_found -> name in
7819 pr "=head2 %s" name;
7820 if name <> alias then
7827 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7828 | OptString n -> pr " %s" n
7829 | StringList n | DeviceList n -> pr " '%s ...'" n
7830 | Bool _ -> pr " true|false"
7831 | Int n -> pr " %s" n
7832 | Int64 n -> pr " %s" n
7833 | FileIn n | FileOut n -> pr " (%s|-)" n
7837 pr "%s\n\n" longdesc;
7839 if List.exists (function FileIn _ | FileOut _ -> true
7840 | _ -> false) (snd style) then
7841 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7843 if List.mem ProtocolLimitWarning flags then
7844 pr "%s\n\n" protocol_limit_warning;
7846 if List.mem DangerWillRobinson flags then
7847 pr "%s\n\n" danger_will_robinson;
7849 match deprecation_notice flags with
7851 | Some txt -> pr "%s\n\n" txt
7852 ) all_functions_sorted
7854 (* Generate a C function prototype. *)
7855 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7856 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7858 ?handle name style =
7859 if extern then pr "extern ";
7860 if static then pr "static ";
7861 (match fst style with
7863 | RInt _ -> pr "int "
7864 | RInt64 _ -> pr "int64_t "
7865 | RBool _ -> pr "int "
7866 | RConstString _ | RConstOptString _ -> pr "const char *"
7867 | RString _ | RBufferOut _ -> pr "char *"
7868 | RStringList _ | RHashtable _ -> pr "char **"
7869 | RStruct (_, typ) ->
7870 if not in_daemon then pr "struct guestfs_%s *" typ
7871 else pr "guestfs_int_%s *" typ
7872 | RStructList (_, typ) ->
7873 if not in_daemon then pr "struct guestfs_%s_list *" typ
7874 else pr "guestfs_int_%s_list *" typ
7876 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7877 pr "%s%s (" prefix name;
7878 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7881 let comma = ref false in
7884 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7888 if single_line then pr ", " else pr ",\n\t\t"
7895 | Device n | Dev_or_Path n
7899 pr "const char *%s" n
7900 | StringList n | DeviceList n ->
7902 pr "char *const *%s" n
7903 | Bool n -> next (); pr "int %s" n
7904 | Int n -> next (); pr "int %s" n
7905 | Int64 n -> next (); pr "int64_t %s" n
7908 if not in_daemon then (next (); pr "const char *%s" n)
7910 if is_RBufferOut then (next (); pr "size_t *size_r");
7913 if semicolon then pr ";";
7914 if newline then pr "\n"
7916 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7917 and generate_c_call_args ?handle ?(decl = false) style =
7919 let comma = ref false in
7921 if !comma then pr ", ";
7926 | Some handle -> pr "%s" handle; comma := true
7931 pr "%s" (name_of_argt arg)
7933 (* For RBufferOut calls, add implicit &size parameter. *)
7935 match fst style with
7943 (* Generate the OCaml bindings interface. *)
7944 and generate_ocaml_mli () =
7945 generate_header OCamlStyle LGPLv2plus;
7948 (** For API documentation you should refer to the C API
7949 in the guestfs(3) manual page. The OCaml API uses almost
7950 exactly the same calls. *)
7953 (** A [guestfs_h] handle. *)
7955 exception Error of string
7956 (** This exception is raised when there is an error. *)
7958 exception Handle_closed of string
7959 (** This exception is raised if you use a {!Guestfs.t} handle
7960 after calling {!close} on it. The string is the name of
7963 val create : unit -> t
7964 (** Create a {!Guestfs.t} handle. *)
7966 val close : t -> unit
7967 (** Close the {!Guestfs.t} handle and free up all resources used
7970 Handles are closed by the garbage collector when they become
7971 unreferenced, but callers can call this in order to provide
7972 predictable cleanup. *)
7975 generate_ocaml_structure_decls ();
7979 fun (name, style, _, _, _, shortdesc, _) ->
7980 generate_ocaml_prototype name style;
7981 pr "(** %s *)\n" shortdesc;
7983 ) all_functions_sorted
7985 (* Generate the OCaml bindings implementation. *)
7986 and generate_ocaml_ml () =
7987 generate_header OCamlStyle LGPLv2plus;
7992 exception Error of string
7993 exception Handle_closed of string
7995 external create : unit -> t = \"ocaml_guestfs_create\"
7996 external close : t -> unit = \"ocaml_guestfs_close\"
7998 (* Give the exceptions names, so they can be raised from the C code. *)
8000 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8001 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8005 generate_ocaml_structure_decls ();
8009 fun (name, style, _, _, _, shortdesc, _) ->
8010 generate_ocaml_prototype ~is_external:true name style;
8011 ) all_functions_sorted
8013 (* Generate the OCaml bindings C implementation. *)
8014 and generate_ocaml_c () =
8015 generate_header CStyle LGPLv2plus;
8022 #include <caml/config.h>
8023 #include <caml/alloc.h>
8024 #include <caml/callback.h>
8025 #include <caml/fail.h>
8026 #include <caml/memory.h>
8027 #include <caml/mlvalues.h>
8028 #include <caml/signals.h>
8030 #include <guestfs.h>
8032 #include \"guestfs_c.h\"
8034 /* Copy a hashtable of string pairs into an assoc-list. We return
8035 * the list in reverse order, but hashtables aren't supposed to be
8038 static CAMLprim value
8039 copy_table (char * const * argv)
8042 CAMLlocal5 (rv, pairv, kv, vv, cons);
8046 for (i = 0; argv[i] != NULL; i += 2) {
8047 kv = caml_copy_string (argv[i]);
8048 vv = caml_copy_string (argv[i+1]);
8049 pairv = caml_alloc (2, 0);
8050 Store_field (pairv, 0, kv);
8051 Store_field (pairv, 1, vv);
8052 cons = caml_alloc (2, 0);
8053 Store_field (cons, 1, rv);
8055 Store_field (cons, 0, pairv);
8063 (* Struct copy functions. *)
8065 let emit_ocaml_copy_list_function typ =
8066 pr "static CAMLprim value\n";
8067 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8069 pr " CAMLparam0 ();\n";
8070 pr " CAMLlocal2 (rv, v);\n";
8071 pr " unsigned int i;\n";
8073 pr " if (%ss->len == 0)\n" typ;
8074 pr " CAMLreturn (Atom (0));\n";
8076 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8077 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8078 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8079 pr " caml_modify (&Field (rv, i), v);\n";
8081 pr " CAMLreturn (rv);\n";
8089 let has_optpercent_col =
8090 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8092 pr "static CAMLprim value\n";
8093 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8095 pr " CAMLparam0 ();\n";
8096 if has_optpercent_col then
8097 pr " CAMLlocal3 (rv, v, v2);\n"
8099 pr " CAMLlocal2 (rv, v);\n";
8101 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8106 pr " v = caml_copy_string (%s->%s);\n" typ name
8108 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8109 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8112 pr " v = caml_alloc_string (32);\n";
8113 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8114 | name, (FBytes|FInt64|FUInt64) ->
8115 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8116 | name, (FInt32|FUInt32) ->
8117 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8118 | name, FOptPercent ->
8119 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8120 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8121 pr " v = caml_alloc (1, 0);\n";
8122 pr " Store_field (v, 0, v2);\n";
8123 pr " } else /* None */\n";
8124 pr " v = Val_int (0);\n";
8126 pr " v = Val_int (%s->%s);\n" typ name
8128 pr " Store_field (rv, %d, v);\n" i
8130 pr " CAMLreturn (rv);\n";
8135 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8138 | typ, (RStructListOnly | RStructAndList) ->
8139 (* generate the function for typ *)
8140 emit_ocaml_copy_list_function typ
8141 | typ, _ -> () (* empty *)
8142 ) (rstructs_used_by all_functions);
8146 fun (name, style, _, _, _, _, _) ->
8147 pr "/* Automatically generated wrapper for function\n";
8149 generate_ocaml_prototype name style;
8154 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8156 let needs_extra_vs =
8157 match fst style with RConstOptString _ -> true | _ -> false in
8159 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8160 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8161 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8164 pr "CAMLprim value\n";
8165 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8166 List.iter (pr ", value %s") (List.tl params);
8171 | [p1; p2; p3; p4; p5] ->
8172 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8173 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8174 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8175 pr " CAMLxparam%d (%s);\n"
8176 (List.length rest) (String.concat ", " rest)
8178 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8180 if not needs_extra_vs then
8181 pr " CAMLlocal1 (rv);\n"
8183 pr " CAMLlocal3 (rv, v, v2);\n";
8186 pr " guestfs_h *g = Guestfs_val (gv);\n";
8187 pr " if (g == NULL)\n";
8188 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8194 | Device n | Dev_or_Path n
8198 pr " const char *%s = String_val (%sv);\n" n n
8200 pr " const char *%s =\n" n;
8201 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8203 | StringList n | DeviceList n ->
8204 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8206 pr " int %s = Bool_val (%sv);\n" n n
8208 pr " int %s = Int_val (%sv);\n" n n
8210 pr " int64_t %s = Int64_val (%sv);\n" n n
8213 match fst style with
8214 | RErr -> pr " int r;\n"; "-1"
8215 | RInt _ -> pr " int r;\n"; "-1"
8216 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8217 | RBool _ -> pr " int r;\n"; "-1"
8218 | RConstString _ | RConstOptString _ ->
8219 pr " const char *r;\n"; "NULL"
8220 | RString _ -> pr " char *r;\n"; "NULL"
8225 | RStruct (_, typ) ->
8226 pr " struct guestfs_%s *r;\n" typ; "NULL"
8227 | RStructList (_, typ) ->
8228 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8235 pr " size_t size;\n";
8239 pr " caml_enter_blocking_section ();\n";
8240 pr " r = guestfs_%s " name;
8241 generate_c_call_args ~handle:"g" style;
8243 pr " caml_leave_blocking_section ();\n";
8247 | StringList n | DeviceList n ->
8248 pr " ocaml_guestfs_free_strings (%s);\n" n;
8249 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8250 | Bool _ | Int _ | Int64 _
8251 | FileIn _ | FileOut _ -> ()
8254 pr " if (r == %s)\n" error_code;
8255 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8258 (match fst style with
8259 | RErr -> pr " rv = Val_unit;\n"
8260 | RInt _ -> pr " rv = Val_int (r);\n"
8262 pr " rv = caml_copy_int64 (r);\n"
8263 | RBool _ -> pr " rv = Val_bool (r);\n"
8265 pr " rv = caml_copy_string (r);\n"
8266 | RConstOptString _ ->
8267 pr " if (r) { /* Some string */\n";
8268 pr " v = caml_alloc (1, 0);\n";
8269 pr " v2 = caml_copy_string (r);\n";
8270 pr " Store_field (v, 0, v2);\n";
8271 pr " } else /* None */\n";
8272 pr " v = Val_int (0);\n";
8274 pr " rv = caml_copy_string (r);\n";
8277 pr " rv = caml_copy_string_array ((const char **) r);\n";
8278 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8280 | RStruct (_, typ) ->
8281 pr " rv = copy_%s (r);\n" typ;
8282 pr " guestfs_free_%s (r);\n" typ;
8283 | RStructList (_, typ) ->
8284 pr " rv = copy_%s_list (r);\n" typ;
8285 pr " guestfs_free_%s_list (r);\n" typ;
8287 pr " rv = copy_table (r);\n";
8288 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8291 pr " rv = caml_alloc_string (size);\n";
8292 pr " memcpy (String_val (rv), r, size);\n";
8295 pr " CAMLreturn (rv);\n";
8299 if List.length params > 5 then (
8300 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8301 pr "CAMLprim value ";
8302 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8303 pr "CAMLprim value\n";
8304 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8306 pr " return ocaml_guestfs_%s (argv[0]" name;
8307 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8312 ) all_functions_sorted
8314 and generate_ocaml_structure_decls () =
8317 pr "type %s = {\n" typ;
8320 | name, FString -> pr " %s : string;\n" name
8321 | name, FBuffer -> pr " %s : string;\n" name
8322 | name, FUUID -> pr " %s : string;\n" name
8323 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8324 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8325 | name, FChar -> pr " %s : char;\n" name
8326 | name, FOptPercent -> pr " %s : float option;\n" name
8332 and generate_ocaml_prototype ?(is_external = false) name style =
8333 if is_external then pr "external " else pr "val ";
8334 pr "%s : t -> " name;
8337 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8338 | OptString _ -> pr "string option -> "
8339 | StringList _ | DeviceList _ -> pr "string array -> "
8340 | Bool _ -> pr "bool -> "
8341 | Int _ -> pr "int -> "
8342 | Int64 _ -> pr "int64 -> "
8344 (match fst style with
8345 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8346 | RInt _ -> pr "int"
8347 | RInt64 _ -> pr "int64"
8348 | RBool _ -> pr "bool"
8349 | RConstString _ -> pr "string"
8350 | RConstOptString _ -> pr "string option"
8351 | RString _ | RBufferOut _ -> pr "string"
8352 | RStringList _ -> pr "string array"
8353 | RStruct (_, typ) -> pr "%s" typ
8354 | RStructList (_, typ) -> pr "%s array" typ
8355 | RHashtable _ -> pr "(string * string) list"
8357 if is_external then (
8359 if List.length (snd style) + 1 > 5 then
8360 pr "\"ocaml_guestfs_%s_byte\" " name;
8361 pr "\"ocaml_guestfs_%s\"" name
8365 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8366 and generate_perl_xs () =
8367 generate_header CStyle LGPLv2plus;
8370 #include \"EXTERN.h\"
8374 #include <guestfs.h>
8377 #define PRId64 \"lld\"
8381 my_newSVll(long long val) {
8382 #ifdef USE_64_BIT_ALL
8383 return newSViv(val);
8387 len = snprintf(buf, 100, \"%%\" PRId64, val);
8388 return newSVpv(buf, len);
8393 #define PRIu64 \"llu\"
8397 my_newSVull(unsigned long long val) {
8398 #ifdef USE_64_BIT_ALL
8399 return newSVuv(val);
8403 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8404 return newSVpv(buf, len);
8408 /* http://www.perlmonks.org/?node_id=680842 */
8410 XS_unpack_charPtrPtr (SV *arg) {
8415 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8416 croak (\"array reference expected\");
8418 av = (AV *)SvRV (arg);
8419 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8421 croak (\"malloc failed\");
8423 for (i = 0; i <= av_len (av); i++) {
8424 SV **elem = av_fetch (av, i, 0);
8426 if (!elem || !*elem)
8427 croak (\"missing element in list\");
8429 ret[i] = SvPV_nolen (*elem);
8437 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8444 RETVAL = guestfs_create ();
8446 croak (\"could not create guestfs handle\");
8447 guestfs_set_error_handler (RETVAL, NULL, NULL);
8460 fun (name, style, _, _, _, _, _) ->
8461 (match fst style with
8462 | RErr -> pr "void\n"
8463 | RInt _ -> pr "SV *\n"
8464 | RInt64 _ -> pr "SV *\n"
8465 | RBool _ -> pr "SV *\n"
8466 | RConstString _ -> pr "SV *\n"
8467 | RConstOptString _ -> pr "SV *\n"
8468 | RString _ -> pr "SV *\n"
8469 | RBufferOut _ -> pr "SV *\n"
8471 | RStruct _ | RStructList _
8473 pr "void\n" (* all lists returned implictly on the stack *)
8475 (* Call and arguments. *)
8477 generate_c_call_args ~handle:"g" ~decl:true style;
8479 pr " guestfs_h *g;\n";
8483 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8486 (* http://www.perlmonks.org/?node_id=554277
8487 * Note that the implicit handle argument means we have
8488 * to add 1 to the ST(x) operator.
8490 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8491 | StringList n | DeviceList n -> pr " char **%s;\n" n
8492 | Bool n -> pr " int %s;\n" n
8493 | Int n -> pr " int %s;\n" n
8494 | Int64 n -> pr " int64_t %s;\n" n
8497 let do_cleanups () =
8500 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8501 | Bool _ | Int _ | Int64 _
8502 | FileIn _ | FileOut _ -> ()
8503 | StringList n | DeviceList n -> pr " free (%s);\n" n
8508 (match fst style with
8513 pr " r = guestfs_%s " name;
8514 generate_c_call_args ~handle:"g" style;
8517 pr " if (r == -1)\n";
8518 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8524 pr " %s = guestfs_%s " n name;
8525 generate_c_call_args ~handle:"g" style;
8528 pr " if (%s == -1)\n" n;
8529 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8530 pr " RETVAL = newSViv (%s);\n" n;
8535 pr " int64_t %s;\n" n;
8537 pr " %s = guestfs_%s " n name;
8538 generate_c_call_args ~handle:"g" style;
8541 pr " if (%s == -1)\n" n;
8542 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8543 pr " RETVAL = my_newSVll (%s);\n" n;
8548 pr " const char *%s;\n" n;
8550 pr " %s = guestfs_%s " n name;
8551 generate_c_call_args ~handle:"g" style;
8554 pr " if (%s == NULL)\n" n;
8555 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8556 pr " RETVAL = newSVpv (%s, 0);\n" n;
8559 | RConstOptString n ->
8561 pr " const char *%s;\n" n;
8563 pr " %s = guestfs_%s " n name;
8564 generate_c_call_args ~handle:"g" style;
8567 pr " if (%s == NULL)\n" n;
8568 pr " RETVAL = &PL_sv_undef;\n";
8570 pr " RETVAL = newSVpv (%s, 0);\n" n;
8575 pr " char *%s;\n" n;
8577 pr " %s = guestfs_%s " n name;
8578 generate_c_call_args ~handle:"g" style;
8581 pr " if (%s == NULL)\n" n;
8582 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8583 pr " RETVAL = newSVpv (%s, 0);\n" n;
8584 pr " free (%s);\n" n;
8587 | RStringList n | RHashtable n ->
8589 pr " char **%s;\n" n;
8592 pr " %s = guestfs_%s " n name;
8593 generate_c_call_args ~handle:"g" style;
8596 pr " if (%s == NULL)\n" n;
8597 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8598 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8599 pr " EXTEND (SP, n);\n";
8600 pr " for (i = 0; i < n; ++i) {\n";
8601 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8602 pr " free (%s[i]);\n" n;
8604 pr " free (%s);\n" n;
8605 | RStruct (n, typ) ->
8606 let cols = cols_of_struct typ in
8607 generate_perl_struct_code typ cols name style n do_cleanups
8608 | RStructList (n, typ) ->
8609 let cols = cols_of_struct typ in
8610 generate_perl_struct_list_code typ cols name style n do_cleanups
8613 pr " char *%s;\n" n;
8614 pr " size_t size;\n";
8616 pr " %s = guestfs_%s " n name;
8617 generate_c_call_args ~handle:"g" style;
8620 pr " if (%s == NULL)\n" n;
8621 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8622 pr " RETVAL = newSVpvn (%s, size);\n" n;
8623 pr " free (%s);\n" n;
8631 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8633 pr " struct guestfs_%s_list *%s;\n" typ n;
8637 pr " %s = guestfs_%s " n name;
8638 generate_c_call_args ~handle:"g" style;
8641 pr " if (%s == NULL)\n" n;
8642 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8643 pr " EXTEND (SP, %s->len);\n" n;
8644 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8645 pr " hv = newHV ();\n";
8649 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8650 name (String.length name) n name
8652 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8653 name (String.length name) n name
8655 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8656 name (String.length name) n name n name
8657 | name, (FBytes|FUInt64) ->
8658 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8659 name (String.length name) n name
8661 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8662 name (String.length name) n name
8663 | name, (FInt32|FUInt32) ->
8664 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8665 name (String.length name) n name
8667 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8668 name (String.length name) n name
8669 | name, FOptPercent ->
8670 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8671 name (String.length name) n name
8673 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8675 pr " guestfs_free_%s_list (%s);\n" typ n
8677 and generate_perl_struct_code typ cols name style n do_cleanups =
8679 pr " struct guestfs_%s *%s;\n" typ n;
8681 pr " %s = guestfs_%s " n name;
8682 generate_c_call_args ~handle:"g" style;
8685 pr " if (%s == NULL)\n" n;
8686 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8687 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8689 fun ((name, _) as col) ->
8690 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8694 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8697 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8700 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8702 | name, (FBytes|FUInt64) ->
8703 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8706 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8708 | name, (FInt32|FUInt32) ->
8709 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8712 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8714 | name, FOptPercent ->
8715 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8718 pr " free (%s);\n" n
8720 (* Generate Sys/Guestfs.pm. *)
8721 and generate_perl_pm () =
8722 generate_header HashStyle LGPLv2plus;
8729 Sys::Guestfs - Perl bindings for libguestfs
8735 my $h = Sys::Guestfs->new ();
8736 $h->add_drive ('guest.img');
8738 $h->mount ('/dev/sda1', '/');
8739 $h->touch ('/hello');
8744 The C<Sys::Guestfs> module provides a Perl XS binding to the
8745 libguestfs API for examining and modifying virtual machine
8748 Amongst the things this is good for: making batch configuration
8749 changes to guests, getting disk used/free statistics (see also:
8750 virt-df), migrating between virtualization systems (see also:
8751 virt-p2v), performing partial backups, performing partial guest
8752 clones, cloning guests and changing registry/UUID/hostname info, and
8755 Libguestfs uses Linux kernel and qemu code, and can access any type of
8756 guest filesystem that Linux and qemu can, including but not limited
8757 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8758 schemes, qcow, qcow2, vmdk.
8760 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8761 LVs, what filesystem is in each LV, etc.). It can also run commands
8762 in the context of the guest. Also you can access filesystems over
8765 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8766 functions for using libguestfs from Perl, including integration
8771 All errors turn into calls to C<croak> (see L<Carp(3)>).
8779 package Sys::Guestfs;
8785 XSLoader::load ('Sys::Guestfs');
8787 =item $h = Sys::Guestfs->new ();
8789 Create a new guestfs handle.
8795 my $class = ref ($proto) || $proto;
8797 my $self = Sys::Guestfs::_create ();
8798 bless $self, $class;
8804 (* Actions. We only need to print documentation for these as
8805 * they are pulled in from the XS code automatically.
8808 fun (name, style, _, flags, _, _, longdesc) ->
8809 if not (List.mem NotInDocs flags) then (
8810 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8812 generate_perl_prototype name style;
8814 pr "%s\n\n" longdesc;
8815 if List.mem ProtocolLimitWarning flags then
8816 pr "%s\n\n" protocol_limit_warning;
8817 if List.mem DangerWillRobinson flags then
8818 pr "%s\n\n" danger_will_robinson;
8819 match deprecation_notice flags with
8821 | Some txt -> pr "%s\n\n" txt
8823 ) all_functions_sorted;
8835 Copyright (C) %s Red Hat Inc.
8839 Please see the file COPYING.LIB for the full license.
8845 L<http://libguestfs.org>,
8846 L<Sys::Guestfs::Lib(3)>.
8851 and generate_perl_prototype name style =
8852 (match fst style with
8860 | RBufferOut n -> pr "$%s = " n
8862 | RHashtable n -> pr "%%%s = " n
8864 | RStructList (n,_) -> pr "@%s = " n
8867 let comma = ref false in
8870 if !comma then pr ", ";
8873 | Pathname n | Device n | Dev_or_Path n | String n
8874 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8876 | StringList n | DeviceList n ->
8881 (* Generate Python C module. *)
8882 and generate_python_c () =
8883 generate_header CStyle LGPLv2plus;
8892 #include \"guestfs.h\"
8900 get_handle (PyObject *obj)
8903 assert (obj != Py_None);
8904 return ((Pyguestfs_Object *) obj)->g;
8908 put_handle (guestfs_h *g)
8912 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8915 /* This list should be freed (but not the strings) after use. */
8917 get_string_list (PyObject *obj)
8924 if (!PyList_Check (obj)) {
8925 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8929 len = PyList_Size (obj);
8930 r = malloc (sizeof (char *) * (len+1));
8932 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8936 for (i = 0; i < len; ++i)
8937 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8944 put_string_list (char * const * const argv)
8949 for (argc = 0; argv[argc] != NULL; ++argc)
8952 list = PyList_New (argc);
8953 for (i = 0; i < argc; ++i)
8954 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8960 put_table (char * const * const argv)
8962 PyObject *list, *item;
8965 for (argc = 0; argv[argc] != NULL; ++argc)
8968 list = PyList_New (argc >> 1);
8969 for (i = 0; i < argc; i += 2) {
8970 item = PyTuple_New (2);
8971 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8972 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8973 PyList_SetItem (list, i >> 1, item);
8980 free_strings (char **argv)
8984 for (argc = 0; argv[argc] != NULL; ++argc)
8990 py_guestfs_create (PyObject *self, PyObject *args)
8994 g = guestfs_create ();
8996 PyErr_SetString (PyExc_RuntimeError,
8997 \"guestfs.create: failed to allocate handle\");
9000 guestfs_set_error_handler (g, NULL, NULL);
9001 return put_handle (g);
9005 py_guestfs_close (PyObject *self, PyObject *args)
9010 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9012 g = get_handle (py_g);
9016 Py_INCREF (Py_None);
9022 let emit_put_list_function typ =
9023 pr "static PyObject *\n";
9024 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9026 pr " PyObject *list;\n";
9029 pr " list = PyList_New (%ss->len);\n" typ;
9030 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9031 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9032 pr " return list;\n";
9037 (* Structures, turned into Python dictionaries. *)
9040 pr "static PyObject *\n";
9041 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9043 pr " PyObject *dict;\n";
9045 pr " dict = PyDict_New ();\n";
9049 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9050 pr " PyString_FromString (%s->%s));\n"
9053 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9054 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9057 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9058 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9060 | name, (FBytes|FUInt64) ->
9061 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9062 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9065 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9066 pr " PyLong_FromLongLong (%s->%s));\n"
9069 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9070 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9073 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9074 pr " PyLong_FromLong (%s->%s));\n"
9076 | name, FOptPercent ->
9077 pr " if (%s->%s >= 0)\n" typ name;
9078 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9079 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9082 pr " Py_INCREF (Py_None);\n";
9083 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9086 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9087 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9089 pr " return dict;\n";
9095 (* Emit a put_TYPE_list function definition only if that function is used. *)
9098 | typ, (RStructListOnly | RStructAndList) ->
9099 (* generate the function for typ *)
9100 emit_put_list_function typ
9101 | typ, _ -> () (* empty *)
9102 ) (rstructs_used_by all_functions);
9104 (* Python wrapper functions. *)
9106 fun (name, style, _, _, _, _, _) ->
9107 pr "static PyObject *\n";
9108 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9111 pr " PyObject *py_g;\n";
9112 pr " guestfs_h *g;\n";
9113 pr " PyObject *py_r;\n";
9116 match fst style with
9117 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9118 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9119 | RConstString _ | RConstOptString _ ->
9120 pr " const char *r;\n"; "NULL"
9121 | RString _ -> pr " char *r;\n"; "NULL"
9122 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9123 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9124 | RStructList (_, typ) ->
9125 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9128 pr " size_t size;\n";
9133 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9134 pr " const char *%s;\n" n
9135 | OptString n -> pr " const char *%s;\n" n
9136 | StringList n | DeviceList n ->
9137 pr " PyObject *py_%s;\n" n;
9138 pr " char **%s;\n" n
9139 | Bool n -> pr " int %s;\n" n
9140 | Int n -> pr " int %s;\n" n
9141 | Int64 n -> pr " long long %s;\n" n
9146 (* Convert the parameters. *)
9147 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9150 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9151 | OptString _ -> pr "z"
9152 | StringList _ | DeviceList _ -> pr "O"
9153 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9155 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9156 * emulate C's int/long/long long in Python?
9159 pr ":guestfs_%s\",\n" name;
9163 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9164 | OptString n -> pr ", &%s" n
9165 | StringList n | DeviceList n -> pr ", &py_%s" n
9166 | Bool n -> pr ", &%s" n
9167 | Int n -> pr ", &%s" n
9168 | Int64 n -> pr ", &%s" n
9172 pr " return NULL;\n";
9174 pr " g = get_handle (py_g);\n";
9177 | Pathname _ | Device _ | Dev_or_Path _ | String _
9178 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9179 | StringList n | DeviceList n ->
9180 pr " %s = get_string_list (py_%s);\n" n n;
9181 pr " if (!%s) return NULL;\n" n
9186 pr " r = guestfs_%s " name;
9187 generate_c_call_args ~handle:"g" style;
9192 | Pathname _ | Device _ | Dev_or_Path _ | String _
9193 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9194 | StringList n | DeviceList n ->
9195 pr " free (%s);\n" n
9198 pr " if (r == %s) {\n" error_code;
9199 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9200 pr " return NULL;\n";
9204 (match fst style with
9206 pr " Py_INCREF (Py_None);\n";
9207 pr " py_r = Py_None;\n"
9209 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9210 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9211 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9212 | RConstOptString _ ->
9214 pr " py_r = PyString_FromString (r);\n";
9216 pr " Py_INCREF (Py_None);\n";
9217 pr " py_r = Py_None;\n";
9220 pr " py_r = PyString_FromString (r);\n";
9223 pr " py_r = put_string_list (r);\n";
9224 pr " free_strings (r);\n"
9225 | RStruct (_, typ) ->
9226 pr " py_r = put_%s (r);\n" typ;
9227 pr " guestfs_free_%s (r);\n" typ
9228 | RStructList (_, typ) ->
9229 pr " py_r = put_%s_list (r);\n" typ;
9230 pr " guestfs_free_%s_list (r);\n" typ
9232 pr " py_r = put_table (r);\n";
9233 pr " free_strings (r);\n"
9235 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9239 pr " return py_r;\n";
9244 (* Table of functions. *)
9245 pr "static PyMethodDef methods[] = {\n";
9246 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9247 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9249 fun (name, _, _, _, _, _, _) ->
9250 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9253 pr " { NULL, NULL, 0, NULL }\n";
9257 (* Init function. *)
9260 initlibguestfsmod (void)
9262 static int initialized = 0;
9264 if (initialized) return;
9265 Py_InitModule ((char *) \"libguestfsmod\", methods);
9270 (* Generate Python module. *)
9271 and generate_python_py () =
9272 generate_header HashStyle LGPLv2plus;
9275 u\"\"\"Python bindings for libguestfs
9278 g = guestfs.GuestFS ()
9279 g.add_drive (\"guest.img\")
9281 parts = g.list_partitions ()
9283 The guestfs module provides a Python binding to the libguestfs API
9284 for examining and modifying virtual machine disk images.
9286 Amongst the things this is good for: making batch configuration
9287 changes to guests, getting disk used/free statistics (see also:
9288 virt-df), migrating between virtualization systems (see also:
9289 virt-p2v), performing partial backups, performing partial guest
9290 clones, cloning guests and changing registry/UUID/hostname info, and
9293 Libguestfs uses Linux kernel and qemu code, and can access any type of
9294 guest filesystem that Linux and qemu can, including but not limited
9295 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9296 schemes, qcow, qcow2, vmdk.
9298 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9299 LVs, what filesystem is in each LV, etc.). It can also run commands
9300 in the context of the guest. Also you can access filesystems over
9303 Errors which happen while using the API are turned into Python
9304 RuntimeError exceptions.
9306 To create a guestfs handle you usually have to perform the following
9309 # Create the handle, call add_drive at least once, and possibly
9310 # several times if the guest has multiple block devices:
9311 g = guestfs.GuestFS ()
9312 g.add_drive (\"guest.img\")
9314 # Launch the qemu subprocess and wait for it to become ready:
9317 # Now you can issue commands, for example:
9322 import libguestfsmod
9325 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9327 def __init__ (self):
9328 \"\"\"Create a new libguestfs handle.\"\"\"
9329 self._o = libguestfsmod.create ()
9332 libguestfsmod.close (self._o)
9337 fun (name, style, _, flags, _, _, longdesc) ->
9339 generate_py_call_args ~handle:"self" (snd style);
9342 if not (List.mem NotInDocs flags) then (
9343 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9345 match fst style with
9346 | RErr | RInt _ | RInt64 _ | RBool _
9347 | RConstOptString _ | RConstString _
9348 | RString _ | RBufferOut _ -> doc
9350 doc ^ "\n\nThis function returns a list of strings."
9351 | RStruct (_, typ) ->
9352 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9353 | RStructList (_, typ) ->
9354 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9356 doc ^ "\n\nThis function returns a dictionary." in
9358 if List.mem ProtocolLimitWarning flags then
9359 doc ^ "\n\n" ^ protocol_limit_warning
9362 if List.mem DangerWillRobinson flags then
9363 doc ^ "\n\n" ^ danger_will_robinson
9366 match deprecation_notice flags with
9368 | Some txt -> doc ^ "\n\n" ^ txt in
9369 let doc = pod2text ~width:60 name doc in
9370 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9371 let doc = String.concat "\n " doc in
9372 pr " u\"\"\"%s\"\"\"\n" doc;
9374 pr " return libguestfsmod.%s " name;
9375 generate_py_call_args ~handle:"self._o" (snd style);
9380 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9381 and generate_py_call_args ~handle args =
9383 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9386 (* Useful if you need the longdesc POD text as plain text. Returns a
9389 * Because this is very slow (the slowest part of autogeneration),
9390 * we memoize the results.
9392 and pod2text ~width name longdesc =
9393 let key = width, name, longdesc in
9394 try Hashtbl.find pod2text_memo key
9396 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9397 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9399 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9400 let chan = open_process_in cmd in
9401 let lines = ref [] in
9403 let line = input_line chan in
9404 if i = 1 then (* discard the first line of output *)
9407 let line = triml line in
9408 lines := line :: !lines;
9411 let lines = try loop 1 with End_of_file -> List.rev !lines in
9413 (match close_process_in chan with
9416 failwithf "pod2text: process exited with non-zero status (%d)" i
9417 | WSIGNALED i | WSTOPPED i ->
9418 failwithf "pod2text: process signalled or stopped by signal %d" i
9420 Hashtbl.add pod2text_memo key lines;
9421 pod2text_memo_updated ();
9424 (* Generate ruby bindings. *)
9425 and generate_ruby_c () =
9426 generate_header CStyle LGPLv2plus;
9434 #include \"guestfs.h\"
9436 #include \"extconf.h\"
9438 /* For Ruby < 1.9 */
9440 #define RARRAY_LEN(r) (RARRAY((r))->len)
9443 static VALUE m_guestfs; /* guestfs module */
9444 static VALUE c_guestfs; /* guestfs_h handle */
9445 static VALUE e_Error; /* used for all errors */
9447 static void ruby_guestfs_free (void *p)
9450 guestfs_close ((guestfs_h *) p);
9453 static VALUE ruby_guestfs_create (VALUE m)
9457 g = guestfs_create ();
9459 rb_raise (e_Error, \"failed to create guestfs handle\");
9461 /* Don't print error messages to stderr by default. */
9462 guestfs_set_error_handler (g, NULL, NULL);
9464 /* Wrap it, and make sure the close function is called when the
9467 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9470 static VALUE ruby_guestfs_close (VALUE gv)
9473 Data_Get_Struct (gv, guestfs_h, g);
9475 ruby_guestfs_free (g);
9476 DATA_PTR (gv) = NULL;
9484 fun (name, style, _, _, _, _, _) ->
9485 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9486 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9489 pr " guestfs_h *g;\n";
9490 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9492 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9498 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9499 pr " Check_Type (%sv, T_STRING);\n" n;
9500 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9502 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9503 pr " \"%s\", \"%s\");\n" n name
9505 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9506 | StringList n | DeviceList n ->
9507 pr " char **%s;\n" n;
9508 pr " Check_Type (%sv, T_ARRAY);\n" n;
9510 pr " int i, len;\n";
9511 pr " len = RARRAY_LEN (%sv);\n" n;
9512 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9514 pr " for (i = 0; i < len; ++i) {\n";
9515 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9516 pr " %s[i] = StringValueCStr (v);\n" n;
9518 pr " %s[len] = NULL;\n" n;
9521 pr " int %s = RTEST (%sv);\n" n n
9523 pr " int %s = NUM2INT (%sv);\n" n n
9525 pr " long long %s = NUM2LL (%sv);\n" n n
9530 match fst style with
9531 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9532 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9533 | RConstString _ | RConstOptString _ ->
9534 pr " const char *r;\n"; "NULL"
9535 | RString _ -> pr " char *r;\n"; "NULL"
9536 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9537 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9538 | RStructList (_, typ) ->
9539 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9542 pr " size_t size;\n";
9546 pr " r = guestfs_%s " name;
9547 generate_c_call_args ~handle:"g" style;
9552 | Pathname _ | Device _ | Dev_or_Path _ | String _
9553 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9554 | StringList n | DeviceList n ->
9555 pr " free (%s);\n" n
9558 pr " if (r == %s)\n" error_code;
9559 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9562 (match fst style with
9564 pr " return Qnil;\n"
9565 | RInt _ | RBool _ ->
9566 pr " return INT2NUM (r);\n"
9568 pr " return ULL2NUM (r);\n"
9570 pr " return rb_str_new2 (r);\n";
9571 | RConstOptString _ ->
9573 pr " return rb_str_new2 (r);\n";
9575 pr " return Qnil;\n";
9577 pr " VALUE rv = rb_str_new2 (r);\n";
9581 pr " int i, len = 0;\n";
9582 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9583 pr " VALUE rv = rb_ary_new2 (len);\n";
9584 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9585 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9586 pr " free (r[i]);\n";
9590 | RStruct (_, typ) ->
9591 let cols = cols_of_struct typ in
9592 generate_ruby_struct_code typ cols
9593 | RStructList (_, typ) ->
9594 let cols = cols_of_struct typ in
9595 generate_ruby_struct_list_code typ cols
9597 pr " VALUE rv = rb_hash_new ();\n";
9599 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9600 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9601 pr " free (r[i]);\n";
9602 pr " free (r[i+1]);\n";
9607 pr " VALUE rv = rb_str_new (r, size);\n";
9617 /* Initialize the module. */
9618 void Init__guestfs ()
9620 m_guestfs = rb_define_module (\"Guestfs\");
9621 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9622 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9624 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9625 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9628 (* Define the rest of the methods. *)
9630 fun (name, style, _, _, _, _, _) ->
9631 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9632 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9637 (* Ruby code to return a struct. *)
9638 and generate_ruby_struct_code typ cols =
9639 pr " VALUE rv = rb_hash_new ();\n";
9643 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9645 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9647 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9648 | name, (FBytes|FUInt64) ->
9649 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9651 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9653 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9655 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9656 | name, FOptPercent ->
9657 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9658 | name, FChar -> (* XXX wrong? *)
9659 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9661 pr " guestfs_free_%s (r);\n" typ;
9664 (* Ruby code to return a struct list. *)
9665 and generate_ruby_struct_list_code typ cols =
9666 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9668 pr " for (i = 0; i < r->len; ++i) {\n";
9669 pr " VALUE hv = rb_hash_new ();\n";
9673 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9675 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
9677 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9678 | name, (FBytes|FUInt64) ->
9679 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9681 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9683 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9685 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9686 | name, FOptPercent ->
9687 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9688 | name, FChar -> (* XXX wrong? *)
9689 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9691 pr " rb_ary_push (rv, hv);\n";
9693 pr " guestfs_free_%s_list (r);\n" typ;
9696 (* Generate Java bindings GuestFS.java file. *)
9697 and generate_java_java () =
9698 generate_header CStyle LGPLv2plus;
9701 package com.redhat.et.libguestfs;
9703 import java.util.HashMap;
9704 import com.redhat.et.libguestfs.LibGuestFSException;
9705 import com.redhat.et.libguestfs.PV;
9706 import com.redhat.et.libguestfs.VG;
9707 import com.redhat.et.libguestfs.LV;
9708 import com.redhat.et.libguestfs.Stat;
9709 import com.redhat.et.libguestfs.StatVFS;
9710 import com.redhat.et.libguestfs.IntBool;
9711 import com.redhat.et.libguestfs.Dirent;
9714 * The GuestFS object is a libguestfs handle.
9718 public class GuestFS {
9719 // Load the native code.
9721 System.loadLibrary (\"guestfs_jni\");
9725 * The native guestfs_h pointer.
9730 * Create a libguestfs handle.
9732 * @throws LibGuestFSException
9734 public GuestFS () throws LibGuestFSException
9738 private native long _create () throws LibGuestFSException;
9741 * Close a libguestfs handle.
9743 * You can also leave handles to be collected by the garbage
9744 * collector, but this method ensures that the resources used
9745 * by the handle are freed up immediately. If you call any
9746 * other methods after closing the handle, you will get an
9749 * @throws LibGuestFSException
9751 public void close () throws LibGuestFSException
9757 private native void _close (long g) throws LibGuestFSException;
9759 public void finalize () throws LibGuestFSException
9767 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9768 if not (List.mem NotInDocs flags); then (
9769 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9771 if List.mem ProtocolLimitWarning flags then
9772 doc ^ "\n\n" ^ protocol_limit_warning
9775 if List.mem DangerWillRobinson flags then
9776 doc ^ "\n\n" ^ danger_will_robinson
9779 match deprecation_notice flags with
9781 | Some txt -> doc ^ "\n\n" ^ txt in
9782 let doc = pod2text ~width:60 name doc in
9783 let doc = List.map ( (* RHBZ#501883 *)
9786 | nonempty -> nonempty
9788 let doc = String.concat "\n * " doc in
9791 pr " * %s\n" shortdesc;
9794 pr " * @throws LibGuestFSException\n";
9798 generate_java_prototype ~public:true ~semicolon:false name style;
9801 pr " if (g == 0)\n";
9802 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9805 if fst style <> RErr then pr "return ";
9807 generate_java_call_args ~handle:"g" (snd style);
9811 generate_java_prototype ~privat:true ~native:true name style;
9818 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9819 and generate_java_call_args ~handle args =
9821 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9824 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9825 ?(semicolon=true) name style =
9826 if privat then pr "private ";
9827 if public then pr "public ";
9828 if native then pr "native ";
9831 (match fst style with
9832 | RErr -> pr "void ";
9833 | RInt _ -> pr "int ";
9834 | RInt64 _ -> pr "long ";
9835 | RBool _ -> pr "boolean ";
9836 | RConstString _ | RConstOptString _ | RString _
9837 | RBufferOut _ -> pr "String ";
9838 | RStringList _ -> pr "String[] ";
9839 | RStruct (_, typ) ->
9840 let name = java_name_of_struct typ in
9842 | RStructList (_, typ) ->
9843 let name = java_name_of_struct typ in
9845 | RHashtable _ -> pr "HashMap<String,String> ";
9848 if native then pr "_%s " name else pr "%s " name;
9850 let needs_comma = ref false in
9859 if !needs_comma then pr ", ";
9860 needs_comma := true;
9864 | Device n | Dev_or_Path n
9870 | StringList n | DeviceList n ->
9881 pr " throws LibGuestFSException";
9882 if semicolon then pr ";"
9884 and generate_java_struct jtyp cols () =
9885 generate_header CStyle LGPLv2plus;
9888 package com.redhat.et.libguestfs;
9891 * Libguestfs %s structure.
9903 | name, FBuffer -> pr " public String %s;\n" name
9904 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9905 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9906 | name, FChar -> pr " public char %s;\n" name
9907 | name, FOptPercent ->
9908 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9909 pr " public float %s;\n" name
9914 and generate_java_c () =
9915 generate_header CStyle LGPLv2plus;
9922 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9923 #include \"guestfs.h\"
9925 /* Note that this function returns. The exception is not thrown
9926 * until after the wrapper function returns.
9929 throw_exception (JNIEnv *env, const char *msg)
9932 cl = (*env)->FindClass (env,
9933 \"com/redhat/et/libguestfs/LibGuestFSException\");
9934 (*env)->ThrowNew (env, cl, msg);
9937 JNIEXPORT jlong JNICALL
9938 Java_com_redhat_et_libguestfs_GuestFS__1create
9939 (JNIEnv *env, jobject obj)
9943 g = guestfs_create ();
9945 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9948 guestfs_set_error_handler (g, NULL, NULL);
9949 return (jlong) (long) g;
9952 JNIEXPORT void JNICALL
9953 Java_com_redhat_et_libguestfs_GuestFS__1close
9954 (JNIEnv *env, jobject obj, jlong jg)
9956 guestfs_h *g = (guestfs_h *) (long) jg;
9963 fun (name, style, _, _, _, _, _) ->
9965 (match fst style with
9966 | RErr -> pr "void ";
9967 | RInt _ -> pr "jint ";
9968 | RInt64 _ -> pr "jlong ";
9969 | RBool _ -> pr "jboolean ";
9970 | RConstString _ | RConstOptString _ | RString _
9971 | RBufferOut _ -> pr "jstring ";
9972 | RStruct _ | RHashtable _ ->
9974 | RStringList _ | RStructList _ ->
9978 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9979 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9981 pr " (JNIEnv *env, jobject obj, jlong jg";
9985 | Device n | Dev_or_Path n
9990 pr ", jstring j%s" n
9991 | StringList n | DeviceList n ->
9992 pr ", jobjectArray j%s" n
9994 pr ", jboolean j%s" n
10002 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10003 let error_code, no_ret =
10004 match fst style with
10005 | RErr -> pr " int r;\n"; "-1", ""
10007 | RInt _ -> pr " int r;\n"; "-1", "0"
10008 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10009 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10010 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10012 pr " jstring jr;\n";
10013 pr " char *r;\n"; "NULL", "NULL"
10015 pr " jobjectArray jr;\n";
10016 pr " int r_len;\n";
10017 pr " jclass cl;\n";
10018 pr " jstring jstr;\n";
10019 pr " char **r;\n"; "NULL", "NULL"
10020 | RStruct (_, typ) ->
10021 pr " jobject jr;\n";
10022 pr " jclass cl;\n";
10023 pr " jfieldID fl;\n";
10024 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10025 | RStructList (_, typ) ->
10026 pr " jobjectArray jr;\n";
10027 pr " jclass cl;\n";
10028 pr " jfieldID fl;\n";
10029 pr " jobject jfl;\n";
10030 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10031 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10033 pr " jstring jr;\n";
10035 pr " size_t size;\n";
10040 | Device n | Dev_or_Path n
10045 pr " const char *%s;\n" n
10046 | StringList n | DeviceList n ->
10047 pr " int %s_len;\n" n;
10048 pr " const char **%s;\n" n
10053 pr " int64_t %s;\n" n
10057 (match fst style with
10058 | RStringList _ | RStructList _ -> true
10059 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10060 | RConstOptString _
10061 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10062 List.exists (function
10063 | StringList _ -> true
10064 | DeviceList _ -> true
10065 | _ -> false) (snd style) in
10071 (* Get the parameters. *)
10075 | Device n | Dev_or_Path n
10079 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10081 (* This is completely undocumented, but Java null becomes
10082 * a NULL parameter.
10084 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10085 | StringList n | DeviceList n ->
10086 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10087 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10088 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10089 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10091 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10093 pr " %s[%s_len] = NULL;\n" n n;
10097 pr " %s = j%s;\n" n n
10100 (* Make the call. *)
10101 pr " r = guestfs_%s " name;
10102 generate_c_call_args ~handle:"g" style;
10105 (* Release the parameters. *)
10109 | Device n | Dev_or_Path n
10113 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10115 pr " if (j%s)\n" n;
10116 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10117 | StringList n | DeviceList n ->
10118 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10119 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10121 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10123 pr " free (%s);\n" n
10129 (* Check for errors. *)
10130 pr " if (r == %s) {\n" error_code;
10131 pr " throw_exception (env, guestfs_last_error (g));\n";
10132 pr " return %s;\n" no_ret;
10135 (* Return value. *)
10136 (match fst style with
10138 | RInt _ -> pr " return (jint) r;\n"
10139 | RBool _ -> pr " return (jboolean) r;\n"
10140 | RInt64 _ -> pr " return (jlong) r;\n"
10141 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10142 | RConstOptString _ ->
10143 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10145 pr " jr = (*env)->NewStringUTF (env, r);\n";
10149 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10150 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10151 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10152 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10153 pr " for (i = 0; i < r_len; ++i) {\n";
10154 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10155 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10156 pr " free (r[i]);\n";
10160 | RStruct (_, typ) ->
10161 let jtyp = java_name_of_struct typ in
10162 let cols = cols_of_struct typ in
10163 generate_java_struct_return typ jtyp cols
10164 | RStructList (_, typ) ->
10165 let jtyp = java_name_of_struct typ in
10166 let cols = cols_of_struct typ in
10167 generate_java_struct_list_return typ jtyp cols
10170 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10171 pr " return NULL;\n"
10173 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10182 and generate_java_struct_return typ jtyp cols =
10183 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10184 pr " jr = (*env)->AllocObject (env, cl);\n";
10188 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10189 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10192 pr " char s[33];\n";
10193 pr " memcpy (s, r->%s, 32);\n" name;
10194 pr " s[32] = 0;\n";
10195 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10196 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10200 pr " int len = r->%s_len;\n" name;
10201 pr " char s[len+1];\n";
10202 pr " memcpy (s, r->%s, len);\n" name;
10203 pr " s[len] = 0;\n";
10204 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10205 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10207 | name, (FBytes|FUInt64|FInt64) ->
10208 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10209 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10210 | name, (FUInt32|FInt32) ->
10211 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10212 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10213 | name, FOptPercent ->
10214 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10215 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10217 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10218 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10223 and generate_java_struct_list_return typ jtyp cols =
10224 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10225 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10226 pr " for (i = 0; i < r->len; ++i) {\n";
10227 pr " jfl = (*env)->AllocObject (env, cl);\n";
10231 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10232 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10235 pr " char s[33];\n";
10236 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10237 pr " s[32] = 0;\n";
10238 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10239 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10243 pr " int len = r->val[i].%s_len;\n" name;
10244 pr " char s[len+1];\n";
10245 pr " memcpy (s, r->val[i].%s, len);\n" name;
10246 pr " s[len] = 0;\n";
10247 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10248 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10250 | name, (FBytes|FUInt64|FInt64) ->
10251 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10252 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10253 | name, (FUInt32|FInt32) ->
10254 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10255 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10256 | name, FOptPercent ->
10257 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10258 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10260 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10261 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10263 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10265 pr " guestfs_free_%s_list (r);\n" typ;
10268 and generate_java_makefile_inc () =
10269 generate_header HashStyle GPLv2plus;
10271 pr "java_built_sources = \\\n";
10274 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10276 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10278 and generate_haskell_hs () =
10279 generate_header HaskellStyle LGPLv2plus;
10281 (* XXX We only know how to generate partial FFI for Haskell
10282 * at the moment. Please help out!
10284 let can_generate style =
10288 | RInt64 _, _ -> true
10290 | RConstString _, _
10291 | RConstOptString _, _
10297 | RBufferOut _, _ -> false in
10300 {-# INCLUDE <guestfs.h> #-}
10301 {-# LANGUAGE ForeignFunctionInterface #-}
10306 (* List out the names of the actions we want to export. *)
10308 fun (name, style, _, _, _, _, _) ->
10309 if can_generate style then pr ",\n %s" name
10315 -- Unfortunately some symbols duplicate ones already present
10316 -- in Prelude. We don't know which, so we hard-code a list
10318 import Prelude hiding (truncate)
10322 import Foreign.C.Types
10324 import Control.Exception
10325 import Data.Typeable
10327 data GuestfsS = GuestfsS -- represents the opaque C struct
10328 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10329 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10331 -- XXX define properly later XXX
10335 data IntBool = IntBool
10337 data StatVFS = StatVFS
10338 data Hashtable = Hashtable
10340 foreign import ccall unsafe \"guestfs_create\" c_create
10342 foreign import ccall unsafe \"&guestfs_close\" c_close
10343 :: FunPtr (GuestfsP -> IO ())
10344 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10345 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10347 create :: IO GuestfsH
10350 c_set_error_handler p nullPtr nullPtr
10351 h <- newForeignPtr c_close p
10354 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10355 :: GuestfsP -> IO CString
10357 -- last_error :: GuestfsH -> IO (Maybe String)
10358 -- last_error h = do
10359 -- str <- withForeignPtr h (\\p -> c_last_error p)
10360 -- maybePeek peekCString str
10362 last_error :: GuestfsH -> IO (String)
10364 str <- withForeignPtr h (\\p -> c_last_error p)
10365 if (str == nullPtr)
10366 then return \"no error\"
10367 else peekCString str
10371 (* Generate wrappers for each foreign function. *)
10373 fun (name, style, _, _, _, _, _) ->
10374 if can_generate style then (
10375 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10377 generate_haskell_prototype ~handle:"GuestfsP" style;
10381 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10383 pr "%s %s = do\n" name
10384 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10386 (* Convert pointer arguments using with* functions. *)
10391 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10392 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10393 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10394 | Bool _ | Int _ | Int64 _ -> ()
10396 (* Convert integer arguments. *)
10400 | Bool n -> sprintf "(fromBool %s)" n
10401 | Int n -> sprintf "(fromIntegral %s)" n
10402 | Int64 n -> sprintf "(fromIntegral %s)" n
10403 | FileIn n | FileOut n
10404 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10406 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10407 (String.concat " " ("p" :: args));
10408 (match fst style with
10409 | RErr | RInt _ | RInt64 _ | RBool _ ->
10410 pr " if (r == -1)\n";
10412 pr " err <- last_error h\n";
10414 | RConstString _ | RConstOptString _ | RString _
10415 | RStringList _ | RStruct _
10416 | RStructList _ | RHashtable _ | RBufferOut _ ->
10417 pr " if (r == nullPtr)\n";
10419 pr " err <- last_error h\n";
10422 (match fst style with
10424 pr " else return ()\n"
10426 pr " else return (fromIntegral r)\n"
10428 pr " else return (fromIntegral r)\n"
10430 pr " else return (toBool r)\n"
10432 | RConstOptString _
10439 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10445 and generate_haskell_prototype ~handle ?(hs = false) style =
10446 pr "%s -> " handle;
10447 let string = if hs then "String" else "CString" in
10448 let int = if hs then "Int" else "CInt" in
10449 let bool = if hs then "Bool" else "CInt" in
10450 let int64 = if hs then "Integer" else "Int64" in
10454 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10455 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10456 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10457 | Bool _ -> pr "%s" bool
10458 | Int _ -> pr "%s" int
10459 | Int64 _ -> pr "%s" int
10460 | FileIn _ -> pr "%s" string
10461 | FileOut _ -> pr "%s" string
10466 (match fst style with
10467 | RErr -> if not hs then pr "CInt"
10468 | RInt _ -> pr "%s" int
10469 | RInt64 _ -> pr "%s" int64
10470 | RBool _ -> pr "%s" bool
10471 | RConstString _ -> pr "%s" string
10472 | RConstOptString _ -> pr "Maybe %s" string
10473 | RString _ -> pr "%s" string
10474 | RStringList _ -> pr "[%s]" string
10475 | RStruct (_, typ) ->
10476 let name = java_name_of_struct typ in
10478 | RStructList (_, typ) ->
10479 let name = java_name_of_struct typ in
10481 | RHashtable _ -> pr "Hashtable"
10482 | RBufferOut _ -> pr "%s" string
10486 and generate_csharp () =
10487 generate_header CPlusPlusStyle LGPLv2plus;
10489 (* XXX Make this configurable by the C# assembly users. *)
10490 let library = "libguestfs.so.0" in
10493 // These C# bindings are highly experimental at present.
10495 // Firstly they only work on Linux (ie. Mono). In order to get them
10496 // to work on Windows (ie. .Net) you would need to port the library
10497 // itself to Windows first.
10499 // The second issue is that some calls are known to be incorrect and
10500 // can cause Mono to segfault. Particularly: calls which pass or
10501 // return string[], or return any structure value. This is because
10502 // we haven't worked out the correct way to do this from C#.
10504 // The third issue is that when compiling you get a lot of warnings.
10505 // We are not sure whether the warnings are important or not.
10507 // Fourthly we do not routinely build or test these bindings as part
10508 // of the make && make check cycle, which means that regressions might
10511 // Suggestions and patches are welcome.
10515 // gmcs Libguestfs.cs
10516 // mono Libguestfs.exe
10518 // (You'll probably want to add a Test class / static main function
10519 // otherwise this won't do anything useful).
10523 using System.Runtime.InteropServices;
10524 using System.Runtime.Serialization;
10525 using System.Collections;
10529 class Error : System.ApplicationException
10531 public Error (string message) : base (message) {}
10532 protected Error (SerializationInfo info, StreamingContext context) {}
10539 [DllImport (\"%s\")]
10540 static extern IntPtr guestfs_create ();
10544 _handle = guestfs_create ();
10545 if (_handle == IntPtr.Zero)
10546 throw new Error (\"could not create guestfs handle\");
10549 [DllImport (\"%s\")]
10550 static extern void guestfs_close (IntPtr h);
10554 guestfs_close (_handle);
10557 [DllImport (\"%s\")]
10558 static extern string guestfs_last_error (IntPtr h);
10560 " library library library;
10562 (* Generate C# structure bindings. We prefix struct names with
10563 * underscore because C# cannot have conflicting struct names and
10564 * method names (eg. "class stat" and "stat").
10568 pr " [StructLayout (LayoutKind.Sequential)]\n";
10569 pr " public class _%s {\n" typ;
10572 | name, FChar -> pr " char %s;\n" name
10573 | name, FString -> pr " string %s;\n" name
10575 pr " uint %s_len;\n" name;
10576 pr " string %s;\n" name
10578 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10579 pr " string %s;\n" name
10580 | name, FUInt32 -> pr " uint %s;\n" name
10581 | name, FInt32 -> pr " int %s;\n" name
10582 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10583 | name, FInt64 -> pr " long %s;\n" name
10584 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10590 (* Generate C# function bindings. *)
10592 fun (name, style, _, _, _, shortdesc, _) ->
10593 let rec csharp_return_type () =
10594 match fst style with
10596 | RBool n -> "bool"
10598 | RInt64 n -> "long"
10600 | RConstOptString n
10602 | RBufferOut n -> "string"
10603 | RStruct (_,n) -> "_" ^ n
10604 | RHashtable n -> "Hashtable"
10605 | RStringList n -> "string[]"
10606 | RStructList (_,n) -> sprintf "_%s[]" n
10608 and c_return_type () =
10609 match fst style with
10613 | RInt64 _ -> "long"
10615 | RConstOptString _
10617 | RBufferOut _ -> "string"
10618 | RStruct (_,n) -> "_" ^ n
10620 | RStringList _ -> "string[]"
10621 | RStructList (_,n) -> sprintf "_%s[]" n
10623 and c_error_comparison () =
10624 match fst style with
10628 | RInt64 _ -> "== -1"
10630 | RConstOptString _
10636 | RStructList (_,_) -> "== null"
10638 and generate_extern_prototype () =
10639 pr " static extern %s guestfs_%s (IntPtr h"
10640 (c_return_type ()) name;
10643 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10644 | FileIn n | FileOut n ->
10645 pr ", [In] string %s" n
10646 | StringList n | DeviceList n ->
10647 pr ", [In] string[] %s" n
10657 and generate_public_prototype () =
10658 pr " public %s %s (" (csharp_return_type ()) name;
10659 let comma = ref false in
10661 if !comma then pr ", ";
10666 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10667 | FileIn n | FileOut n ->
10668 next (); pr "string %s" n
10669 | StringList n | DeviceList n ->
10670 next (); pr "string[] %s" n
10672 next (); pr "bool %s" n
10674 next (); pr "int %s" n
10676 next (); pr "long %s" n
10680 and generate_call () =
10681 pr "guestfs_%s (_handle" name;
10682 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10686 pr " [DllImport (\"%s\")]\n" library;
10687 generate_extern_prototype ();
10689 pr " /// <summary>\n";
10690 pr " /// %s\n" shortdesc;
10691 pr " /// </summary>\n";
10692 generate_public_prototype ();
10694 pr " %s r;\n" (c_return_type ());
10697 pr " if (r %s)\n" (c_error_comparison ());
10698 pr " throw new Error (guestfs_last_error (_handle));\n";
10699 (match fst style with
10702 pr " return r != 0 ? true : false;\n"
10704 pr " Hashtable rr = new Hashtable ();\n";
10705 pr " for (int i = 0; i < r.Length; i += 2)\n";
10706 pr " rr.Add (r[i], r[i+1]);\n";
10708 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10709 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10715 ) all_functions_sorted;
10721 and generate_bindtests () =
10722 generate_header CStyle LGPLv2plus;
10726 #include <stdlib.h>
10727 #include <inttypes.h>
10728 #include <string.h>
10730 #include \"guestfs.h\"
10731 #include \"guestfs-internal.h\"
10732 #include \"guestfs-internal-actions.h\"
10733 #include \"guestfs_protocol.h\"
10735 #define error guestfs_error
10736 #define safe_calloc guestfs_safe_calloc
10737 #define safe_malloc guestfs_safe_malloc
10740 print_strings (char *const *argv)
10745 for (argc = 0; argv[argc] != NULL; ++argc) {
10746 if (argc > 0) printf (\", \");
10747 printf (\"\\\"%%s\\\"\", argv[argc]);
10752 /* The test0 function prints its parameters to stdout. */
10756 match test_functions with
10757 | [] -> assert false
10758 | test0 :: tests -> test0, tests in
10761 let (name, style, _, _, _, _, _) = test0 in
10762 generate_prototype ~extern:false ~semicolon:false ~newline:true
10763 ~handle:"g" ~prefix:"guestfs__" name style;
10768 | Device n | Dev_or_Path n
10771 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10772 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10773 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10774 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10775 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10776 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10778 pr " /* Java changes stdout line buffering so we need this: */\n";
10779 pr " fflush (stdout);\n";
10785 fun (name, style, _, _, _, _, _) ->
10786 if String.sub name (String.length name - 3) 3 <> "err" then (
10787 pr "/* Test normal return. */\n";
10788 generate_prototype ~extern:false ~semicolon:false ~newline:true
10789 ~handle:"g" ~prefix:"guestfs__" name style;
10791 (match fst style with
10796 pr " sscanf (val, \"%%d\", &r);\n";
10799 pr " int64_t r;\n";
10800 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10803 pr " return STREQ (val, \"true\");\n"
10805 | RConstOptString _ ->
10806 (* Can't return the input string here. Return a static
10807 * string so we ensure we get a segfault if the caller
10808 * tries to free it.
10810 pr " return \"static string\";\n"
10812 pr " return strdup (val);\n"
10814 pr " char **strs;\n";
10816 pr " sscanf (val, \"%%d\", &n);\n";
10817 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10818 pr " for (i = 0; i < n; ++i) {\n";
10819 pr " strs[i] = safe_malloc (g, 16);\n";
10820 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10822 pr " strs[n] = NULL;\n";
10823 pr " return strs;\n"
10824 | RStruct (_, typ) ->
10825 pr " struct guestfs_%s *r;\n" typ;
10826 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10828 | RStructList (_, typ) ->
10829 pr " struct guestfs_%s_list *r;\n" typ;
10830 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10831 pr " sscanf (val, \"%%d\", &r->len);\n";
10832 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10835 pr " char **strs;\n";
10837 pr " sscanf (val, \"%%d\", &n);\n";
10838 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10839 pr " for (i = 0; i < n; ++i) {\n";
10840 pr " strs[i*2] = safe_malloc (g, 16);\n";
10841 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10842 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10843 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10845 pr " strs[n*2] = NULL;\n";
10846 pr " return strs;\n"
10848 pr " return strdup (val);\n"
10853 pr "/* Test error return. */\n";
10854 generate_prototype ~extern:false ~semicolon:false ~newline:true
10855 ~handle:"g" ~prefix:"guestfs__" name style;
10857 pr " error (g, \"error\");\n";
10858 (match fst style with
10859 | RErr | RInt _ | RInt64 _ | RBool _ ->
10861 | RConstString _ | RConstOptString _
10862 | RString _ | RStringList _ | RStruct _
10866 pr " return NULL;\n"
10873 and generate_ocaml_bindtests () =
10874 generate_header OCamlStyle GPLv2plus;
10878 let g = Guestfs.create () in
10882 String.concat " " (
10885 | CallString s -> "\"" ^ s ^ "\""
10886 | CallOptString None -> "None"
10887 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10888 | CallStringList xs ->
10889 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10890 | CallInt i when i >= 0 -> string_of_int i
10891 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10892 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10893 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10894 | CallBool b -> string_of_bool b
10899 generate_lang_bindtests (
10900 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10903 pr "print_endline \"EOF\"\n"
10905 and generate_perl_bindtests () =
10906 pr "#!/usr/bin/perl -w\n";
10907 generate_header HashStyle GPLv2plus;
10914 my $g = Sys::Guestfs->new ();
10918 String.concat ", " (
10921 | CallString s -> "\"" ^ s ^ "\""
10922 | CallOptString None -> "undef"
10923 | CallOptString (Some s) -> sprintf "\"%s\"" s
10924 | CallStringList xs ->
10925 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10926 | CallInt i -> string_of_int i
10927 | CallInt64 i -> Int64.to_string i
10928 | CallBool b -> if b then "1" else "0"
10933 generate_lang_bindtests (
10934 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10937 pr "print \"EOF\\n\"\n"
10939 and generate_python_bindtests () =
10940 generate_header HashStyle GPLv2plus;
10945 g = guestfs.GuestFS ()
10949 String.concat ", " (
10952 | CallString s -> "\"" ^ s ^ "\""
10953 | CallOptString None -> "None"
10954 | CallOptString (Some s) -> sprintf "\"%s\"" s
10955 | CallStringList xs ->
10956 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10957 | CallInt i -> string_of_int i
10958 | CallInt64 i -> Int64.to_string i
10959 | CallBool b -> if b then "1" else "0"
10964 generate_lang_bindtests (
10965 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10968 pr "print \"EOF\"\n"
10970 and generate_ruby_bindtests () =
10971 generate_header HashStyle GPLv2plus;
10976 g = Guestfs::create()
10980 String.concat ", " (
10983 | CallString s -> "\"" ^ s ^ "\""
10984 | CallOptString None -> "nil"
10985 | CallOptString (Some s) -> sprintf "\"%s\"" s
10986 | CallStringList xs ->
10987 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10988 | CallInt i -> string_of_int i
10989 | CallInt64 i -> Int64.to_string i
10990 | CallBool b -> string_of_bool b
10995 generate_lang_bindtests (
10996 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10999 pr "print \"EOF\\n\"\n"
11001 and generate_java_bindtests () =
11002 generate_header CStyle GPLv2plus;
11005 import com.redhat.et.libguestfs.*;
11007 public class Bindtests {
11008 public static void main (String[] argv)
11011 GuestFS g = new GuestFS ();
11015 String.concat ", " (
11018 | CallString s -> "\"" ^ s ^ "\""
11019 | CallOptString None -> "null"
11020 | CallOptString (Some s) -> sprintf "\"%s\"" s
11021 | CallStringList xs ->
11023 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11024 | CallInt i -> string_of_int i
11025 | CallInt64 i -> Int64.to_string i
11026 | CallBool b -> string_of_bool b
11031 generate_lang_bindtests (
11032 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11036 System.out.println (\"EOF\");
11038 catch (Exception exn) {
11039 System.err.println (exn);
11046 and generate_haskell_bindtests () =
11047 generate_header HaskellStyle GPLv2plus;
11050 module Bindtests where
11051 import qualified Guestfs
11054 g <- Guestfs.create
11058 String.concat " " (
11061 | CallString s -> "\"" ^ s ^ "\""
11062 | CallOptString None -> "Nothing"
11063 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11064 | CallStringList xs ->
11065 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11066 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11067 | CallInt i -> string_of_int i
11068 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11069 | CallInt64 i -> Int64.to_string i
11070 | CallBool true -> "True"
11071 | CallBool false -> "False"
11076 generate_lang_bindtests (
11077 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11080 pr " putStrLn \"EOF\"\n"
11082 (* Language-independent bindings tests - we do it this way to
11083 * ensure there is parity in testing bindings across all languages.
11085 and generate_lang_bindtests call =
11086 call "test0" [CallString "abc"; CallOptString (Some "def");
11087 CallStringList []; CallBool false;
11088 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089 call "test0" [CallString "abc"; CallOptString None;
11090 CallStringList []; CallBool false;
11091 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092 call "test0" [CallString ""; CallOptString (Some "def");
11093 CallStringList []; CallBool false;
11094 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095 call "test0" [CallString ""; CallOptString (Some "");
11096 CallStringList []; CallBool false;
11097 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11098 call "test0" [CallString "abc"; CallOptString (Some "def");
11099 CallStringList ["1"]; CallBool false;
11100 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11101 call "test0" [CallString "abc"; CallOptString (Some "def");
11102 CallStringList ["1"; "2"]; CallBool false;
11103 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11104 call "test0" [CallString "abc"; CallOptString (Some "def");
11105 CallStringList ["1"]; CallBool true;
11106 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11107 call "test0" [CallString "abc"; CallOptString (Some "def");
11108 CallStringList ["1"]; CallBool false;
11109 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11110 call "test0" [CallString "abc"; CallOptString (Some "def");
11111 CallStringList ["1"]; CallBool false;
11112 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11113 call "test0" [CallString "abc"; CallOptString (Some "def");
11114 CallStringList ["1"]; CallBool false;
11115 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11116 call "test0" [CallString "abc"; CallOptString (Some "def");
11117 CallStringList ["1"]; CallBool false;
11118 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11119 call "test0" [CallString "abc"; CallOptString (Some "def");
11120 CallStringList ["1"]; CallBool false;
11121 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11122 call "test0" [CallString "abc"; CallOptString (Some "def");
11123 CallStringList ["1"]; CallBool false;
11124 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11126 (* XXX Add here tests of the return and error functions. *)
11128 (* Code to generator bindings for virt-inspector. Currently only
11129 * implemented for OCaml code (for virt-p2v 2.0).
11131 let rng_input = "inspector/virt-inspector.rng"
11133 (* Read the input file and parse it into internal structures. This is
11134 * by no means a complete RELAX NG parser, but is just enough to be
11135 * able to parse the specific input file.
11138 | Element of string * rng list (* <element name=name/> *)
11139 | Attribute of string * rng list (* <attribute name=name/> *)
11140 | Interleave of rng list (* <interleave/> *)
11141 | ZeroOrMore of rng (* <zeroOrMore/> *)
11142 | OneOrMore of rng (* <oneOrMore/> *)
11143 | Optional of rng (* <optional/> *)
11144 | Choice of string list (* <choice><value/>*</choice> *)
11145 | Value of string (* <value>str</value> *)
11146 | Text (* <text/> *)
11148 let rec string_of_rng = function
11149 | Element (name, xs) ->
11150 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11151 | Attribute (name, xs) ->
11152 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11153 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11154 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11155 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11156 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11157 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11158 | Value value -> "Value \"" ^ value ^ "\""
11161 and string_of_rng_list xs =
11162 String.concat ", " (List.map string_of_rng xs)
11164 let rec parse_rng ?defines context = function
11166 | Xml.Element ("element", ["name", name], children) :: rest ->
11167 Element (name, parse_rng ?defines context children)
11168 :: parse_rng ?defines context rest
11169 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11170 Attribute (name, parse_rng ?defines context children)
11171 :: parse_rng ?defines context rest
11172 | Xml.Element ("interleave", [], children) :: rest ->
11173 Interleave (parse_rng ?defines context children)
11174 :: parse_rng ?defines context rest
11175 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11176 let rng = parse_rng ?defines context [child] in
11178 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11180 failwithf "%s: <zeroOrMore> contains more than one child element"
11183 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11184 let rng = parse_rng ?defines context [child] in
11186 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11188 failwithf "%s: <oneOrMore> contains more than one child element"
11191 | Xml.Element ("optional", [], [child]) :: rest ->
11192 let rng = parse_rng ?defines context [child] in
11194 | [child] -> Optional child :: parse_rng ?defines context rest
11196 failwithf "%s: <optional> contains more than one child element"
11199 | Xml.Element ("choice", [], children) :: rest ->
11200 let values = List.map (
11201 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11203 failwithf "%s: can't handle anything except <value> in <choice>"
11207 :: parse_rng ?defines context rest
11208 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11209 Value value :: parse_rng ?defines context rest
11210 | Xml.Element ("text", [], []) :: rest ->
11211 Text :: parse_rng ?defines context rest
11212 | Xml.Element ("ref", ["name", name], []) :: rest ->
11213 (* Look up the reference. Because of limitations in this parser,
11214 * we can't handle arbitrarily nested <ref> yet. You can only
11215 * use <ref> from inside <start>.
11217 (match defines with
11219 failwithf "%s: contains <ref>, but no refs are defined yet" context
11221 let rng = StringMap.find name map in
11222 rng @ parse_rng ?defines context rest
11225 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11228 let xml = Xml.parse_file rng_input in
11230 | Xml.Element ("grammar", _,
11231 Xml.Element ("start", _, gram) :: defines) ->
11232 (* The <define/> elements are referenced in the <start> section,
11233 * so build a map of those first.
11235 let defines = List.fold_left (
11237 function Xml.Element ("define", ["name", name], defn) ->
11238 StringMap.add name defn map
11240 failwithf "%s: expected <define name=name/>" rng_input
11241 ) StringMap.empty defines in
11242 let defines = StringMap.mapi parse_rng defines in
11244 (* Parse the <start> clause, passing the defines. *)
11245 parse_rng ~defines "<start>" gram
11247 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11250 let name_of_field = function
11251 | Element (name, _) | Attribute (name, _)
11252 | ZeroOrMore (Element (name, _))
11253 | OneOrMore (Element (name, _))
11254 | Optional (Element (name, _)) -> name
11255 | Optional (Attribute (name, _)) -> name
11256 | Text -> (* an unnamed field in an element *)
11259 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11261 (* At the moment this function only generates OCaml types. However we
11262 * should parameterize it later so it can generate types/structs in a
11263 * variety of languages.
11265 let generate_types xs =
11266 (* A simple type is one that can be printed out directly, eg.
11267 * "string option". A complex type is one which has a name and has
11268 * to be defined via another toplevel definition, eg. a struct.
11270 * generate_type generates code for either simple or complex types.
11271 * In the simple case, it returns the string ("string option"). In
11272 * the complex case, it returns the name ("mountpoint"). In the
11273 * complex case it has to print out the definition before returning,
11274 * so it should only be called when we are at the beginning of a
11275 * new line (BOL context).
11277 let rec generate_type = function
11278 | Text -> (* string *)
11280 | Choice values -> (* [`val1|`val2|...] *)
11281 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11282 | ZeroOrMore rng -> (* <rng> list *)
11283 let t, is_simple = generate_type rng in
11284 t ^ " list (* 0 or more *)", is_simple
11285 | OneOrMore rng -> (* <rng> list *)
11286 let t, is_simple = generate_type rng in
11287 t ^ " list (* 1 or more *)", is_simple
11288 (* virt-inspector hack: bool *)
11289 | Optional (Attribute (name, [Value "1"])) ->
11291 | Optional rng -> (* <rng> list *)
11292 let t, is_simple = generate_type rng in
11293 t ^ " option", is_simple
11294 (* type name = { fields ... } *)
11295 | Element (name, fields) when is_attrs_interleave fields ->
11296 generate_type_struct name (get_attrs_interleave fields)
11297 | Element (name, [field]) (* type name = field *)
11298 | Attribute (name, [field]) ->
11299 let t, is_simple = generate_type field in
11300 if is_simple then (t, true)
11302 pr "type %s = %s\n" name t;
11305 | Element (name, fields) -> (* type name = { fields ... } *)
11306 generate_type_struct name fields
11308 failwithf "generate_type failed at: %s" (string_of_rng rng)
11310 and is_attrs_interleave = function
11311 | [Interleave _] -> true
11312 | Attribute _ :: fields -> is_attrs_interleave fields
11313 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11316 and get_attrs_interleave = function
11317 | [Interleave fields] -> fields
11318 | ((Attribute _) as field) :: fields
11319 | ((Optional (Attribute _)) as field) :: fields ->
11320 field :: get_attrs_interleave fields
11321 | _ -> assert false
11323 and generate_types xs =
11324 List.iter (fun x -> ignore (generate_type x)) xs
11326 and generate_type_struct name fields =
11327 (* Calculate the types of the fields first. We have to do this
11328 * before printing anything so we are still in BOL context.
11330 let types = List.map fst (List.map generate_type fields) in
11332 (* Special case of a struct containing just a string and another
11333 * field. Turn it into an assoc list.
11336 | ["string"; other] ->
11337 let fname1, fname2 =
11339 | [f1; f2] -> name_of_field f1, name_of_field f2
11340 | _ -> assert false in
11341 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11345 pr "type %s = {\n" name;
11347 fun (field, ftype) ->
11348 let fname = name_of_field field in
11349 pr " %s_%s : %s;\n" name fname ftype
11350 ) (List.combine fields types);
11352 (* Return the name of this type, and
11353 * false because it's not a simple type.
11360 let generate_parsers xs =
11361 (* As for generate_type above, generate_parser makes a parser for
11362 * some type, and returns the name of the parser it has generated.
11363 * Because it (may) need to print something, it should always be
11364 * called in BOL context.
11366 let rec generate_parser = function
11367 | Text -> (* string *)
11368 "string_child_or_empty"
11369 | Choice values -> (* [`val1|`val2|...] *)
11370 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11372 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11373 | ZeroOrMore rng -> (* <rng> list *)
11374 let pa = generate_parser rng in
11375 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11376 | OneOrMore rng -> (* <rng> list *)
11377 let pa = generate_parser rng in
11378 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11379 (* virt-inspector hack: bool *)
11380 | Optional (Attribute (name, [Value "1"])) ->
11381 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11382 | Optional rng -> (* <rng> list *)
11383 let pa = generate_parser rng in
11384 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11385 (* type name = { fields ... } *)
11386 | Element (name, fields) when is_attrs_interleave fields ->
11387 generate_parser_struct name (get_attrs_interleave fields)
11388 | Element (name, [field]) -> (* type name = field *)
11389 let pa = generate_parser field in
11390 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11391 pr "let %s =\n" parser_name;
11393 pr "let parse_%s = %s\n" name parser_name;
11395 | Attribute (name, [field]) ->
11396 let pa = generate_parser field in
11397 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11398 pr "let %s =\n" parser_name;
11400 pr "let parse_%s = %s\n" name parser_name;
11402 | Element (name, fields) -> (* type name = { fields ... } *)
11403 generate_parser_struct name ([], fields)
11405 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11407 and is_attrs_interleave = function
11408 | [Interleave _] -> true
11409 | Attribute _ :: fields -> is_attrs_interleave fields
11410 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11413 and get_attrs_interleave = function
11414 | [Interleave fields] -> [], fields
11415 | ((Attribute _) as field) :: fields
11416 | ((Optional (Attribute _)) as field) :: fields ->
11417 let attrs, interleaves = get_attrs_interleave fields in
11418 (field :: attrs), interleaves
11419 | _ -> assert false
11421 and generate_parsers xs =
11422 List.iter (fun x -> ignore (generate_parser x)) xs
11424 and generate_parser_struct name (attrs, interleaves) =
11425 (* Generate parsers for the fields first. We have to do this
11426 * before printing anything so we are still in BOL context.
11428 let fields = attrs @ interleaves in
11429 let pas = List.map generate_parser fields in
11431 (* Generate an intermediate tuple from all the fields first.
11432 * If the type is just a string + another field, then we will
11433 * return this directly, otherwise it is turned into a record.
11435 * RELAX NG note: This code treats <interleave> and plain lists of
11436 * fields the same. In other words, it doesn't bother enforcing
11437 * any ordering of fields in the XML.
11439 pr "let parse_%s x =\n" name;
11440 pr " let t = (\n ";
11441 let comma = ref false in
11444 if !comma then pr ",\n ";
11447 | Optional (Attribute (fname, [field])), pa ->
11449 | Optional (Element (fname, [field])), pa ->
11450 pr "%s (optional_child %S x)" pa fname
11451 | Attribute (fname, [Text]), _ ->
11452 pr "attribute %S x" fname
11453 | (ZeroOrMore _ | OneOrMore _), pa ->
11458 let fname = name_of_field field in
11459 pr "%s (child %S x)" pa fname
11460 ) (List.combine fields pas);
11464 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11468 pr " (Obj.magic t : %s)\n" name
11472 | (Optional (Attribute (fname, [field])), pa) ->
11473 pr " %s_%s =\n" name fname;
11475 | (Optional (Element (fname, [field])), pa) ->
11476 pr " %s_%s =\n" name fname;
11477 pr " (let x = optional_child %S x in\n" fname;
11480 let fname = name_of_field field in
11481 pr " %s_%s =\n" name fname;
11482 pr " (let x = child %S x in\n" fname;
11484 ) (List.combine fields pas);
11488 sprintf "parse_%s" name
11491 generate_parsers xs
11493 (* Generate ocaml/guestfs_inspector.mli. *)
11494 let generate_ocaml_inspector_mli () =
11495 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11498 (** This is an OCaml language binding to the external [virt-inspector]
11501 For more information, please read the man page [virt-inspector(1)].
11506 generate_types grammar;
11507 pr "(** The nested information returned from the {!inspect} function. *)\n";
11511 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11512 (** To inspect a libvirt domain called [name], pass a singleton
11513 list: [inspect [name]]. When using libvirt only, you may
11514 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11516 To inspect a disk image or images, pass a list of the filenames
11517 of the disk images: [inspect filenames]
11519 This function inspects the given guest or disk images and
11520 returns a list of operating system(s) found and a large amount
11521 of information about them. In the vast majority of cases,
11522 a virtual machine only contains a single operating system.
11524 If the optional [~xml] parameter is given, then this function
11525 skips running the external virt-inspector program and just
11526 parses the given XML directly (which is expected to be XML
11527 produced from a previous run of virt-inspector). The list of
11528 names and connect URI are ignored in this case.
11530 This function can throw a wide variety of exceptions, for example
11531 if the external virt-inspector program cannot be found, or if
11532 it doesn't generate valid XML.
11536 (* Generate ocaml/guestfs_inspector.ml. *)
11537 let generate_ocaml_inspector_ml () =
11538 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11543 generate_types grammar;
11547 (* Misc functions which are used by the parser code below. *)
11548 let first_child = function
11549 | Xml.Element (_, _, c::_) -> c
11550 | Xml.Element (name, _, []) ->
11551 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11552 | Xml.PCData str ->
11553 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11555 let string_child_or_empty = function
11556 | Xml.Element (_, _, [Xml.PCData s]) -> s
11557 | Xml.Element (_, _, []) -> \"\"
11558 | Xml.Element (x, _, _) ->
11559 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11561 | Xml.PCData str ->
11562 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11564 let optional_child name xml =
11565 let children = Xml.children xml in
11567 Some (List.find (function
11568 | Xml.Element (n, _, _) when n = name -> true
11569 | _ -> false) children)
11573 let child name xml =
11574 match optional_child name xml with
11577 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11579 let attribute name xml =
11580 try Xml.attrib xml name
11581 with Xml.No_attribute _ ->
11582 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11586 generate_parsers grammar;
11590 (* Run external virt-inspector, then use parser to parse the XML. *)
11591 let inspect ?connect ?xml names =
11595 if names = [] then invalid_arg \"inspect: no names given\";
11596 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11597 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11599 let cmd = List.map Filename.quote cmd in
11600 let cmd = String.concat \" \" cmd in
11601 let chan = open_process_in cmd in
11602 let xml = Xml.parse_in chan in
11603 (match close_process_in chan with
11605 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11606 | WSIGNALED i | WSTOPPED i ->
11607 failwith (\"external virt-inspector command died or stopped on sig \" ^
11612 Xml.parse_string doc in
11613 parse_operatingsystems xml
11616 (* This is used to generate the src/MAX_PROC_NR file which
11617 * contains the maximum procedure number, a surrogate for the
11618 * ABI version number. See src/Makefile.am for the details.
11620 and generate_max_proc_nr () =
11621 let proc_nrs = List.map (
11622 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11623 ) daemon_functions in
11625 let max_proc_nr = List.fold_left max 0 proc_nrs in
11627 pr "%d\n" max_proc_nr
11629 let output_to filename k =
11630 let filename_new = filename ^ ".new" in
11631 chan := open_out filename_new;
11634 chan := Pervasives.stdout;
11636 (* Is the new file different from the current file? *)
11637 if Sys.file_exists filename && files_equal filename filename_new then
11638 unlink filename_new (* same, so skip it *)
11640 (* different, overwrite old one *)
11641 (try chmod filename 0o644 with Unix_error _ -> ());
11642 rename filename_new filename;
11643 chmod filename 0o444;
11644 printf "written %s\n%!" filename;
11647 let perror msg = function
11648 | Unix_error (err, _, _) ->
11649 eprintf "%s: %s\n" msg (error_message err)
11651 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11653 (* Main program. *)
11656 try openfile "HACKING" [O_RDWR] 0
11658 | Unix_error (ENOENT, _, _) ->
11660 You are probably running this from the wrong directory.
11661 Run it from the top source directory using the command
11666 perror "open: HACKING" exn;
11669 (* Acquire a lock so parallel builds won't try to run the generator
11670 * twice at the same time. Subsequent builds will wait for the first
11671 * one to finish. Note the lock is released implicitly when the
11674 (try lockf lock_fd F_LOCK 1
11676 perror "lock: HACKING" exn;
11679 check_functions ();
11681 output_to "src/guestfs_protocol.x" generate_xdr;
11682 output_to "src/guestfs-structs.h" generate_structs_h;
11683 output_to "src/guestfs-actions.h" generate_actions_h;
11684 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11685 output_to "src/guestfs-actions.c" generate_client_actions;
11686 output_to "src/guestfs-bindtests.c" generate_bindtests;
11687 output_to "src/guestfs-structs.pod" generate_structs_pod;
11688 output_to "src/guestfs-actions.pod" generate_actions_pod;
11689 output_to "src/guestfs-availability.pod" generate_availability_pod;
11690 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11691 output_to "src/libguestfs.syms" generate_linker_script;
11692 output_to "daemon/actions.h" generate_daemon_actions_h;
11693 output_to "daemon/stubs.c" generate_daemon_actions;
11694 output_to "daemon/names.c" generate_daemon_names;
11695 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11696 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11697 output_to "capitests/tests.c" generate_tests;
11698 output_to "fish/cmds.c" generate_fish_cmds;
11699 output_to "fish/completion.c" generate_fish_completion;
11700 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11701 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11702 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11703 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11704 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11705 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11706 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11707 output_to "perl/Guestfs.xs" generate_perl_xs;
11708 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11709 output_to "perl/bindtests.pl" generate_perl_bindtests;
11710 output_to "python/guestfs-py.c" generate_python_c;
11711 output_to "python/guestfs.py" generate_python_py;
11712 output_to "python/bindtests.py" generate_python_bindtests;
11713 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11714 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11715 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11719 let cols = cols_of_struct typ in
11720 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11721 output_to filename (generate_java_struct jtyp cols);
11724 output_to "java/Makefile.inc" generate_java_makefile_inc;
11725 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11726 output_to "java/Bindtests.java" generate_java_bindtests;
11727 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11728 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11729 output_to "csharp/Libguestfs.cs" generate_csharp;
11731 (* Always generate this file last, and unconditionally. It's used
11732 * by the Makefile to know when we must re-run the generator.
11734 let chan = open_out "src/stamp-generator" in
11735 fprintf chan "1\n";
11738 printf "generated %d lines of code\n" !lines