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 | NotInFish (* do not export via guestfish *)
186 | NotInDocs (* do not add this function to documentation *)
187 | DeprecatedBy of string (* function is deprecated, use .. instead *)
188 | Optional of string (* function is part of an optional group *)
190 (* You can supply zero or as many tests as you want per API call.
192 * Note that the test environment has 3 block devices, of size 500MB,
193 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194 * a fourth ISO block device with some known files on it (/dev/sdd).
196 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197 * Number of cylinders was 63 for IDE emulated disks with precisely
198 * the same size. How exactly this is calculated is a mystery.
200 * The ISO block device (/dev/sdd) comes from images/test.iso.
202 * To be able to run the tests in a reasonable amount of time,
203 * the virtual machine and block devices are reused between tests.
204 * So don't try testing kill_subprocess :-x
206 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
208 * Don't assume anything about the previous contents of the block
209 * devices. Use 'Init*' to create some initial scenarios.
211 * You can add a prerequisite clause to any individual test. This
212 * is a run-time check, which, if it fails, causes the test to be
213 * skipped. Useful if testing a command which might not work on
214 * all variations of libguestfs builds. A test that has prerequisite
215 * of 'Always' is run unconditionally.
217 * In addition, packagers can skip individual tests by setting the
218 * environment variables: eg:
219 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
220 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
222 type tests = (test_init * test_prereq * test) list
224 (* Run the command sequence and just expect nothing to fail. *)
227 (* Run the command sequence and expect the output of the final
228 * command to be the string.
230 | TestOutput of seq * string
232 (* Run the command sequence and expect the output of the final
233 * command to be the list of strings.
235 | TestOutputList of seq * string list
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of block devices (could be either
239 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240 * character of each string).
242 | TestOutputListOfDevices of seq * string list
244 (* Run the command sequence and expect the output of the final
245 * command to be the integer.
247 | TestOutputInt of seq * int
249 (* Run the command sequence and expect the output of the final
250 * command to be <op> <int>, eg. ">=", "1".
252 | TestOutputIntOp of seq * string * int
254 (* Run the command sequence and expect the output of the final
255 * command to be a true value (!= 0 or != NULL).
257 | TestOutputTrue of seq
259 (* Run the command sequence and expect the output of the final
260 * command to be a false value (== 0 or == NULL, but not an error).
262 | TestOutputFalse of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a list of the given length (but don't care about
268 | TestOutputLength of seq * int
270 (* Run the command sequence and expect the output of the final
271 * command to be a buffer (RBufferOut), ie. string + size.
273 | TestOutputBuffer of seq * string
275 (* Run the command sequence and expect the output of the final
276 * command to be a structure.
278 | TestOutputStruct of seq * test_field_compare list
280 (* Run the command sequence and expect the final command (only)
283 | TestLastFail of seq
285 and test_field_compare =
286 | CompareWithInt of string * int
287 | CompareWithIntOp of string * string * int
288 | CompareWithString of string * string
289 | CompareFieldsIntEq of string * string
290 | CompareFieldsStrEq of string * string
292 (* Test prerequisites. *)
294 (* Test always runs. *)
297 (* Test is currently disabled - eg. it fails, or it tests some
298 * unimplemented feature.
302 (* 'string' is some C code (a function body) that should return
303 * true or false. The test will run if the code returns true.
307 (* As for 'If' but the test runs _unless_ the code returns true. *)
310 (* Some initial scenarios for testing. *)
312 (* Do nothing, block devices could contain random stuff including
313 * LVM PVs, and some filesystems might be mounted. This is usually
318 (* Block devices are empty and no filesystems are mounted. *)
321 (* /dev/sda contains a single partition /dev/sda1, with random
322 * content. /dev/sdb and /dev/sdc may have random content.
327 (* /dev/sda contains a single partition /dev/sda1, which is formatted
328 * as ext2, empty [except for lost+found] and mounted on /.
329 * /dev/sdb and /dev/sdc may have random content.
335 * /dev/sda1 (is a PV):
336 * /dev/VG/LV (size 8MB):
337 * formatted as ext2, empty [except for lost+found], mounted on /
338 * /dev/sdb and /dev/sdc may have random content.
342 (* /dev/sdd (the ISO, see images/ directory in source)
347 (* Sequence of commands for testing. *)
349 and cmd = string list
351 (* Note about long descriptions: When referring to another
352 * action, use the format C<guestfs_other> (ie. the full name of
353 * the C function). This will be replaced as appropriate in other
356 * Apart from that, long descriptions are just perldoc paragraphs.
359 (* Generate a random UUID (used in tests). *)
361 let chan = open_process_in "uuidgen" in
362 let uuid = input_line chan in
363 (match close_process_in chan with
366 failwith "uuidgen: process exited with non-zero status"
367 | WSIGNALED _ | WSTOPPED _ ->
368 failwith "uuidgen: process signalled or stopped by signal"
372 (* These test functions are used in the language binding tests. *)
374 let test_all_args = [
377 StringList "strlist";
385 let test_all_rets = [
386 (* except for RErr, which is tested thoroughly elsewhere *)
387 "test0rint", RInt "valout";
388 "test0rint64", RInt64 "valout";
389 "test0rbool", RBool "valout";
390 "test0rconststring", RConstString "valout";
391 "test0rconstoptstring", RConstOptString "valout";
392 "test0rstring", RString "valout";
393 "test0rstringlist", RStringList "valout";
394 "test0rstruct", RStruct ("valout", "lvm_pv");
395 "test0rstructlist", RStructList ("valout", "lvm_pv");
396 "test0rhashtable", RHashtable "valout";
399 let test_functions = [
400 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
402 "internal test function - do not use",
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
408 It echos the contents of each parameter to stdout.
410 You probably don't want to call this function.");
414 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
416 "internal test function - do not use",
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
422 It converts string C<val> to the return type.
424 You probably don't want to call this function.");
425 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
427 "internal test function - do not use",
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
433 This function always returns an error.
435 You probably don't want to call this function.")]
439 (* non_daemon_functions are any functions which don't get processed
440 * in the daemon, eg. functions for setting and getting local
441 * configuration values.
444 let non_daemon_functions = test_functions @ [
445 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
447 "launch the qemu subprocess",
449 Internally libguestfs is implemented by running a virtual machine
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
455 ("wait_ready", (RErr, []), -1, [NotInFish],
457 "wait until the qemu subprocess launches (no op)",
459 This function is a no op.
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete. However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
470 ("kill_subprocess", (RErr, []), -1, [],
472 "kill the qemu subprocess",
474 This kills the qemu subprocess. You should never need to call this.");
476 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
478 "add an image to examine or modify",
480 This function adds a virtual machine disk image C<filename> to the
481 guest. The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
485 You don't necessarily need to be root when using libguestfs. However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>. In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
502 Note that this call checks for the existence of C<filename>. This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
505 the general C<guestfs_config> call instead.");
507 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
509 "add a CD-ROM disk image to examine",
511 This function adds a virtual CD-ROM disk image to the guest.
513 This is equivalent to the qemu parameter C<-cdrom filename>.
521 This call checks for the existence of C<filename>. This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
524 the general C<guestfs_config> call instead.
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
534 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
536 "add a drive in snapshot mode (read-only)",
538 This adds a drive in snapshot mode, making it effectively
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed. We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>. In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
555 C<readonly=on> is only added where qemu supports this option.
557 Note that this call checks for the existence of C<filename>. This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
560 the general C<guestfs_config> call instead.");
562 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
564 "add qemu parameters",
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>. Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
571 The first character of C<param> string must be a C<-> (dash).
573 C<value> can be NULL.");
575 ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
577 "set the qemu binary",
579 Set the qemu binary that we will use.
581 The default is chosen when the library was compiled by the
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
589 Note that you should call this function as early as possible
590 after creating the handle. This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results. Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
597 ("get_qemu", (RConstString "qemu", []), -1, [],
598 [InitNone, Always, TestRun (
600 "get the qemu binary",
602 Return the current qemu binary.
604 This is always non-NULL. If it wasn't set already, then this will
605 return the default qemu binary name.");
607 ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
609 "set the search path",
611 Set the path that libguestfs searches for kernel and initrd.img.
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
616 Setting C<path> to C<NULL> restores the default path.");
618 ("get_path", (RConstString "path", []), -1, [],
619 [InitNone, Always, TestRun (
621 "get the search path",
623 Return the current search path.
625 This is always non-NULL. If it wasn't set already, then this will
626 return the default path.");
628 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
630 "add options to kernel command line",
632 This function is used to add additional options to the
633 guest kernel command line.
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
641 ("get_append", (RConstOptString "append", []), -1, [],
642 (* This cannot be tested with the current framework. The
643 * function can return NULL in normal operations, which the
644 * test framework interprets as an error.
647 "get the additional kernel options",
649 Return the additional kernel options which are added to the
650 guest kernel command line.
652 If C<NULL> then no options are added.");
654 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658 If C<autosync> is true, this enables autosync. Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
666 ("get_autosync", (RBool "autosync", []), -1, [],
667 [InitNone, Always, TestRun (
668 [["get_autosync"]])],
671 Get the autosync flag.");
673 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
682 ("get_verbose", (RBool "verbose", []), -1, [],
686 This returns the verbose messages flag.");
688 ("is_ready", (RBool "ready", []), -1, [],
689 [InitNone, Always, TestOutputTrue (
691 "is ready to accept commands",
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
696 For more information on states, see L<guestfs(3)>.");
698 ("is_config", (RBool "config", []), -1, [],
699 [InitNone, Always, TestOutputFalse (
701 "is in configuration state",
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
706 For more information on states, see L<guestfs(3)>.");
708 ("is_launching", (RBool "launching", []), -1, [],
709 [InitNone, Always, TestOutputFalse (
710 [["is_launching"]])],
711 "is launching subprocess",
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
716 For more information on states, see L<guestfs(3)>.");
718 ("is_busy", (RBool "busy", []), -1, [],
719 [InitNone, Always, TestOutputFalse (
721 "is busy processing a command",
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
726 For more information on states, see L<guestfs(3)>.");
728 ("get_state", (RInt "state", []), -1, [],
730 "get the current state",
732 This returns the current state as an opaque integer. This is
733 only useful for printing debug and internal error messages.
735 For more information on states, see L<guestfs(3)>.");
737 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738 [InitNone, Always, TestOutputInt (
739 [["set_memsize"; "500"];
740 ["get_memsize"]], 500)],
741 "set memory allocated to the qemu subprocess",
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess. This only has any effect if called before
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
754 ("get_memsize", (RInt "memsize", []), -1, [],
755 [InitNone, Always, TestOutputIntOp (
756 [["get_memsize"]], ">=", 256)],
757 "get memory allocated to the qemu subprocess",
759 This gets the memory size in megabytes allocated to the
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
769 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770 [InitNone, Always, TestOutputIntOp (
771 [["get_pid"]], ">=", 1)],
772 "get PID of qemu subprocess",
774 Return the process ID of the qemu subprocess. If there is no
775 qemu subprocess, then this will return an error.
777 This is an internal call used for debugging and testing.");
779 ("version", (RStruct ("version", "version"), []), -1, [],
780 [InitNone, Always, TestOutputStruct (
781 [["version"]], [CompareWithInt ("major", 1)])],
782 "get the library version number",
784 Return the libguestfs version number that the program is linked
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against. You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
792 This call was added in version C<1.0.58>. In previous
793 versions of libguestfs there was no way to get the version
794 number. From C code you can use dynamic linker functions
795 to find out if this symbol exists (if it doesn't, then
796 it's an earlier version).
798 The call returns a structure with four elements. The first
799 three (C<major>, C<minor> and C<release>) are numbers and
800 correspond to the usual version triplet. The fourth element
801 (C<extra>) is a string and is normally empty, but may be
802 used for distro-specific information.
804 To construct the original version string:
805 C<$major.$minor.$release$extra>
807 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
809 I<Note:> Don't use this call to test for availability
810 of features. In enterprise distributions we backport
811 features from later versions into earlier versions,
812 making this an unreliable way to test for features.
813 Use 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<value>.");
1255 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1256 [], (* XXX Augeas code needs tests. *)
1257 "insert a sibling Augeas node",
1259 Create a new sibling C<label> for C<path>, inserting it into
1260 the tree before or after C<path> (depending on the boolean
1263 C<path> must match exactly one existing node in the tree, and
1264 C<label> must be a label, ie. not contain C</>, C<*> or end
1265 with a bracketed index C<[N]>.");
1267 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1268 [], (* XXX Augeas code needs tests. *)
1269 "remove an Augeas path",
1271 Remove C<path> and all of its children.
1273 On success this returns the number of entries which were removed.");
1275 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1276 [], (* XXX Augeas code needs tests. *)
1279 Move the node C<src> to C<dest>. C<src> must match exactly
1280 one node. C<dest> is overwritten if it exists.");
1282 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1283 [], (* XXX Augeas code needs tests. *)
1284 "return Augeas nodes which match augpath",
1286 Returns a list of paths which match the path expression C<path>.
1287 The returned paths are sufficiently qualified so that they match
1288 exactly one node in the current tree.");
1290 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1291 [], (* XXX Augeas code needs tests. *)
1292 "write all pending Augeas changes to disk",
1294 This writes all pending changes to disk.
1296 The flags which were passed to C<guestfs_aug_init> affect exactly
1297 how files are saved.");
1299 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1300 [], (* XXX Augeas code needs tests. *)
1301 "load files into the tree",
1303 Load files into the tree.
1305 See C<aug_load> in the Augeas documentation for the full gory
1308 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1309 [], (* XXX Augeas code needs tests. *)
1310 "list Augeas nodes under augpath",
1312 This is just a shortcut for listing C<guestfs_aug_match>
1313 C<path/*> and sorting the resulting nodes into alphabetical order.");
1315 ("rm", (RErr, [Pathname "path"]), 29, [],
1316 [InitBasicFS, Always, TestRun
1319 InitBasicFS, Always, TestLastFail
1321 InitBasicFS, Always, TestLastFail
1326 Remove the single file C<path>.");
1328 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1329 [InitBasicFS, Always, TestRun
1332 InitBasicFS, Always, TestLastFail
1333 [["rmdir"; "/new"]];
1334 InitBasicFS, Always, TestLastFail
1336 ["rmdir"; "/new"]]],
1337 "remove a directory",
1339 Remove the single directory C<path>.");
1341 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1342 [InitBasicFS, Always, TestOutputFalse
1344 ["mkdir"; "/new/foo"];
1345 ["touch"; "/new/foo/bar"];
1347 ["exists"; "/new"]]],
1348 "remove a file or directory recursively",
1350 Remove the file or directory C<path>, recursively removing the
1351 contents if its a directory. This is like the C<rm -rf> shell
1354 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1355 [InitBasicFS, Always, TestOutputTrue
1357 ["is_dir"; "/new"]];
1358 InitBasicFS, Always, TestLastFail
1359 [["mkdir"; "/new/foo/bar"]]],
1360 "create a directory",
1362 Create a directory named C<path>.");
1364 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1365 [InitBasicFS, Always, TestOutputTrue
1366 [["mkdir_p"; "/new/foo/bar"];
1367 ["is_dir"; "/new/foo/bar"]];
1368 InitBasicFS, Always, TestOutputTrue
1369 [["mkdir_p"; "/new/foo/bar"];
1370 ["is_dir"; "/new/foo"]];
1371 InitBasicFS, Always, TestOutputTrue
1372 [["mkdir_p"; "/new/foo/bar"];
1373 ["is_dir"; "/new"]];
1374 (* Regression tests for RHBZ#503133: *)
1375 InitBasicFS, Always, TestRun
1377 ["mkdir_p"; "/new"]];
1378 InitBasicFS, Always, TestLastFail
1380 ["mkdir_p"; "/new"]]],
1381 "create a directory and parents",
1383 Create a directory named C<path>, creating any parent directories
1384 as necessary. This is like the C<mkdir -p> shell command.");
1386 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1387 [], (* XXX Need stat command to test *)
1390 Change the mode (permissions) of C<path> to C<mode>. Only
1391 numeric modes are supported.
1393 I<Note>: When using this command from guestfish, C<mode>
1394 by default would be decimal, unless you prefix it with
1395 C<0> to get octal, ie. use C<0700> not C<700>.
1397 The mode actually set is affected by the umask.");
1399 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1400 [], (* XXX Need stat command to test *)
1401 "change file owner and group",
1403 Change the file owner to C<owner> and group to C<group>.
1405 Only numeric uid and gid are supported. If you want to use
1406 names, you will need to locate and parse the password file
1407 yourself (Augeas support makes this relatively easy).");
1409 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1410 [InitISOFS, Always, TestOutputTrue (
1411 [["exists"; "/empty"]]);
1412 InitISOFS, Always, TestOutputTrue (
1413 [["exists"; "/directory"]])],
1414 "test if file or directory exists",
1416 This returns C<true> if and only if there is a file, directory
1417 (or anything) with the given C<path> name.
1419 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1421 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1422 [InitISOFS, Always, TestOutputTrue (
1423 [["is_file"; "/known-1"]]);
1424 InitISOFS, Always, TestOutputFalse (
1425 [["is_file"; "/directory"]])],
1426 "test if file exists",
1428 This returns C<true> if and only if there is a file
1429 with the given C<path> name. Note that it returns false for
1430 other objects like directories.
1432 See also C<guestfs_stat>.");
1434 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1435 [InitISOFS, Always, TestOutputFalse (
1436 [["is_dir"; "/known-3"]]);
1437 InitISOFS, Always, TestOutputTrue (
1438 [["is_dir"; "/directory"]])],
1439 "test if file exists",
1441 This returns C<true> if and only if there is a directory
1442 with the given C<path> name. Note that it returns false for
1443 other objects like files.
1445 See also C<guestfs_stat>.");
1447 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1448 [InitEmpty, Always, TestOutputListOfDevices (
1449 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1450 ["pvcreate"; "/dev/sda1"];
1451 ["pvcreate"; "/dev/sda2"];
1452 ["pvcreate"; "/dev/sda3"];
1453 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1454 "create an LVM physical volume",
1456 This creates an LVM physical volume on the named C<device>,
1457 where C<device> should usually be a partition name such
1460 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1461 [InitEmpty, Always, TestOutputList (
1462 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463 ["pvcreate"; "/dev/sda1"];
1464 ["pvcreate"; "/dev/sda2"];
1465 ["pvcreate"; "/dev/sda3"];
1466 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467 ["vgcreate"; "VG2"; "/dev/sda3"];
1468 ["vgs"]], ["VG1"; "VG2"])],
1469 "create an LVM volume group",
1471 This creates an LVM volume group called C<volgroup>
1472 from the non-empty list of physical volumes C<physvols>.");
1474 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1475 [InitEmpty, Always, TestOutputList (
1476 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1477 ["pvcreate"; "/dev/sda1"];
1478 ["pvcreate"; "/dev/sda2"];
1479 ["pvcreate"; "/dev/sda3"];
1480 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1481 ["vgcreate"; "VG2"; "/dev/sda3"];
1482 ["lvcreate"; "LV1"; "VG1"; "50"];
1483 ["lvcreate"; "LV2"; "VG1"; "50"];
1484 ["lvcreate"; "LV3"; "VG2"; "50"];
1485 ["lvcreate"; "LV4"; "VG2"; "50"];
1486 ["lvcreate"; "LV5"; "VG2"; "50"];
1488 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1489 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1490 "create an LVM logical volume",
1492 This creates an LVM logical volume called C<logvol>
1493 on the volume group C<volgroup>, with C<size> megabytes.");
1495 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1496 [InitEmpty, Always, TestOutput (
1497 [["part_disk"; "/dev/sda"; "mbr"];
1498 ["mkfs"; "ext2"; "/dev/sda1"];
1499 ["mount_options"; ""; "/dev/sda1"; "/"];
1500 ["write_file"; "/new"; "new file contents"; "0"];
1501 ["cat"; "/new"]], "new file contents")],
1502 "make a filesystem",
1504 This creates a filesystem on C<device> (usually a partition
1505 or LVM logical volume). The filesystem type is C<fstype>, for
1508 ("sfdisk", (RErr, [Device "device";
1509 Int "cyls"; Int "heads"; Int "sectors";
1510 StringList "lines"]), 43, [DangerWillRobinson],
1512 "create partitions on a block device",
1514 This is a direct interface to the L<sfdisk(8)> program for creating
1515 partitions on block devices.
1517 C<device> should be a block device, for example C</dev/sda>.
1519 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1520 and sectors on the device, which are passed directly to sfdisk as
1521 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1522 of these, then the corresponding parameter is omitted. Usually for
1523 'large' disks, you can just pass C<0> for these, but for small
1524 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1525 out the right geometry and you will need to tell it.
1527 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1528 information refer to the L<sfdisk(8)> manpage.
1530 To create a single partition occupying the whole disk, you would
1531 pass C<lines> as a single element list, when the single element being
1532 the string C<,> (comma).
1534 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1535 C<guestfs_part_init>");
1537 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1538 [InitBasicFS, Always, TestOutput (
1539 [["write_file"; "/new"; "new file contents"; "0"];
1540 ["cat"; "/new"]], "new file contents");
1541 InitBasicFS, Always, TestOutput (
1542 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1543 ["cat"; "/new"]], "\nnew file contents\n");
1544 InitBasicFS, Always, TestOutput (
1545 [["write_file"; "/new"; "\n\n"; "0"];
1546 ["cat"; "/new"]], "\n\n");
1547 InitBasicFS, Always, TestOutput (
1548 [["write_file"; "/new"; ""; "0"];
1549 ["cat"; "/new"]], "");
1550 InitBasicFS, Always, TestOutput (
1551 [["write_file"; "/new"; "\n\n\n"; "0"];
1552 ["cat"; "/new"]], "\n\n\n");
1553 InitBasicFS, Always, TestOutput (
1554 [["write_file"; "/new"; "\n"; "0"];
1555 ["cat"; "/new"]], "\n");
1556 (* Regression test for RHBZ#597135. *)
1557 InitBasicFS, Always, TestLastFail
1558 [["write_file"; "/new"; "abc"; "10000"]]],
1561 This call creates a file called C<path>. The contents of the
1562 file is the string C<content> (which can contain any 8 bit data),
1563 with length C<size>.
1565 As a special case, if C<size> is C<0>
1566 then the length is calculated using C<strlen> (so in this case
1567 the content cannot contain embedded ASCII NULs).
1569 I<NB.> Owing to a bug, writing content containing ASCII NUL
1570 characters does I<not> work, even if the length is specified.
1571 We hope to resolve this bug in a future version. In the meantime
1572 use C<guestfs_upload>.");
1574 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1575 [InitEmpty, Always, TestOutputListOfDevices (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1579 ["mounts"]], ["/dev/sda1"]);
1580 InitEmpty, Always, TestOutputList (
1581 [["part_disk"; "/dev/sda"; "mbr"];
1582 ["mkfs"; "ext2"; "/dev/sda1"];
1583 ["mount_options"; ""; "/dev/sda1"; "/"];
1586 "unmount a filesystem",
1588 This unmounts the given filesystem. The filesystem may be
1589 specified either by its mountpoint (path) or the device which
1590 contains the filesystem.");
1592 ("mounts", (RStringList "devices", []), 46, [],
1593 [InitBasicFS, Always, TestOutputListOfDevices (
1594 [["mounts"]], ["/dev/sda1"])],
1595 "show mounted filesystems",
1597 This returns the list of currently mounted filesystems. It returns
1598 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1600 Some internal mounts are not shown.
1602 See also: C<guestfs_mountpoints>");
1604 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1605 [InitBasicFS, Always, TestOutputList (
1608 (* check that umount_all can unmount nested mounts correctly: *)
1609 InitEmpty, Always, TestOutputList (
1610 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1611 ["mkfs"; "ext2"; "/dev/sda1"];
1612 ["mkfs"; "ext2"; "/dev/sda2"];
1613 ["mkfs"; "ext2"; "/dev/sda3"];
1614 ["mount_options"; ""; "/dev/sda1"; "/"];
1616 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1617 ["mkdir"; "/mp1/mp2"];
1618 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1619 ["mkdir"; "/mp1/mp2/mp3"];
1622 "unmount all filesystems",
1624 This unmounts all mounted filesystems.
1626 Some internal mounts are not unmounted by this call.");
1628 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1630 "remove all LVM LVs, VGs and PVs",
1632 This command removes all LVM logical volumes, volume groups
1633 and physical volumes.");
1635 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1636 [InitISOFS, Always, TestOutput (
1637 [["file"; "/empty"]], "empty");
1638 InitISOFS, Always, TestOutput (
1639 [["file"; "/known-1"]], "ASCII text");
1640 InitISOFS, Always, TestLastFail (
1641 [["file"; "/notexists"]])],
1642 "determine file type",
1644 This call uses the standard L<file(1)> command to determine
1645 the type or contents of the file. This also works on devices,
1646 for example to find out whether a partition contains a filesystem.
1648 This call will also transparently look inside various types
1651 The exact command which runs is C<file -zbsL path>. Note in
1652 particular that the filename is not prepended to the output
1653 (the C<-b> option).");
1655 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1656 [InitBasicFS, Always, TestOutput (
1657 [["upload"; "test-command"; "/test-command"];
1658 ["chmod"; "0o755"; "/test-command"];
1659 ["command"; "/test-command 1"]], "Result1");
1660 InitBasicFS, Always, TestOutput (
1661 [["upload"; "test-command"; "/test-command"];
1662 ["chmod"; "0o755"; "/test-command"];
1663 ["command"; "/test-command 2"]], "Result2\n");
1664 InitBasicFS, Always, TestOutput (
1665 [["upload"; "test-command"; "/test-command"];
1666 ["chmod"; "0o755"; "/test-command"];
1667 ["command"; "/test-command 3"]], "\nResult3");
1668 InitBasicFS, Always, TestOutput (
1669 [["upload"; "test-command"; "/test-command"];
1670 ["chmod"; "0o755"; "/test-command"];
1671 ["command"; "/test-command 4"]], "\nResult4\n");
1672 InitBasicFS, Always, TestOutput (
1673 [["upload"; "test-command"; "/test-command"];
1674 ["chmod"; "0o755"; "/test-command"];
1675 ["command"; "/test-command 5"]], "\nResult5\n\n");
1676 InitBasicFS, Always, TestOutput (
1677 [["upload"; "test-command"; "/test-command"];
1678 ["chmod"; "0o755"; "/test-command"];
1679 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1680 InitBasicFS, Always, TestOutput (
1681 [["upload"; "test-command"; "/test-command"];
1682 ["chmod"; "0o755"; "/test-command"];
1683 ["command"; "/test-command 7"]], "");
1684 InitBasicFS, Always, TestOutput (
1685 [["upload"; "test-command"; "/test-command"];
1686 ["chmod"; "0o755"; "/test-command"];
1687 ["command"; "/test-command 8"]], "\n");
1688 InitBasicFS, Always, TestOutput (
1689 [["upload"; "test-command"; "/test-command"];
1690 ["chmod"; "0o755"; "/test-command"];
1691 ["command"; "/test-command 9"]], "\n\n");
1692 InitBasicFS, Always, TestOutput (
1693 [["upload"; "test-command"; "/test-command"];
1694 ["chmod"; "0o755"; "/test-command"];
1695 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1696 InitBasicFS, Always, TestOutput (
1697 [["upload"; "test-command"; "/test-command"];
1698 ["chmod"; "0o755"; "/test-command"];
1699 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1700 InitBasicFS, Always, TestLastFail (
1701 [["upload"; "test-command"; "/test-command"];
1702 ["chmod"; "0o755"; "/test-command"];
1703 ["command"; "/test-command"]])],
1704 "run a command from the guest filesystem",
1706 This call runs a command from the guest filesystem. The
1707 filesystem must be mounted, and must contain a compatible
1708 operating system (ie. something Linux, with the same
1709 or compatible processor architecture).
1711 The single parameter is an argv-style list of arguments.
1712 The first element is the name of the program to run.
1713 Subsequent elements are parameters. The list must be
1714 non-empty (ie. must contain a program name). Note that
1715 the command runs directly, and is I<not> invoked via
1716 the shell (see C<guestfs_sh>).
1718 The return value is anything printed to I<stdout> by
1721 If the command returns a non-zero exit status, then
1722 this function returns an error message. The error message
1723 string is the content of I<stderr> from the command.
1725 The C<$PATH> environment variable will contain at least
1726 C</usr/bin> and C</bin>. If you require a program from
1727 another location, you should provide the full path in the
1730 Shared libraries and data files required by the program
1731 must be available on filesystems which are mounted in the
1732 correct places. It is the caller's responsibility to ensure
1733 all filesystems that are needed are mounted at the right
1736 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1737 [InitBasicFS, Always, TestOutputList (
1738 [["upload"; "test-command"; "/test-command"];
1739 ["chmod"; "0o755"; "/test-command"];
1740 ["command_lines"; "/test-command 1"]], ["Result1"]);
1741 InitBasicFS, Always, TestOutputList (
1742 [["upload"; "test-command"; "/test-command"];
1743 ["chmod"; "0o755"; "/test-command"];
1744 ["command_lines"; "/test-command 2"]], ["Result2"]);
1745 InitBasicFS, Always, TestOutputList (
1746 [["upload"; "test-command"; "/test-command"];
1747 ["chmod"; "0o755"; "/test-command"];
1748 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1749 InitBasicFS, Always, TestOutputList (
1750 [["upload"; "test-command"; "/test-command"];
1751 ["chmod"; "0o755"; "/test-command"];
1752 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1753 InitBasicFS, Always, TestOutputList (
1754 [["upload"; "test-command"; "/test-command"];
1755 ["chmod"; "0o755"; "/test-command"];
1756 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1757 InitBasicFS, Always, TestOutputList (
1758 [["upload"; "test-command"; "/test-command"];
1759 ["chmod"; "0o755"; "/test-command"];
1760 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1761 InitBasicFS, Always, TestOutputList (
1762 [["upload"; "test-command"; "/test-command"];
1763 ["chmod"; "0o755"; "/test-command"];
1764 ["command_lines"; "/test-command 7"]], []);
1765 InitBasicFS, Always, TestOutputList (
1766 [["upload"; "test-command"; "/test-command"];
1767 ["chmod"; "0o755"; "/test-command"];
1768 ["command_lines"; "/test-command 8"]], [""]);
1769 InitBasicFS, Always, TestOutputList (
1770 [["upload"; "test-command"; "/test-command"];
1771 ["chmod"; "0o755"; "/test-command"];
1772 ["command_lines"; "/test-command 9"]], ["";""]);
1773 InitBasicFS, Always, TestOutputList (
1774 [["upload"; "test-command"; "/test-command"];
1775 ["chmod"; "0o755"; "/test-command"];
1776 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1777 InitBasicFS, Always, TestOutputList (
1778 [["upload"; "test-command"; "/test-command"];
1779 ["chmod"; "0o755"; "/test-command"];
1780 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1781 "run a command, returning lines",
1783 This is the same as C<guestfs_command>, but splits the
1784 result into a list of lines.
1786 See also: C<guestfs_sh_lines>");
1788 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1789 [InitISOFS, Always, TestOutputStruct (
1790 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1791 "get file information",
1793 Returns file information for the given C<path>.
1795 This is the same as the C<stat(2)> system call.");
1797 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1798 [InitISOFS, Always, TestOutputStruct (
1799 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1800 "get file information for a symbolic link",
1802 Returns file information for the given C<path>.
1804 This is the same as C<guestfs_stat> except that if C<path>
1805 is a symbolic link, then the link is stat-ed, not the file it
1808 This is the same as the C<lstat(2)> system call.");
1810 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1811 [InitISOFS, Always, TestOutputStruct (
1812 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1813 "get file system statistics",
1815 Returns file system statistics for any mounted file system.
1816 C<path> should be a file or directory in the mounted file system
1817 (typically it is the mount point itself, but it doesn't need to be).
1819 This is the same as the C<statvfs(2)> system call.");
1821 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1823 "get ext2/ext3/ext4 superblock details",
1825 This returns the contents of the ext2, ext3 or ext4 filesystem
1826 superblock on C<device>.
1828 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1829 manpage for more details. The list of fields returned isn't
1830 clearly defined, and depends on both the version of C<tune2fs>
1831 that libguestfs was built against, and the filesystem itself.");
1833 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1834 [InitEmpty, Always, TestOutputTrue (
1835 [["blockdev_setro"; "/dev/sda"];
1836 ["blockdev_getro"; "/dev/sda"]])],
1837 "set block device to read-only",
1839 Sets the block device named C<device> to read-only.
1841 This uses the L<blockdev(8)> command.");
1843 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1844 [InitEmpty, Always, TestOutputFalse (
1845 [["blockdev_setrw"; "/dev/sda"];
1846 ["blockdev_getro"; "/dev/sda"]])],
1847 "set block device to read-write",
1849 Sets the block device named C<device> to read-write.
1851 This uses the L<blockdev(8)> command.");
1853 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1854 [InitEmpty, Always, TestOutputTrue (
1855 [["blockdev_setro"; "/dev/sda"];
1856 ["blockdev_getro"; "/dev/sda"]])],
1857 "is block device set to read-only",
1859 Returns a boolean indicating if the block device is read-only
1860 (true if read-only, false if not).
1862 This uses the L<blockdev(8)> command.");
1864 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1865 [InitEmpty, Always, TestOutputInt (
1866 [["blockdev_getss"; "/dev/sda"]], 512)],
1867 "get sectorsize of block device",
1869 This returns the size of sectors on a block device.
1870 Usually 512, but can be larger for modern devices.
1872 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 This uses the L<blockdev(8)> command.");
1877 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1878 [InitEmpty, Always, TestOutputInt (
1879 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1880 "get blocksize of block device",
1882 This returns the block size of a device.
1884 (Note this is different from both I<size in blocks> and
1885 I<filesystem block size>).
1887 This uses the L<blockdev(8)> command.");
1889 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1891 "set blocksize of block device",
1893 This sets the block size of a device.
1895 (Note this is different from both I<size in blocks> and
1896 I<filesystem block size>).
1898 This uses the L<blockdev(8)> command.");
1900 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1901 [InitEmpty, Always, TestOutputInt (
1902 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1903 "get total size of device in 512-byte sectors",
1905 This returns the size of the device in units of 512-byte sectors
1906 (even if the sectorsize isn't 512 bytes ... weird).
1908 See also C<guestfs_blockdev_getss> for the real sector size of
1909 the device, and C<guestfs_blockdev_getsize64> for the more
1910 useful I<size in bytes>.
1912 This uses the L<blockdev(8)> command.");
1914 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1915 [InitEmpty, Always, TestOutputInt (
1916 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1917 "get total size of device in bytes",
1919 This returns the size of the device in bytes.
1921 See also C<guestfs_blockdev_getsz>.
1923 This uses the L<blockdev(8)> command.");
1925 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1926 [InitEmpty, Always, TestRun
1927 [["blockdev_flushbufs"; "/dev/sda"]]],
1928 "flush device buffers",
1930 This tells the kernel to flush internal buffers associated
1933 This uses the L<blockdev(8)> command.");
1935 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1936 [InitEmpty, Always, TestRun
1937 [["blockdev_rereadpt"; "/dev/sda"]]],
1938 "reread partition table",
1940 Reread the partition table on C<device>.
1942 This uses the L<blockdev(8)> command.");
1944 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1945 [InitBasicFS, Always, TestOutput (
1946 (* Pick a file from cwd which isn't likely to change. *)
1947 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948 ["checksum"; "md5"; "/COPYING.LIB"]],
1949 Digest.to_hex (Digest.file "COPYING.LIB"))],
1950 "upload a file from the local machine",
1952 Upload local file C<filename> to C<remotefilename> on the
1955 C<filename> can also be a named pipe.
1957 See also C<guestfs_download>.");
1959 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1960 [InitBasicFS, Always, TestOutput (
1961 (* Pick a file from cwd which isn't likely to change. *)
1962 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1963 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1964 ["upload"; "testdownload.tmp"; "/upload"];
1965 ["checksum"; "md5"; "/upload"]],
1966 Digest.to_hex (Digest.file "COPYING.LIB"))],
1967 "download a file to the local machine",
1969 Download file C<remotefilename> and save it as C<filename>
1970 on the local machine.
1972 C<filename> can also be a named pipe.
1974 See also C<guestfs_upload>, C<guestfs_cat>.");
1976 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1977 [InitISOFS, Always, TestOutput (
1978 [["checksum"; "crc"; "/known-3"]], "2891671662");
1979 InitISOFS, Always, TestLastFail (
1980 [["checksum"; "crc"; "/notexists"]]);
1981 InitISOFS, Always, TestOutput (
1982 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1983 InitISOFS, Always, TestOutput (
1984 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1985 InitISOFS, Always, TestOutput (
1986 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1987 InitISOFS, Always, TestOutput (
1988 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1989 InitISOFS, Always, TestOutput (
1990 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1991 InitISOFS, Always, TestOutput (
1992 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1993 "compute MD5, SHAx or CRC checksum of file",
1995 This call computes the MD5, SHAx or CRC checksum of the
1998 The type of checksum to compute is given by the C<csumtype>
1999 parameter which must have one of the following values:
2005 Compute the cyclic redundancy check (CRC) specified by POSIX
2006 for the C<cksum> command.
2010 Compute the MD5 hash (using the C<md5sum> program).
2014 Compute the SHA1 hash (using the C<sha1sum> program).
2018 Compute the SHA224 hash (using the C<sha224sum> program).
2022 Compute the SHA256 hash (using the C<sha256sum> program).
2026 Compute the SHA384 hash (using the C<sha384sum> program).
2030 Compute the SHA512 hash (using the C<sha512sum> program).
2034 The checksum is returned as a printable string.");
2036 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2037 [InitBasicFS, Always, TestOutput (
2038 [["tar_in"; "../images/helloworld.tar"; "/"];
2039 ["cat"; "/hello"]], "hello\n")],
2040 "unpack tarfile to directory",
2042 This command uploads and unpacks local file C<tarfile> (an
2043 I<uncompressed> tar file) into C<directory>.
2045 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2047 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2049 "pack directory into tarfile",
2051 This command packs the contents of C<directory> and downloads
2052 it to local file C<tarfile>.
2054 To download a compressed tarball, use C<guestfs_tgz_out>.");
2056 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2057 [InitBasicFS, Always, TestOutput (
2058 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2059 ["cat"; "/hello"]], "hello\n")],
2060 "unpack compressed tarball to directory",
2062 This command uploads and unpacks local file C<tarball> (a
2063 I<gzip compressed> tar file) into C<directory>.
2065 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2067 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2069 "pack directory into compressed tarball",
2071 This command packs the contents of C<directory> and downloads
2072 it to local file C<tarball>.
2074 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2076 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2077 [InitBasicFS, Always, TestLastFail (
2079 ["mount_ro"; "/dev/sda1"; "/"];
2080 ["touch"; "/new"]]);
2081 InitBasicFS, Always, TestOutput (
2082 [["write_file"; "/new"; "data"; "0"];
2084 ["mount_ro"; "/dev/sda1"; "/"];
2085 ["cat"; "/new"]], "data")],
2086 "mount a guest disk, read-only",
2088 This is the same as the C<guestfs_mount> command, but it
2089 mounts the filesystem with the read-only (I<-o ro>) flag.");
2091 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2093 "mount a guest disk with mount options",
2095 This is the same as the C<guestfs_mount> command, but it
2096 allows you to set the mount options as for the
2097 L<mount(8)> I<-o> flag.
2099 If the C<options> parameter is an empty string, then
2100 no options are passed (all options default to whatever
2101 the filesystem uses).");
2103 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2105 "mount a guest disk with mount options and vfstype",
2107 This is the same as the C<guestfs_mount> command, but it
2108 allows you to set both the mount options and the vfstype
2109 as for the L<mount(8)> I<-o> and I<-t> flags.");
2111 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2113 "debugging and internals",
2115 The C<guestfs_debug> command exposes some internals of
2116 C<guestfsd> (the guestfs daemon) that runs inside the
2119 There is no comprehensive help for this command. You have
2120 to look at the file C<daemon/debug.c> in the libguestfs source
2121 to find out what you can do.");
2123 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2124 [InitEmpty, Always, TestOutputList (
2125 [["part_disk"; "/dev/sda"; "mbr"];
2126 ["pvcreate"; "/dev/sda1"];
2127 ["vgcreate"; "VG"; "/dev/sda1"];
2128 ["lvcreate"; "LV1"; "VG"; "50"];
2129 ["lvcreate"; "LV2"; "VG"; "50"];
2130 ["lvremove"; "/dev/VG/LV1"];
2131 ["lvs"]], ["/dev/VG/LV2"]);
2132 InitEmpty, Always, TestOutputList (
2133 [["part_disk"; "/dev/sda"; "mbr"];
2134 ["pvcreate"; "/dev/sda1"];
2135 ["vgcreate"; "VG"; "/dev/sda1"];
2136 ["lvcreate"; "LV1"; "VG"; "50"];
2137 ["lvcreate"; "LV2"; "VG"; "50"];
2138 ["lvremove"; "/dev/VG"];
2140 InitEmpty, Always, TestOutputList (
2141 [["part_disk"; "/dev/sda"; "mbr"];
2142 ["pvcreate"; "/dev/sda1"];
2143 ["vgcreate"; "VG"; "/dev/sda1"];
2144 ["lvcreate"; "LV1"; "VG"; "50"];
2145 ["lvcreate"; "LV2"; "VG"; "50"];
2146 ["lvremove"; "/dev/VG"];
2148 "remove an LVM logical volume",
2150 Remove an LVM logical volume C<device>, where C<device> is
2151 the path to the LV, such as C</dev/VG/LV>.
2153 You can also remove all LVs in a volume group by specifying
2154 the VG name, C</dev/VG>.");
2156 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2157 [InitEmpty, Always, TestOutputList (
2158 [["part_disk"; "/dev/sda"; "mbr"];
2159 ["pvcreate"; "/dev/sda1"];
2160 ["vgcreate"; "VG"; "/dev/sda1"];
2161 ["lvcreate"; "LV1"; "VG"; "50"];
2162 ["lvcreate"; "LV2"; "VG"; "50"];
2165 InitEmpty, Always, TestOutputList (
2166 [["part_disk"; "/dev/sda"; "mbr"];
2167 ["pvcreate"; "/dev/sda1"];
2168 ["vgcreate"; "VG"; "/dev/sda1"];
2169 ["lvcreate"; "LV1"; "VG"; "50"];
2170 ["lvcreate"; "LV2"; "VG"; "50"];
2173 "remove an LVM volume group",
2175 Remove an LVM volume group C<vgname>, (for example C<VG>).
2177 This also forcibly removes all logical volumes in the volume
2180 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2181 [InitEmpty, Always, TestOutputListOfDevices (
2182 [["part_disk"; "/dev/sda"; "mbr"];
2183 ["pvcreate"; "/dev/sda1"];
2184 ["vgcreate"; "VG"; "/dev/sda1"];
2185 ["lvcreate"; "LV1"; "VG"; "50"];
2186 ["lvcreate"; "LV2"; "VG"; "50"];
2188 ["pvremove"; "/dev/sda1"];
2190 InitEmpty, Always, TestOutputListOfDevices (
2191 [["part_disk"; "/dev/sda"; "mbr"];
2192 ["pvcreate"; "/dev/sda1"];
2193 ["vgcreate"; "VG"; "/dev/sda1"];
2194 ["lvcreate"; "LV1"; "VG"; "50"];
2195 ["lvcreate"; "LV2"; "VG"; "50"];
2197 ["pvremove"; "/dev/sda1"];
2199 InitEmpty, Always, TestOutputListOfDevices (
2200 [["part_disk"; "/dev/sda"; "mbr"];
2201 ["pvcreate"; "/dev/sda1"];
2202 ["vgcreate"; "VG"; "/dev/sda1"];
2203 ["lvcreate"; "LV1"; "VG"; "50"];
2204 ["lvcreate"; "LV2"; "VG"; "50"];
2206 ["pvremove"; "/dev/sda1"];
2208 "remove an LVM physical volume",
2210 This wipes a physical volume C<device> so that LVM will no longer
2213 The implementation uses the C<pvremove> command which refuses to
2214 wipe physical volumes that contain any volume groups, so you have
2215 to remove those first.");
2217 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2218 [InitBasicFS, Always, TestOutput (
2219 [["set_e2label"; "/dev/sda1"; "testlabel"];
2220 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2221 "set the ext2/3/4 filesystem label",
2223 This sets the ext2/3/4 filesystem label of the filesystem on
2224 C<device> to C<label>. Filesystem labels are limited to
2227 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2228 to return the existing label on a filesystem.");
2230 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2232 "get the ext2/3/4 filesystem label",
2234 This returns the ext2/3/4 filesystem label of the filesystem on
2237 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2238 (let uuid = uuidgen () in
2239 [InitBasicFS, Always, TestOutput (
2240 [["set_e2uuid"; "/dev/sda1"; uuid];
2241 ["get_e2uuid"; "/dev/sda1"]], uuid);
2242 InitBasicFS, Always, TestOutput (
2243 [["set_e2uuid"; "/dev/sda1"; "clear"];
2244 ["get_e2uuid"; "/dev/sda1"]], "");
2245 (* We can't predict what UUIDs will be, so just check the commands run. *)
2246 InitBasicFS, Always, TestRun (
2247 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2248 InitBasicFS, Always, TestRun (
2249 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2250 "set the ext2/3/4 filesystem UUID",
2252 This sets the ext2/3/4 filesystem UUID of the filesystem on
2253 C<device> to C<uuid>. The format of the UUID and alternatives
2254 such as C<clear>, C<random> and C<time> are described in the
2255 L<tune2fs(8)> manpage.
2257 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2258 to return the existing UUID of a filesystem.");
2260 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2262 "get the ext2/3/4 filesystem UUID",
2264 This returns the ext2/3/4 filesystem UUID of the filesystem on
2267 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2268 [InitBasicFS, Always, TestOutputInt (
2269 [["umount"; "/dev/sda1"];
2270 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2271 InitBasicFS, Always, TestOutputInt (
2272 [["umount"; "/dev/sda1"];
2273 ["zero"; "/dev/sda1"];
2274 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2275 "run the filesystem checker",
2277 This runs the filesystem checker (fsck) on C<device> which
2278 should have filesystem type C<fstype>.
2280 The returned integer is the status. See L<fsck(8)> for the
2281 list of status codes from C<fsck>.
2289 Multiple status codes can be summed together.
2293 A non-zero return code can mean \"success\", for example if
2294 errors have been corrected on the filesystem.
2298 Checking or repairing NTFS volumes is not supported
2303 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2305 ("zero", (RErr, [Device "device"]), 85, [],
2306 [InitBasicFS, Always, TestOutput (
2307 [["umount"; "/dev/sda1"];
2308 ["zero"; "/dev/sda1"];
2309 ["file"; "/dev/sda1"]], "data")],
2310 "write zeroes to the device",
2312 This command writes zeroes over the first few blocks of C<device>.
2314 How many blocks are zeroed isn't specified (but it's I<not> enough
2315 to securely wipe the device). It should be sufficient to remove
2316 any partition tables, filesystem superblocks and so on.
2318 See also: C<guestfs_scrub_device>.");
2320 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2321 (* Test disabled because grub-install incompatible with virtio-blk driver.
2322 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2324 [InitBasicFS, Disabled, TestOutputTrue (
2325 [["grub_install"; "/"; "/dev/sda1"];
2326 ["is_dir"; "/boot"]])],
2329 This command installs GRUB (the Grand Unified Bootloader) on
2330 C<device>, with the root directory being C<root>.
2332 Note: If grub-install reports the error
2333 \"No suitable drive was found in the generated device map.\"
2334 it may be that you need to create a C</boot/grub/device.map>
2335 file first that contains the mapping between grub device names
2336 and Linux device names. It is usually sufficient to create
2341 replacing C</dev/vda> with the name of the installation device.");
2343 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344 [InitBasicFS, Always, TestOutput (
2345 [["write_file"; "/old"; "file content"; "0"];
2346 ["cp"; "/old"; "/new"];
2347 ["cat"; "/new"]], "file content");
2348 InitBasicFS, Always, TestOutputTrue (
2349 [["write_file"; "/old"; "file content"; "0"];
2350 ["cp"; "/old"; "/new"];
2351 ["is_file"; "/old"]]);
2352 InitBasicFS, Always, TestOutput (
2353 [["write_file"; "/old"; "file content"; "0"];
2355 ["cp"; "/old"; "/dir/new"];
2356 ["cat"; "/dir/new"]], "file content")],
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2362 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363 [InitBasicFS, Always, TestOutput (
2364 [["mkdir"; "/olddir"];
2365 ["mkdir"; "/newdir"];
2366 ["write_file"; "/olddir/file"; "file content"; "0"];
2367 ["cp_a"; "/olddir"; "/newdir"];
2368 ["cat"; "/newdir/olddir/file"]], "file content")],
2369 "copy a file or directory recursively",
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2374 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375 [InitBasicFS, Always, TestOutput (
2376 [["write_file"; "/old"; "file content"; "0"];
2377 ["mv"; "/old"; "/new"];
2378 ["cat"; "/new"]], "file content");
2379 InitBasicFS, Always, TestOutputFalse (
2380 [["write_file"; "/old"; "file content"; "0"];
2381 ["mv"; "/old"; "/new"];
2382 ["is_file"; "/old"]])],
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2388 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389 [InitEmpty, Always, TestRun (
2390 [["drop_caches"; "3"]])],
2391 "drop kernel page cache, dentries and inodes",
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches. The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2398 Setting C<whattodrop> to 3 should drop everything.
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2403 ("dmesg", (RString "kmsgs", []), 91, [],
2404 [InitEmpty, Always, TestRun (
2406 "return kernel messages",
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel. This is sometimes useful for extended
2410 debugging of problems.
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2417 ("ping_daemon", (RErr, []), 92, [],
2418 [InitEmpty, Always, TestRun (
2419 [["ping_daemon"]])],
2420 "ping the guest daemon",
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess. Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2427 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428 [InitBasicFS, Always, TestOutputTrue (
2429 [["write_file"; "/file1"; "contents of a file"; "0"];
2430 ["cp"; "/file1"; "/file2"];
2431 ["equal"; "/file1"; "/file2"]]);
2432 InitBasicFS, Always, TestOutputFalse (
2433 [["write_file"; "/file1"; "contents of a file"; "0"];
2434 ["write_file"; "/file2"; "contents of another file"; "0"];
2435 ["equal"; "/file1"; "/file2"]]);
2436 InitBasicFS, Always, TestLastFail (
2437 [["equal"; "/file1"; "/file2"]])],
2438 "test if two files have equal contents",
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2443 The external L<cmp(1)> program is used for the comparison.");
2445 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446 [InitISOFS, Always, TestOutputList (
2447 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448 InitISOFS, Always, TestOutputList (
2449 [["strings"; "/empty"]], [])],
2450 "print the printable strings in a file",
2452 This runs the L<strings(1)> command on a file and returns
2453 the list of printable strings found.");
2455 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2456 [InitISOFS, Always, TestOutputList (
2457 [["strings_e"; "b"; "/known-5"]], []);
2458 InitBasicFS, Disabled, TestOutputList (
2459 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2460 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2461 "print the printable strings in a file",
2463 This is like the C<guestfs_strings> command, but allows you to
2464 specify the encoding of strings that are looked for in
2465 the source file C<path>.
2467 Allowed encodings are:
2473 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2474 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2478 Single 8-bit-byte characters.
2482 16-bit big endian strings such as those encoded in
2483 UTF-16BE or UCS-2BE.
2485 =item l (lower case letter L)
2487 16-bit little endian such as UTF-16LE and UCS-2LE.
2488 This is useful for examining binaries in Windows guests.
2492 32-bit big endian such as UCS-4BE.
2496 32-bit little endian such as UCS-4LE.
2500 The returned strings are transcoded to UTF-8.");
2502 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2503 [InitISOFS, Always, TestOutput (
2504 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2505 (* Test for RHBZ#501888c2 regression which caused large hexdump
2506 * commands to segfault.
2508 InitISOFS, Always, TestRun (
2509 [["hexdump"; "/100krandom"]])],
2510 "dump a file in hexadecimal",
2512 This runs C<hexdump -C> on the given C<path>. The result is
2513 the human-readable, canonical hex dump of the file.");
2515 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2516 [InitNone, Always, TestOutput (
2517 [["part_disk"; "/dev/sda"; "mbr"];
2518 ["mkfs"; "ext3"; "/dev/sda1"];
2519 ["mount_options"; ""; "/dev/sda1"; "/"];
2520 ["write_file"; "/new"; "test file"; "0"];
2521 ["umount"; "/dev/sda1"];
2522 ["zerofree"; "/dev/sda1"];
2523 ["mount_options"; ""; "/dev/sda1"; "/"];
2524 ["cat"; "/new"]], "test file")],
2525 "zero unused inodes and disk blocks on ext2/3 filesystem",
2527 This runs the I<zerofree> program on C<device>. This program
2528 claims to zero unused inodes and disk blocks on an ext2/3
2529 filesystem, thus making it possible to compress the filesystem
2532 You should B<not> run this program if the filesystem is
2535 It is possible that using this program can damage the filesystem
2536 or data on the filesystem.");
2538 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2540 "resize an LVM physical volume",
2542 This resizes (expands or shrinks) an existing LVM physical
2543 volume to match the new size of the underlying device.");
2545 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2546 Int "cyls"; Int "heads"; Int "sectors";
2547 String "line"]), 99, [DangerWillRobinson],
2549 "modify a single partition on a block device",
2551 This runs L<sfdisk(8)> option to modify just the single
2552 partition C<n> (note: C<n> counts from 1).
2554 For other parameters, see C<guestfs_sfdisk>. You should usually
2555 pass C<0> for the cyls/heads/sectors parameters.
2557 See also: C<guestfs_part_add>");
2559 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2561 "display the partition table",
2563 This displays the partition table on C<device>, in the
2564 human-readable output of the L<sfdisk(8)> command. It is
2565 not intended to be parsed.
2567 See also: C<guestfs_part_list>");
2569 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2571 "display the kernel geometry",
2573 This displays the kernel's idea of the geometry of C<device>.
2575 The result is in human-readable format, and not designed to
2578 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2580 "display the disk geometry from the partition table",
2582 This displays the disk geometry of C<device> read from the
2583 partition table. Especially in the case where the underlying
2584 block device has been resized, this can be different from the
2585 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2587 The result is in human-readable format, and not designed to
2590 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2592 "activate or deactivate all volume groups",
2594 This command activates or (if C<activate> is false) deactivates
2595 all logical volumes in all volume groups.
2596 If activated, then they are made known to the
2597 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2598 then those devices disappear.
2600 This command is the same as running C<vgchange -a y|n>");
2602 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2604 "activate or deactivate some volume groups",
2606 This command activates or (if C<activate> is false) deactivates
2607 all logical volumes in the listed volume groups C<volgroups>.
2608 If activated, then they are made known to the
2609 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2610 then those devices disappear.
2612 This command is the same as running C<vgchange -a y|n volgroups...>
2614 Note that if C<volgroups> is an empty list then B<all> volume groups
2615 are activated or deactivated.");
2617 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2618 [InitNone, Always, TestOutput (
2619 [["part_disk"; "/dev/sda"; "mbr"];
2620 ["pvcreate"; "/dev/sda1"];
2621 ["vgcreate"; "VG"; "/dev/sda1"];
2622 ["lvcreate"; "LV"; "VG"; "10"];
2623 ["mkfs"; "ext2"; "/dev/VG/LV"];
2624 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2625 ["write_file"; "/new"; "test content"; "0"];
2627 ["lvresize"; "/dev/VG/LV"; "20"];
2628 ["e2fsck_f"; "/dev/VG/LV"];
2629 ["resize2fs"; "/dev/VG/LV"];
2630 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2631 ["cat"; "/new"]], "test content");
2632 InitNone, Always, TestRun (
2633 (* Make an LV smaller to test RHBZ#587484. *)
2634 [["part_disk"; "/dev/sda"; "mbr"];
2635 ["pvcreate"; "/dev/sda1"];
2636 ["vgcreate"; "VG"; "/dev/sda1"];
2637 ["lvcreate"; "LV"; "VG"; "20"];
2638 ["lvresize"; "/dev/VG/LV"; "10"]])],
2639 "resize an LVM logical volume",
2641 This resizes (expands or shrinks) an existing LVM logical
2642 volume to C<mbytes>. When reducing, data in the reduced part
2645 ("resize2fs", (RErr, [Device "device"]), 106, [],
2646 [], (* lvresize tests this *)
2647 "resize an ext2, ext3 or ext4 filesystem",
2649 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2650 the underlying device.
2652 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2653 on the C<device> before calling this command. For unknown reasons
2654 C<resize2fs> sometimes gives an error about this and sometimes not.
2655 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2656 calling this function.");
2658 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2659 [InitBasicFS, Always, TestOutputList (
2660 [["find"; "/"]], ["lost+found"]);
2661 InitBasicFS, Always, TestOutputList (
2665 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2666 InitBasicFS, Always, TestOutputList (
2667 [["mkdir_p"; "/a/b/c"];
2668 ["touch"; "/a/b/c/d"];
2669 ["find"; "/a/b/"]], ["c"; "c/d"])],
2670 "find all files and directories",
2672 This command lists out all files and directories, recursively,
2673 starting at C<directory>. It is essentially equivalent to
2674 running the shell command C<find directory -print> but some
2675 post-processing happens on the output, described below.
2677 This returns a list of strings I<without any prefix>. Thus
2678 if the directory structure was:
2684 then the returned list from C<guestfs_find> C</tmp> would be
2692 If C<directory> is not a directory, then this command returns
2695 The returned list is sorted.
2697 See also C<guestfs_find0>.");
2699 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2700 [], (* lvresize tests this *)
2701 "check an ext2/ext3 filesystem",
2703 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2704 filesystem checker on C<device>, noninteractively (C<-p>),
2705 even if the filesystem appears to be clean (C<-f>).
2707 This command is only needed because of C<guestfs_resize2fs>
2708 (q.v.). Normally you should use C<guestfs_fsck>.");
2710 ("sleep", (RErr, [Int "secs"]), 109, [],
2711 [InitNone, Always, TestRun (
2713 "sleep for some seconds",
2715 Sleep for C<secs> seconds.");
2717 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2718 [InitNone, Always, TestOutputInt (
2719 [["part_disk"; "/dev/sda"; "mbr"];
2720 ["mkfs"; "ntfs"; "/dev/sda1"];
2721 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2722 InitNone, Always, TestOutputInt (
2723 [["part_disk"; "/dev/sda"; "mbr"];
2724 ["mkfs"; "ext2"; "/dev/sda1"];
2725 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2726 "probe NTFS volume",
2728 This command runs the L<ntfs-3g.probe(8)> command which probes
2729 an NTFS C<device> for mountability. (Not all NTFS volumes can
2730 be mounted read-write, and some cannot be mounted at all).
2732 C<rw> is a boolean flag. Set it to true if you want to test
2733 if the volume can be mounted read-write. Set it to false if
2734 you want to test if the volume can be mounted read-only.
2736 The return value is an integer which C<0> if the operation
2737 would succeed, or some non-zero value documented in the
2738 L<ntfs-3g.probe(8)> manual page.");
2740 ("sh", (RString "output", [String "command"]), 111, [],
2741 [], (* XXX needs tests *)
2742 "run a command via the shell",
2744 This call runs a command from the guest filesystem via the
2747 This is like C<guestfs_command>, but passes the command to:
2749 /bin/sh -c \"command\"
2751 Depending on the guest's shell, this usually results in
2752 wildcards being expanded, shell expressions being interpolated
2755 All the provisos about C<guestfs_command> apply to this call.");
2757 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2758 [], (* XXX needs tests *)
2759 "run a command via the shell returning lines",
2761 This is the same as C<guestfs_sh>, but splits the result
2762 into a list of lines.
2764 See also: C<guestfs_command_lines>");
2766 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2767 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2768 * code in stubs.c, since all valid glob patterns must start with "/".
2769 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2771 [InitBasicFS, Always, TestOutputList (
2772 [["mkdir_p"; "/a/b/c"];
2773 ["touch"; "/a/b/c/d"];
2774 ["touch"; "/a/b/c/e"];
2775 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2776 InitBasicFS, Always, TestOutputList (
2777 [["mkdir_p"; "/a/b/c"];
2778 ["touch"; "/a/b/c/d"];
2779 ["touch"; "/a/b/c/e"];
2780 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2781 InitBasicFS, Always, TestOutputList (
2782 [["mkdir_p"; "/a/b/c"];
2783 ["touch"; "/a/b/c/d"];
2784 ["touch"; "/a/b/c/e"];
2785 ["glob_expand"; "/a/*/x/*"]], [])],
2786 "expand a wildcard path",
2788 This command searches for all the pathnames matching
2789 C<pattern> according to the wildcard expansion rules
2792 If no paths match, then this returns an empty list
2793 (note: not an error).
2795 It is just a wrapper around the C L<glob(3)> function
2796 with flags C<GLOB_MARK|GLOB_BRACE>.
2797 See that manual page for more details.");
2799 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2800 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2801 [["scrub_device"; "/dev/sdc"]])],
2802 "scrub (securely wipe) a device",
2804 This command writes patterns over C<device> to make data retrieval
2807 It is an interface to the L<scrub(1)> program. See that
2808 manual page for more details.");
2810 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2811 [InitBasicFS, Always, TestRun (
2812 [["write_file"; "/file"; "content"; "0"];
2813 ["scrub_file"; "/file"]])],
2814 "scrub (securely wipe) a file",
2816 This command writes patterns over a file to make data retrieval
2819 The file is I<removed> after scrubbing.
2821 It is an interface to the L<scrub(1)> program. See that
2822 manual page for more details.");
2824 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2825 [], (* XXX needs testing *)
2826 "scrub (securely wipe) free space",
2828 This command creates the directory C<dir> and then fills it
2829 with files until the filesystem is full, and scrubs the files
2830 as for C<guestfs_scrub_file>, and deletes them.
2831 The intention is to scrub any free space on the partition
2834 It is an interface to the L<scrub(1)> program. See that
2835 manual page for more details.");
2837 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2838 [InitBasicFS, Always, TestRun (
2840 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2841 "create a temporary directory",
2843 This command creates a temporary directory. The
2844 C<template> parameter should be a full pathname for the
2845 temporary directory name with the final six characters being
2848 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2849 the second one being suitable for Windows filesystems.
2851 The name of the temporary directory that was created
2854 The temporary directory is created with mode 0700
2855 and is owned by root.
2857 The caller is responsible for deleting the temporary
2858 directory and its contents after use.
2860 See also: L<mkdtemp(3)>");
2862 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2863 [InitISOFS, Always, TestOutputInt (
2864 [["wc_l"; "/10klines"]], 10000)],
2865 "count lines in a file",
2867 This command counts the lines in a file, using the
2868 C<wc -l> external command.");
2870 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2871 [InitISOFS, Always, TestOutputInt (
2872 [["wc_w"; "/10klines"]], 10000)],
2873 "count words in a file",
2875 This command counts the words in a file, using the
2876 C<wc -w> external command.");
2878 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2879 [InitISOFS, Always, TestOutputInt (
2880 [["wc_c"; "/100kallspaces"]], 102400)],
2881 "count characters in a file",
2883 This command counts the characters in a file, using the
2884 C<wc -c> external command.");
2886 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2887 [InitISOFS, Always, TestOutputList (
2888 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2889 "return first 10 lines of a file",
2891 This command returns up to the first 10 lines of a file as
2892 a list of strings.");
2894 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2895 [InitISOFS, Always, TestOutputList (
2896 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2897 InitISOFS, Always, TestOutputList (
2898 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2899 InitISOFS, Always, TestOutputList (
2900 [["head_n"; "0"; "/10klines"]], [])],
2901 "return first N lines of a file",
2903 If the parameter C<nrlines> is a positive number, this returns the first
2904 C<nrlines> lines of the file C<path>.
2906 If the parameter C<nrlines> is a negative number, this returns lines
2907 from the file C<path>, excluding the last C<nrlines> lines.
2909 If the parameter C<nrlines> is zero, this returns an empty list.");
2911 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2912 [InitISOFS, Always, TestOutputList (
2913 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2914 "return last 10 lines of a file",
2916 This command returns up to the last 10 lines of a file as
2917 a list of strings.");
2919 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2920 [InitISOFS, Always, TestOutputList (
2921 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2922 InitISOFS, Always, TestOutputList (
2923 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2924 InitISOFS, Always, TestOutputList (
2925 [["tail_n"; "0"; "/10klines"]], [])],
2926 "return last N lines of a file",
2928 If the parameter C<nrlines> is a positive number, this returns the last
2929 C<nrlines> lines of the file C<path>.
2931 If the parameter C<nrlines> is a negative number, this returns lines
2932 from the file C<path>, starting with the C<-nrlines>th line.
2934 If the parameter C<nrlines> is zero, this returns an empty list.");
2936 ("df", (RString "output", []), 125, [],
2937 [], (* XXX Tricky to test because it depends on the exact format
2938 * of the 'df' command and other imponderables.
2940 "report file system disk space usage",
2942 This command runs the C<df> command to report disk space used.
2944 This command is mostly useful for interactive sessions. It
2945 is I<not> intended that you try to parse the output string.
2946 Use C<statvfs> from programs.");
2948 ("df_h", (RString "output", []), 126, [],
2949 [], (* XXX Tricky to test because it depends on the exact format
2950 * of the 'df' command and other imponderables.
2952 "report file system disk space usage (human readable)",
2954 This command runs the C<df -h> command to report disk space used
2955 in human-readable format.
2957 This command is mostly useful for interactive sessions. It
2958 is I<not> intended that you try to parse the output string.
2959 Use C<statvfs> from programs.");
2961 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2962 [InitISOFS, Always, TestOutputInt (
2963 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2964 "estimate file space usage",
2966 This command runs the C<du -s> command to estimate file space
2969 C<path> can be a file or a directory. If C<path> is a directory
2970 then the estimate includes the contents of the directory and all
2971 subdirectories (recursively).
2973 The result is the estimated size in I<kilobytes>
2974 (ie. units of 1024 bytes).");
2976 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2977 [InitISOFS, Always, TestOutputList (
2978 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2979 "list files in an initrd",
2981 This command lists out files contained in an initrd.
2983 The files are listed without any initial C</> character. The
2984 files are listed in the order they appear (not necessarily
2985 alphabetical). Directory names are listed as separate items.
2987 Old Linux kernels (2.4 and earlier) used a compressed ext2
2988 filesystem as initrd. We I<only> support the newer initramfs
2989 format (compressed cpio files).");
2991 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2993 "mount a file using the loop device",
2995 This command lets you mount C<file> (a filesystem image
2996 in a file) on a mount point. It is entirely equivalent to
2997 the command C<mount -o loop file mountpoint>.");
2999 ("mkswap", (RErr, [Device "device"]), 130, [],
3000 [InitEmpty, Always, TestRun (
3001 [["part_disk"; "/dev/sda"; "mbr"];
3002 ["mkswap"; "/dev/sda1"]])],
3003 "create a swap partition",
3005 Create a swap partition on C<device>.");
3007 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3008 [InitEmpty, Always, TestRun (
3009 [["part_disk"; "/dev/sda"; "mbr"];
3010 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3011 "create a swap partition with a label",
3013 Create a swap partition on C<device> with label C<label>.
3015 Note that you cannot attach a swap label to a block device
3016 (eg. C</dev/sda>), just to a partition. This appears to be
3017 a limitation of the kernel or swap tools.");
3019 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3020 (let uuid = uuidgen () in
3021 [InitEmpty, Always, TestRun (
3022 [["part_disk"; "/dev/sda"; "mbr"];
3023 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3024 "create a swap partition with an explicit UUID",
3026 Create a swap partition on C<device> with UUID C<uuid>.");
3028 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3029 [InitBasicFS, Always, TestOutputStruct (
3030 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3031 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3032 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3033 InitBasicFS, Always, TestOutputStruct (
3034 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3035 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3036 "make block, character or FIFO devices",
3038 This call creates block or character special devices, or
3039 named pipes (FIFOs).
3041 The C<mode> parameter should be the mode, using the standard
3042 constants. C<devmajor> and C<devminor> are the
3043 device major and minor numbers, only used when creating block
3044 and character special devices.
3046 Note that, just like L<mknod(2)>, the mode must be bitwise
3047 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3048 just creates a regular file). These constants are
3049 available in the standard Linux header files, or you can use
3050 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3051 which are wrappers around this command which bitwise OR
3052 in the appropriate constant for you.
3054 The mode actually set is affected by the umask.");
3056 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3057 [InitBasicFS, Always, TestOutputStruct (
3058 [["mkfifo"; "0o777"; "/node"];
3059 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3060 "make FIFO (named pipe)",
3062 This call creates a FIFO (named pipe) called C<path> with
3063 mode C<mode>. It is just a convenient wrapper around
3066 The mode actually set is affected by the umask.");
3068 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3069 [InitBasicFS, Always, TestOutputStruct (
3070 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3071 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3072 "make block device node",
3074 This call creates a block device node called C<path> with
3075 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3076 It is just a convenient wrapper around C<guestfs_mknod>.
3078 The mode actually set is affected by the umask.");
3080 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3081 [InitBasicFS, Always, TestOutputStruct (
3082 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3083 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3084 "make char device node",
3086 This call creates a char device node called C<path> with
3087 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3088 It is just a convenient wrapper around C<guestfs_mknod>.
3090 The mode actually set is affected by the umask.");
3092 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3093 [InitEmpty, Always, TestOutputInt (
3094 [["umask"; "0o22"]], 0o22)],
3095 "set file mode creation mask (umask)",
3097 This function sets the mask used for creating new files and
3098 device nodes to C<mask & 0777>.
3100 Typical umask values would be C<022> which creates new files
3101 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3102 C<002> which creates new files with permissions like
3103 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3105 The default umask is C<022>. This is important because it
3106 means that directories and device nodes will be created with
3107 C<0644> or C<0755> mode even if you specify C<0777>.
3109 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3111 This call returns the previous umask.");
3113 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3115 "read directories entries",
3117 This returns the list of directory entries in directory C<dir>.
3119 All entries in the directory are returned, including C<.> and
3120 C<..>. The entries are I<not> sorted, but returned in the same
3121 order as the underlying filesystem.
3123 Also this call returns basic file type information about each
3124 file. The C<ftyp> field will contain one of the following characters:
3162 The L<readdir(3)> call returned a C<d_type> field with an
3167 This function is primarily intended for use by programs. To
3168 get a simple list of names, use C<guestfs_ls>. To get a printable
3169 directory for human consumption, use C<guestfs_ll>.");
3171 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3173 "create partitions on a block device",
3175 This is a simplified interface to the C<guestfs_sfdisk>
3176 command, where partition sizes are specified in megabytes
3177 only (rounded to the nearest cylinder) and you don't need
3178 to specify the cyls, heads and sectors parameters which
3179 were rarely if ever used anyway.
3181 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3182 and C<guestfs_part_disk>");
3184 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3186 "determine file type inside a compressed file",
3188 This command runs C<file> after first decompressing C<path>
3191 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3193 Since 1.0.63, use C<guestfs_file> instead which can now
3194 process compressed files.");
3196 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3198 "list extended attributes of a file or directory",
3200 This call lists the extended attributes of the file or directory
3203 At the system call level, this is a combination of the
3204 L<listxattr(2)> and L<getxattr(2)> calls.
3206 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3208 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3210 "list extended attributes of a file or directory",
3212 This is the same as C<guestfs_getxattrs>, but if C<path>
3213 is a symbolic link, then it returns the extended attributes
3214 of the link itself.");
3216 ("setxattr", (RErr, [String "xattr";
3217 String "val"; Int "vallen"; (* will be BufferIn *)
3218 Pathname "path"]), 143, [Optional "linuxxattrs"],
3220 "set extended attribute of a file or directory",
3222 This call sets the extended attribute named C<xattr>
3223 of the file C<path> to the value C<val> (of length C<vallen>).
3224 The value is arbitrary 8 bit data.
3226 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3228 ("lsetxattr", (RErr, [String "xattr";
3229 String "val"; Int "vallen"; (* will be BufferIn *)
3230 Pathname "path"]), 144, [Optional "linuxxattrs"],
3232 "set extended attribute of a file or directory",
3234 This is the same as C<guestfs_setxattr>, but if C<path>
3235 is a symbolic link, then it sets an extended attribute
3236 of the link itself.");
3238 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3240 "remove extended attribute of a file or directory",
3242 This call removes the extended attribute named C<xattr>
3243 of the file C<path>.
3245 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3247 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3249 "remove extended attribute of a file or directory",
3251 This is the same as C<guestfs_removexattr>, but if C<path>
3252 is a symbolic link, then it removes an extended attribute
3253 of the link itself.");
3255 ("mountpoints", (RHashtable "mps", []), 147, [],
3259 This call is similar to C<guestfs_mounts>. That call returns
3260 a list of devices. This one returns a hash table (map) of
3261 device name to directory where the device is mounted.");
3263 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3264 (* This is a special case: while you would expect a parameter
3265 * of type "Pathname", that doesn't work, because it implies
3266 * NEED_ROOT in the generated calling code in stubs.c, and
3267 * this function cannot use NEED_ROOT.
3270 "create a mountpoint",
3272 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3273 specialized calls that can be used to create extra mountpoints
3274 before mounting the first filesystem.
3276 These calls are I<only> necessary in some very limited circumstances,
3277 mainly the case where you want to mount a mix of unrelated and/or
3278 read-only filesystems together.
3280 For example, live CDs often contain a \"Russian doll\" nest of
3281 filesystems, an ISO outer layer, with a squashfs image inside, with
3282 an ext2/3 image inside that. You can unpack this as follows
3285 add-ro Fedora-11-i686-Live.iso
3288 mkmountpoint /squash
3291 mount-loop /cd/LiveOS/squashfs.img /squash
3292 mount-loop /squash/LiveOS/ext3fs.img /ext3
3294 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3296 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3298 "remove a mountpoint",
3300 This calls removes a mountpoint that was previously created
3301 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3302 for full details.");
3304 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3305 [InitISOFS, Always, TestOutputBuffer (
3306 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3307 (* Test various near large, large and too large files (RHBZ#589039). *)
3308 InitBasicFS, Always, TestLastFail (
3310 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3311 ["read_file"; "/a"]]);
3312 InitBasicFS, Always, TestLastFail (
3314 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3315 ["read_file"; "/a"]]);
3316 InitBasicFS, Always, TestLastFail (
3318 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3319 ["read_file"; "/a"]])],
3322 This calls returns the contents of the file C<path> as a
3325 Unlike C<guestfs_cat>, this function can correctly
3326 handle files that contain embedded ASCII NUL characters.
3327 However unlike C<guestfs_download>, this function is limited
3328 in the total size of file that can be handled.");
3330 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3331 [InitISOFS, Always, TestOutputList (
3332 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3333 InitISOFS, Always, TestOutputList (
3334 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3335 "return lines matching a pattern",
3337 This calls the external C<grep> program and returns the
3340 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3341 [InitISOFS, Always, TestOutputList (
3342 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3343 "return lines matching a pattern",
3345 This calls the external C<egrep> program and returns the
3348 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3349 [InitISOFS, Always, TestOutputList (
3350 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3351 "return lines matching a pattern",
3353 This calls the external C<fgrep> program and returns the
3356 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3357 [InitISOFS, Always, TestOutputList (
3358 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359 "return lines matching a pattern",
3361 This calls the external C<grep -i> program and returns the
3364 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3365 [InitISOFS, Always, TestOutputList (
3366 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3367 "return lines matching a pattern",
3369 This calls the external C<egrep -i> program and returns the
3372 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3373 [InitISOFS, Always, TestOutputList (
3374 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3375 "return lines matching a pattern",
3377 This calls the external C<fgrep -i> program and returns the
3380 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3381 [InitISOFS, Always, TestOutputList (
3382 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383 "return lines matching a pattern",
3385 This calls the external C<zgrep> program and returns the
3388 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3389 [InitISOFS, Always, TestOutputList (
3390 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3391 "return lines matching a pattern",
3393 This calls the external C<zegrep> program and returns the
3396 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3397 [InitISOFS, Always, TestOutputList (
3398 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3399 "return lines matching a pattern",
3401 This calls the external C<zfgrep> program and returns the
3404 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3405 [InitISOFS, Always, TestOutputList (
3406 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407 "return lines matching a pattern",
3409 This calls the external C<zgrep -i> program and returns the
3412 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3413 [InitISOFS, Always, TestOutputList (
3414 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3415 "return lines matching a pattern",
3417 This calls the external C<zegrep -i> program and returns the
3420 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3421 [InitISOFS, Always, TestOutputList (
3422 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3423 "return lines matching a pattern",
3425 This calls the external C<zfgrep -i> program and returns the
3428 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3429 [InitISOFS, Always, TestOutput (
3430 [["realpath"; "/../directory"]], "/directory")],
3431 "canonicalized absolute pathname",
3433 Return the canonicalized absolute pathname of C<path>. The
3434 returned path has no C<.>, C<..> or symbolic link path elements.");
3436 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3437 [InitBasicFS, Always, TestOutputStruct (
3440 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3441 "create a hard link",
3443 This command creates a hard link using the C<ln> command.");
3445 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3446 [InitBasicFS, Always, TestOutputStruct (
3449 ["ln_f"; "/a"; "/b"];
3450 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3451 "create a hard link",
3453 This command creates a hard link using the C<ln -f> command.
3454 The C<-f> option removes the link (C<linkname>) if it exists already.");
3456 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3457 [InitBasicFS, Always, TestOutputStruct (
3459 ["ln_s"; "a"; "/b"];
3460 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3461 "create a symbolic link",
3463 This command creates a symbolic link using the C<ln -s> command.");
3465 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3466 [InitBasicFS, Always, TestOutput (
3467 [["mkdir_p"; "/a/b"];
3468 ["touch"; "/a/b/c"];
3469 ["ln_sf"; "../d"; "/a/b/c"];
3470 ["readlink"; "/a/b/c"]], "../d")],
3471 "create a symbolic link",
3473 This command creates a symbolic link using the C<ln -sf> command,
3474 The C<-f> option removes the link (C<linkname>) if it exists already.");
3476 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3477 [] (* XXX tested above *),
3478 "read the target of a symbolic link",
3480 This command reads the target of a symbolic link.");
3482 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3483 [InitBasicFS, Always, TestOutputStruct (
3484 [["fallocate"; "/a"; "1000000"];
3485 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3486 "preallocate a file in the guest filesystem",
3488 This command preallocates a file (containing zero bytes) named
3489 C<path> of size C<len> bytes. If the file exists already, it
3492 Do not confuse this with the guestfish-specific
3493 C<alloc> command which allocates a file in the host and
3494 attaches it as a device.");
3496 ("swapon_device", (RErr, [Device "device"]), 170, [],
3497 [InitPartition, Always, TestRun (
3498 [["mkswap"; "/dev/sda1"];
3499 ["swapon_device"; "/dev/sda1"];
3500 ["swapoff_device"; "/dev/sda1"]])],
3501 "enable swap on device",
3503 This command enables the libguestfs appliance to use the
3504 swap device or partition named C<device>. The increased
3505 memory is made available for all commands, for example
3506 those run using C<guestfs_command> or C<guestfs_sh>.
3508 Note that you should not swap to existing guest swap
3509 partitions unless you know what you are doing. They may
3510 contain hibernation information, or other information that
3511 the guest doesn't want you to trash. You also risk leaking
3512 information about the host to the guest this way. Instead,
3513 attach a new host device to the guest and swap on that.");
3515 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3516 [], (* XXX tested by swapon_device *)
3517 "disable swap on device",
3519 This command disables the libguestfs appliance swap
3520 device or partition named C<device>.
3521 See C<guestfs_swapon_device>.");
3523 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3524 [InitBasicFS, Always, TestRun (
3525 [["fallocate"; "/swap"; "8388608"];
3526 ["mkswap_file"; "/swap"];
3527 ["swapon_file"; "/swap"];
3528 ["swapoff_file"; "/swap"]])],
3529 "enable swap on file",
3531 This command enables swap to a file.
3532 See C<guestfs_swapon_device> for other notes.");
3534 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3535 [], (* XXX tested by swapon_file *)
3536 "disable swap on file",
3538 This command disables the libguestfs appliance swap on file.");
3540 ("swapon_label", (RErr, [String "label"]), 174, [],
3541 [InitEmpty, Always, TestRun (
3542 [["part_disk"; "/dev/sdb"; "mbr"];
3543 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3544 ["swapon_label"; "swapit"];
3545 ["swapoff_label"; "swapit"];
3546 ["zero"; "/dev/sdb"];
3547 ["blockdev_rereadpt"; "/dev/sdb"]])],
3548 "enable swap on labeled swap partition",
3550 This command enables swap to a labeled swap partition.
3551 See C<guestfs_swapon_device> for other notes.");
3553 ("swapoff_label", (RErr, [String "label"]), 175, [],
3554 [], (* XXX tested by swapon_label *)
3555 "disable swap on labeled swap partition",
3557 This command disables the libguestfs appliance swap on
3558 labeled swap partition.");
3560 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3561 (let uuid = uuidgen () in
3562 [InitEmpty, Always, TestRun (
3563 [["mkswap_U"; uuid; "/dev/sdb"];
3564 ["swapon_uuid"; uuid];
3565 ["swapoff_uuid"; uuid]])]),
3566 "enable swap on swap partition by UUID",
3568 This command enables swap to a swap partition with the given UUID.
3569 See C<guestfs_swapon_device> for other notes.");
3571 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3572 [], (* XXX tested by swapon_uuid *)
3573 "disable swap on swap partition by UUID",
3575 This command disables the libguestfs appliance swap partition
3576 with the given UUID.");
3578 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3579 [InitBasicFS, Always, TestRun (
3580 [["fallocate"; "/swap"; "8388608"];
3581 ["mkswap_file"; "/swap"]])],
3582 "create a swap file",
3586 This command just writes a swap file signature to an existing
3587 file. To create the file itself, use something like C<guestfs_fallocate>.");
3589 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3590 [InitISOFS, Always, TestRun (
3591 [["inotify_init"; "0"]])],
3592 "create an inotify handle",
3594 This command creates a new inotify handle.
3595 The inotify subsystem can be used to notify events which happen to
3596 objects in the guest filesystem.
3598 C<maxevents> is the maximum number of events which will be
3599 queued up between calls to C<guestfs_inotify_read> or
3600 C<guestfs_inotify_files>.
3601 If this is passed as C<0>, then the kernel (or previously set)
3602 default is used. For Linux 2.6.29 the default was 16384 events.
3603 Beyond this limit, the kernel throws away events, but records
3604 the fact that it threw them away by setting a flag
3605 C<IN_Q_OVERFLOW> in the returned structure list (see
3606 C<guestfs_inotify_read>).
3608 Before any events are generated, you have to add some
3609 watches to the internal watch list. See:
3610 C<guestfs_inotify_add_watch>,
3611 C<guestfs_inotify_rm_watch> and
3612 C<guestfs_inotify_watch_all>.
3614 Queued up events should be read periodically by calling
3615 C<guestfs_inotify_read>
3616 (or C<guestfs_inotify_files> which is just a helpful
3617 wrapper around C<guestfs_inotify_read>). If you don't
3618 read the events out often enough then you risk the internal
3621 The handle should be closed after use by calling
3622 C<guestfs_inotify_close>. This also removes any
3623 watches automatically.
3625 See also L<inotify(7)> for an overview of the inotify interface
3626 as exposed by the Linux kernel, which is roughly what we expose
3627 via libguestfs. Note that there is one global inotify handle
3628 per libguestfs instance.");
3630 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3631 [InitBasicFS, Always, TestOutputList (
3632 [["inotify_init"; "0"];
3633 ["inotify_add_watch"; "/"; "1073741823"];
3636 ["inotify_files"]], ["a"; "b"])],
3637 "add an inotify watch",
3639 Watch C<path> for the events listed in C<mask>.
3641 Note that if C<path> is a directory then events within that
3642 directory are watched, but this does I<not> happen recursively
3643 (in subdirectories).
3645 Note for non-C or non-Linux callers: the inotify events are
3646 defined by the Linux kernel ABI and are listed in
3647 C</usr/include/sys/inotify.h>.");
3649 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3651 "remove an inotify watch",
3653 Remove a previously defined inotify watch.
3654 See C<guestfs_inotify_add_watch>.");
3656 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3658 "return list of inotify events",
3660 Return the complete queue of events that have happened
3661 since the previous read call.
3663 If no events have happened, this returns an empty list.
3665 I<Note>: In order to make sure that all events have been
3666 read, you must call this function repeatedly until it
3667 returns an empty list. The reason is that the call will
3668 read events up to the maximum appliance-to-host message
3669 size and leave remaining events in the queue.");
3671 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3673 "return list of watched files that had events",
3675 This function is a helpful wrapper around C<guestfs_inotify_read>
3676 which just returns a list of pathnames of objects that were
3677 touched. The returned pathnames are sorted and deduplicated.");
3679 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3681 "close the inotify handle",
3683 This closes the inotify handle which was previously
3684 opened by inotify_init. It removes all watches, throws
3685 away any pending events, and deallocates all resources.");
3687 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3689 "set SELinux security context",
3691 This sets the SELinux security context of the daemon
3692 to the string C<context>.
3694 See the documentation about SELINUX in L<guestfs(3)>.");
3696 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3698 "get SELinux security context",
3700 This gets the SELinux security context of the daemon.
3702 See the documentation about SELINUX in L<guestfs(3)>,
3703 and C<guestfs_setcon>");
3705 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3706 [InitEmpty, Always, TestOutput (
3707 [["part_disk"; "/dev/sda"; "mbr"];
3708 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3709 ["mount_options"; ""; "/dev/sda1"; "/"];
3710 ["write_file"; "/new"; "new file contents"; "0"];
3711 ["cat"; "/new"]], "new file contents")],
3712 "make a filesystem with block size",
3714 This call is similar to C<guestfs_mkfs>, but it allows you to
3715 control the block size of the resulting filesystem. Supported
3716 block sizes depend on the filesystem type, but typically they
3717 are C<1024>, C<2048> or C<4096> only.");
3719 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3720 [InitEmpty, Always, TestOutput (
3721 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3722 ["mke2journal"; "4096"; "/dev/sda1"];
3723 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3724 ["mount_options"; ""; "/dev/sda2"; "/"];
3725 ["write_file"; "/new"; "new file contents"; "0"];
3726 ["cat"; "/new"]], "new file contents")],
3727 "make ext2/3/4 external journal",
3729 This creates an ext2 external journal on C<device>. It is equivalent
3732 mke2fs -O journal_dev -b blocksize device");
3734 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3735 [InitEmpty, Always, TestOutput (
3736 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3738 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3739 ["mount_options"; ""; "/dev/sda2"; "/"];
3740 ["write_file"; "/new"; "new file contents"; "0"];
3741 ["cat"; "/new"]], "new file contents")],
3742 "make ext2/3/4 external journal with label",
3744 This creates an ext2 external journal on C<device> with label C<label>.");
3746 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3747 (let uuid = uuidgen () in
3748 [InitEmpty, Always, TestOutput (
3749 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3750 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3751 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3752 ["mount_options"; ""; "/dev/sda2"; "/"];
3753 ["write_file"; "/new"; "new file contents"; "0"];
3754 ["cat"; "/new"]], "new file contents")]),
3755 "make ext2/3/4 external journal with UUID",
3757 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3759 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3761 "make ext2/3/4 filesystem with external journal",
3763 This creates an ext2/3/4 filesystem on C<device> with
3764 an external journal on C<journal>. It is equivalent
3767 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3769 See also C<guestfs_mke2journal>.");
3771 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3773 "make ext2/3/4 filesystem with external journal",
3775 This creates an ext2/3/4 filesystem on C<device> with
3776 an external journal on the journal labeled C<label>.
3778 See also C<guestfs_mke2journal_L>.");
3780 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3782 "make ext2/3/4 filesystem with external journal",
3784 This creates an ext2/3/4 filesystem on C<device> with
3785 an external journal on the journal with UUID C<uuid>.
3787 See also C<guestfs_mke2journal_U>.");
3789 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3790 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3791 "load a kernel module",
3793 This loads a kernel module in the appliance.
3795 The kernel module must have been whitelisted when libguestfs
3796 was built (see C<appliance/kmod.whitelist.in> in the source).");
3798 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3799 [InitNone, Always, TestOutput (
3800 [["echo_daemon"; "This is a test"]], "This is a test"
3802 "echo arguments back to the client",
3804 This command concatenates the list of C<words> passed with single spaces
3805 between them and returns the resulting string.
3807 You can use this command to test the connection through to the daemon.
3809 See also C<guestfs_ping_daemon>.");
3811 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3812 [], (* There is a regression test for this. *)
3813 "find all files and directories, returning NUL-separated list",
3815 This command lists out all files and directories, recursively,
3816 starting at C<directory>, placing the resulting list in the
3817 external file called C<files>.
3819 This command works the same way as C<guestfs_find> with the
3820 following exceptions:
3826 The resulting list is written to an external file.
3830 Items (filenames) in the result are separated
3831 by C<\\0> characters. See L<find(1)> option I<-print0>.
3835 This command is not limited in the number of names that it
3840 The result list is not sorted.
3844 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3845 [InitISOFS, Always, TestOutput (
3846 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3847 InitISOFS, Always, TestOutput (
3848 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3849 InitISOFS, Always, TestOutput (
3850 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3851 InitISOFS, Always, TestLastFail (
3852 [["case_sensitive_path"; "/Known-1/"]]);
3853 InitBasicFS, Always, TestOutput (
3855 ["mkdir"; "/a/bbb"];
3856 ["touch"; "/a/bbb/c"];
3857 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3858 InitBasicFS, Always, TestOutput (
3860 ["mkdir"; "/a/bbb"];
3861 ["touch"; "/a/bbb/c"];
3862 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3863 InitBasicFS, Always, TestLastFail (
3865 ["mkdir"; "/a/bbb"];
3866 ["touch"; "/a/bbb/c"];
3867 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3868 "return true path on case-insensitive filesystem",
3870 This can be used to resolve case insensitive paths on
3871 a filesystem which is case sensitive. The use case is
3872 to resolve paths which you have read from Windows configuration
3873 files or the Windows Registry, to the true path.
3875 The command handles a peculiarity of the Linux ntfs-3g
3876 filesystem driver (and probably others), which is that although
3877 the underlying filesystem is case-insensitive, the driver
3878 exports the filesystem to Linux as case-sensitive.
3880 One consequence of this is that special directories such
3881 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3882 (or other things) depending on the precise details of how
3883 they were created. In Windows itself this would not be
3886 Bug or feature? You decide:
3887 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3889 This function resolves the true case of each element in the
3890 path and returns the case-sensitive path.
3892 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3893 might return C<\"/WINDOWS/system32\"> (the exact return value
3894 would depend on details of how the directories were originally
3895 created under Windows).
3898 This function does not handle drive names, backslashes etc.
3900 See also C<guestfs_realpath>.");
3902 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3903 [InitBasicFS, Always, TestOutput (
3904 [["vfs_type"; "/dev/sda1"]], "ext2")],
3905 "get the Linux VFS type corresponding to a mounted device",
3907 This command gets the filesystem type corresponding to
3908 the filesystem on C<device>.
3910 For most filesystems, the result is the name of the Linux
3911 VFS module which would be used to mount this filesystem
3912 if you mounted it without specifying the filesystem type.
3913 For example a string such as C<ext3> or C<ntfs>.");
3915 ("truncate", (RErr, [Pathname "path"]), 199, [],
3916 [InitBasicFS, Always, TestOutputStruct (
3917 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3918 ["truncate"; "/test"];
3919 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3920 "truncate a file to zero size",
3922 This command truncates C<path> to a zero-length file. The
3923 file must exist already.");
3925 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3926 [InitBasicFS, Always, TestOutputStruct (
3927 [["touch"; "/test"];
3928 ["truncate_size"; "/test"; "1000"];
3929 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3930 "truncate a file to a particular size",
3932 This command truncates C<path> to size C<size> bytes. The file
3935 If the current file size is less than C<size> then
3936 the file is extended to the required size with zero bytes.
3937 This creates a sparse file (ie. disk blocks are not allocated
3938 for the file until you write to it). To create a non-sparse
3939 file of zeroes, use C<guestfs_fallocate64> instead.");
3941 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3942 [InitBasicFS, Always, TestOutputStruct (
3943 [["touch"; "/test"];
3944 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3945 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3946 "set timestamp of a file with nanosecond precision",
3948 This command sets the timestamps of a file with nanosecond
3951 C<atsecs, atnsecs> are the last access time (atime) in secs and
3952 nanoseconds from the epoch.
3954 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3955 secs and nanoseconds from the epoch.
3957 If the C<*nsecs> field contains the special value C<-1> then
3958 the corresponding timestamp is set to the current time. (The
3959 C<*secs> field is ignored in this case).
3961 If the C<*nsecs> field contains the special value C<-2> then
3962 the corresponding timestamp is left unchanged. (The
3963 C<*secs> field is ignored in this case).");
3965 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3966 [InitBasicFS, Always, TestOutputStruct (
3967 [["mkdir_mode"; "/test"; "0o111"];
3968 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3969 "create a directory with a particular mode",
3971 This command creates a directory, setting the initial permissions
3972 of the directory to C<mode>.
3974 For common Linux filesystems, the actual mode which is set will
3975 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3976 interpret the mode in other ways.
3978 See also C<guestfs_mkdir>, C<guestfs_umask>");
3980 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3982 "change file owner and group",
3984 Change the file owner to C<owner> and group to C<group>.
3985 This is like C<guestfs_chown> but if C<path> is a symlink then
3986 the link itself is changed, not the target.
3988 Only numeric uid and gid are supported. If you want to use
3989 names, you will need to locate and parse the password file
3990 yourself (Augeas support makes this relatively easy).");
3992 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3994 "lstat on multiple files",
3996 This call allows you to perform the C<guestfs_lstat> operation
3997 on multiple files, where all files are in the directory C<path>.
3998 C<names> is the list of files from this directory.
4000 On return you get a list of stat structs, with a one-to-one
4001 correspondence to the C<names> list. If any name did not exist
4002 or could not be lstat'd, then the C<ino> field of that structure
4005 This call is intended for programs that want to efficiently
4006 list a directory contents without making many round-trips.
4007 See also C<guestfs_lxattrlist> for a similarly efficient call
4008 for getting extended attributes. Very long directory listings
4009 might cause the protocol message size to be exceeded, causing
4010 this call to fail. The caller must split up such requests
4011 into smaller groups of names.");
4013 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4015 "lgetxattr on multiple files",
4017 This call allows you to get the extended attributes
4018 of multiple files, where all files are in the directory C<path>.
4019 C<names> is the list of files from this directory.
4021 On return you get a flat list of xattr structs which must be
4022 interpreted sequentially. The first xattr struct always has a zero-length
4023 C<attrname>. C<attrval> in this struct is zero-length
4024 to indicate there was an error doing C<lgetxattr> for this
4025 file, I<or> is a C string which is a decimal number
4026 (the number of following attributes for this file, which could
4027 be C<\"0\">). Then after the first xattr struct are the
4028 zero or more attributes for the first named file.
4029 This repeats for the second and subsequent files.
4031 This call is intended for programs that want to efficiently
4032 list a directory contents without making many round-trips.
4033 See also C<guestfs_lstatlist> for a similarly efficient call
4034 for getting standard stats. Very long directory listings
4035 might cause the protocol message size to be exceeded, causing
4036 this call to fail. The caller must split up such requests
4037 into smaller groups of names.");
4039 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4041 "readlink on multiple files",
4043 This call allows you to do a C<readlink> operation
4044 on multiple files, where all files are in the directory C<path>.
4045 C<names> is the list of files from this directory.
4047 On return you get a list of strings, with a one-to-one
4048 correspondence to the C<names> list. Each string is the
4049 value of the symbolic link.
4051 If the C<readlink(2)> operation fails on any name, then
4052 the corresponding result string is the empty string C<\"\">.
4053 However the whole operation is completed even if there
4054 were C<readlink(2)> errors, and so you can call this
4055 function with names where you don't know if they are
4056 symbolic links already (albeit slightly less efficient).
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 Very long directory listings might cause the protocol
4061 message size to be exceeded, causing
4062 this call to fail. The caller must split up such requests
4063 into smaller groups of names.");
4065 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4066 [InitISOFS, Always, TestOutputBuffer (
4067 [["pread"; "/known-4"; "1"; "3"]], "\n");
4068 InitISOFS, Always, TestOutputBuffer (
4069 [["pread"; "/empty"; "0"; "100"]], "")],
4070 "read part of a file",
4072 This command lets you read part of a file. It reads C<count>
4073 bytes of the file, starting at C<offset>, from file C<path>.
4075 This may read fewer bytes than requested. For further details
4076 see the L<pread(2)> system call.");
4078 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4079 [InitEmpty, Always, TestRun (
4080 [["part_init"; "/dev/sda"; "gpt"]])],
4081 "create an empty partition table",
4083 This creates an empty partition table on C<device> of one of the
4084 partition types listed below. Usually C<parttype> should be
4085 either C<msdos> or C<gpt> (for large disks).
4087 Initially there are no partitions. Following this, you should
4088 call C<guestfs_part_add> for each partition required.
4090 Possible values for C<parttype> are:
4094 =item B<efi> | B<gpt>
4096 Intel EFI / GPT partition table.
4098 This is recommended for >= 2 TB partitions that will be accessed
4099 from Linux and Intel-based Mac OS X. It also has limited backwards
4100 compatibility with the C<mbr> format.
4102 =item B<mbr> | B<msdos>
4104 The standard PC \"Master Boot Record\" (MBR) format used
4105 by MS-DOS and Windows. This partition type will B<only> work
4106 for device sizes up to 2 TB. For large disks we recommend
4111 Other partition table types that may work but are not
4120 =item B<amiga> | B<rdb>
4122 Amiga \"Rigid Disk Block\" format.
4130 DASD, used on IBM mainframes.
4138 Old Mac partition format. Modern Macs use C<gpt>.
4142 NEC PC-98 format, common in Japan apparently.
4150 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4151 [InitEmpty, Always, TestRun (
4152 [["part_init"; "/dev/sda"; "mbr"];
4153 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4154 InitEmpty, Always, TestRun (
4155 [["part_init"; "/dev/sda"; "gpt"];
4156 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4157 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4158 InitEmpty, Always, TestRun (
4159 [["part_init"; "/dev/sda"; "mbr"];
4160 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4161 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4162 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4163 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4164 "add a partition to the device",
4166 This command adds a partition to C<device>. If there is no partition
4167 table on the device, call C<guestfs_part_init> first.
4169 The C<prlogex> parameter is the type of partition. Normally you
4170 should pass C<p> or C<primary> here, but MBR partition tables also
4171 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4174 C<startsect> and C<endsect> are the start and end of the partition
4175 in I<sectors>. C<endsect> may be negative, which means it counts
4176 backwards from the end of the disk (C<-1> is the last sector).
4178 Creating a partition which covers the whole disk is not so easy.
4179 Use C<guestfs_part_disk> to do that.");
4181 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4182 [InitEmpty, Always, TestRun (
4183 [["part_disk"; "/dev/sda"; "mbr"]]);
4184 InitEmpty, Always, TestRun (
4185 [["part_disk"; "/dev/sda"; "gpt"]])],
4186 "partition whole disk with a single primary partition",
4188 This command is simply a combination of C<guestfs_part_init>
4189 followed by C<guestfs_part_add> to create a single primary partition
4190 covering the whole disk.
4192 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4193 but other possible values are described in C<guestfs_part_init>.");
4195 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4196 [InitEmpty, Always, TestRun (
4197 [["part_disk"; "/dev/sda"; "mbr"];
4198 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4199 "make a partition bootable",
4201 This sets the bootable flag on partition numbered C<partnum> on
4202 device C<device>. Note that partitions are numbered from 1.
4204 The bootable flag is used by some operating systems (notably
4205 Windows) to determine which partition to boot from. It is by
4206 no means universally recognized.");
4208 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4209 [InitEmpty, Always, TestRun (
4210 [["part_disk"; "/dev/sda"; "gpt"];
4211 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4212 "set partition name",
4214 This sets the partition name on partition numbered C<partnum> on
4215 device C<device>. Note that partitions are numbered from 1.
4217 The partition name can only be set on certain types of partition
4218 table. This works on C<gpt> but not on C<mbr> partitions.");
4220 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4221 [], (* XXX Add a regression test for this. *)
4222 "list partitions on a device",
4224 This command parses the partition table on C<device> and
4225 returns the list of partitions found.
4227 The fields in the returned structure are:
4233 Partition number, counting from 1.
4237 Start of the partition I<in bytes>. To get sectors you have to
4238 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4242 End of the partition in bytes.
4246 Size of the partition in bytes.
4250 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4251 [InitEmpty, Always, TestOutput (
4252 [["part_disk"; "/dev/sda"; "gpt"];
4253 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4254 "get the partition table type",
4256 This command examines the partition table on C<device> and
4257 returns the partition table type (format) being used.
4259 Common return values include: C<msdos> (a DOS/Windows style MBR
4260 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4261 values are possible, although unusual. See C<guestfs_part_init>
4264 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4265 [InitBasicFS, Always, TestOutputBuffer (
4266 [["fill"; "0x63"; "10"; "/test"];
4267 ["read_file"; "/test"]], "cccccccccc")],
4268 "fill a file with octets",
4270 This command creates a new file called C<path>. The initial
4271 content of the file is C<len> octets of C<c>, where C<c>
4272 must be a number in the range C<[0..255]>.
4274 To fill a file with zero bytes (sparsely), it is
4275 much more efficient to use C<guestfs_truncate_size>.");
4277 ("available", (RErr, [StringList "groups"]), 216, [],
4278 [InitNone, Always, TestRun [["available"; ""]]],
4279 "test availability of some parts of the API",
4281 This command is used to check the availability of some
4282 groups of functionality in the appliance, which not all builds of
4283 the libguestfs appliance will be able to provide.
4285 The libguestfs groups, and the functions that those
4286 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4288 The argument C<groups> is a list of group names, eg:
4289 C<[\"inotify\", \"augeas\"]> would check for the availability of
4290 the Linux inotify functions and Augeas (configuration file
4293 The command returns no error if I<all> requested groups are available.
4295 It fails with an error if one or more of the requested
4296 groups is unavailable in the appliance.
4298 If an unknown group name is included in the
4299 list of groups then an error is always returned.
4307 You must call C<guestfs_launch> before calling this function.
4309 The reason is because we don't know what groups are
4310 supported by the appliance/daemon until it is running and can
4315 If a group of functions is available, this does not necessarily
4316 mean that they will work. You still have to check for errors
4317 when calling individual API functions even if they are
4322 It is usually the job of distro packagers to build
4323 complete functionality into the libguestfs appliance.
4324 Upstream libguestfs, if built from source with all
4325 requirements satisfied, will support everything.
4329 This call was added in version C<1.0.80>. In previous
4330 versions of libguestfs all you could do would be to speculatively
4331 execute a command to find out if the daemon implemented it.
4332 See also C<guestfs_version>.
4336 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4337 [InitBasicFS, Always, TestOutputBuffer (
4338 [["write_file"; "/src"; "hello, world"; "0"];
4339 ["dd"; "/src"; "/dest"];
4340 ["read_file"; "/dest"]], "hello, world")],
4341 "copy from source to destination using dd",
4343 This command copies from one source device or file C<src>
4344 to another destination device or file C<dest>. Normally you
4345 would use this to copy to or from a device or partition, for
4346 example to duplicate a filesystem.
4348 If the destination is a device, it must be as large or larger
4349 than the source file or device, otherwise the copy will fail.
4350 This command cannot do partial copies (see C<guestfs_copy_size>).");
4352 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4353 [InitBasicFS, Always, TestOutputInt (
4354 [["write_file"; "/file"; "hello, world"; "0"];
4355 ["filesize"; "/file"]], 12)],
4356 "return the size of the file in bytes",
4358 This command returns the size of C<file> in bytes.
4360 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4361 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4362 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4364 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4365 [InitBasicFSonLVM, Always, TestOutputList (
4366 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4367 ["lvs"]], ["/dev/VG/LV2"])],
4368 "rename an LVM logical volume",
4370 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4372 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4373 [InitBasicFSonLVM, Always, TestOutputList (
4375 ["vg_activate"; "false"; "VG"];
4376 ["vgrename"; "VG"; "VG2"];
4377 ["vg_activate"; "true"; "VG2"];
4378 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4379 ["vgs"]], ["VG2"])],
4380 "rename an LVM volume group",
4382 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4384 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4385 [InitISOFS, Always, TestOutputBuffer (
4386 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4387 "list the contents of a single file in an initrd",
4389 This command unpacks the file C<filename> from the initrd file
4390 called C<initrdpath>. The filename must be given I<without> the
4391 initial C</> character.
4393 For example, in guestfish you could use the following command
4394 to examine the boot script (usually called C</init>)
4395 contained in a Linux initrd or initramfs image:
4397 initrd-cat /boot/initrd-<version>.img init
4399 See also C<guestfs_initrd_list>.");
4401 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4403 "get the UUID of a physical volume",
4405 This command returns the UUID of the LVM PV C<device>.");
4407 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4409 "get the UUID of a volume group",
4411 This command returns the UUID of the LVM VG named C<vgname>.");
4413 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4415 "get the UUID of a logical volume",
4417 This command returns the UUID of the LVM LV C<device>.");
4419 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4421 "get the PV UUIDs containing the volume group",
4423 Given a VG called C<vgname>, this returns the UUIDs of all
4424 the physical volumes that this volume group resides on.
4426 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4427 calls to associate physical volumes and volume groups.
4429 See also C<guestfs_vglvuuids>.");
4431 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4433 "get the LV UUIDs of all LVs in the volume group",
4435 Given a VG called C<vgname>, this returns the UUIDs of all
4436 the logical volumes created in this volume group.
4438 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4439 calls to associate logical volumes and volume groups.
4441 See also C<guestfs_vgpvuuids>.");
4443 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4444 [InitBasicFS, Always, TestOutputBuffer (
4445 [["write_file"; "/src"; "hello, world"; "0"];
4446 ["copy_size"; "/src"; "/dest"; "5"];
4447 ["read_file"; "/dest"]], "hello")],
4448 "copy size bytes from source to destination using dd",
4450 This command copies exactly C<size> bytes from one source device
4451 or file C<src> to another destination device or file C<dest>.
4453 Note this will fail if the source is too short or if the destination
4454 is not large enough.");
4456 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4457 [InitEmpty, Always, TestRun (
4458 [["part_init"; "/dev/sda"; "mbr"];
4459 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4460 ["part_del"; "/dev/sda"; "1"]])],
4461 "delete a partition",
4463 This command deletes the partition numbered C<partnum> on C<device>.
4465 Note that in the case of MBR partitioning, deleting an
4466 extended partition also deletes any logical partitions
4469 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4470 [InitEmpty, Always, TestOutputTrue (
4471 [["part_init"; "/dev/sda"; "mbr"];
4472 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4473 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4474 ["part_get_bootable"; "/dev/sda"; "1"]])],
4475 "return true if a partition is bootable",
4477 This command returns true if the partition C<partnum> on
4478 C<device> has the bootable flag set.
4480 See also C<guestfs_part_set_bootable>.");
4482 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4483 [InitEmpty, Always, TestOutputInt (
4484 [["part_init"; "/dev/sda"; "mbr"];
4485 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4486 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4487 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4488 "get the MBR type byte (ID byte) from a partition",
4490 Returns the MBR type byte (also known as the ID byte) from
4491 the numbered partition C<partnum>.
4493 Note that only MBR (old DOS-style) partitions have type bytes.
4494 You will get undefined results for other partition table
4495 types (see C<guestfs_part_get_parttype>).");
4497 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4498 [], (* tested by part_get_mbr_id *)
4499 "set the MBR type byte (ID byte) of a partition",
4501 Sets the MBR type byte (also known as the ID byte) of
4502 the numbered partition C<partnum> to C<idbyte>. Note
4503 that the type bytes quoted in most documentation are
4504 in fact hexadecimal numbers, but usually documented
4505 without any leading \"0x\" which might be confusing.
4507 Note that only MBR (old DOS-style) partitions have type bytes.
4508 You will get undefined results for other partition table
4509 types (see C<guestfs_part_get_parttype>).");
4513 let all_functions = non_daemon_functions @ daemon_functions
4515 (* In some places we want the functions to be displayed sorted
4516 * alphabetically, so this is useful:
4518 let all_functions_sorted =
4519 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4520 compare n1 n2) all_functions
4522 (* Field types for structures. *)
4524 | FChar (* C 'char' (really, a 7 bit byte). *)
4525 | FString (* nul-terminated ASCII string, NOT NULL. *)
4526 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4531 | FBytes (* Any int measure that counts bytes. *)
4532 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4533 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4535 (* Because we generate extra parsing code for LVM command line tools,
4536 * we have to pull out the LVM columns separately here.
4546 "pv_attr", FString (* XXX *);
4547 "pv_pe_count", FInt64;
4548 "pv_pe_alloc_count", FInt64;
4551 "pv_mda_count", FInt64;
4552 "pv_mda_free", FBytes;
4553 (* Not in Fedora 10:
4554 "pv_mda_size", FBytes;
4561 "vg_attr", FString (* XXX *);
4564 "vg_sysid", FString;
4565 "vg_extent_size", FBytes;
4566 "vg_extent_count", FInt64;
4567 "vg_free_count", FInt64;
4572 "snap_count", FInt64;
4575 "vg_mda_count", FInt64;
4576 "vg_mda_free", FBytes;
4577 (* Not in Fedora 10:
4578 "vg_mda_size", FBytes;
4584 "lv_attr", FString (* XXX *);
4587 "lv_kernel_major", FInt64;
4588 "lv_kernel_minor", FInt64;
4590 "seg_count", FInt64;
4592 "snap_percent", FOptPercent;
4593 "copy_percent", FOptPercent;
4596 "mirror_log", FString;
4600 (* Names and fields in all structures (in RStruct and RStructList)
4604 (* The old RIntBool return type, only ever used for aug_defnode. Do
4605 * not use this struct in any new code.
4608 "i", FInt32; (* for historical compatibility *)
4609 "b", FInt32; (* for historical compatibility *)
4612 (* LVM PVs, VGs, LVs. *)
4613 "lvm_pv", lvm_pv_cols;
4614 "lvm_vg", lvm_vg_cols;
4615 "lvm_lv", lvm_lv_cols;
4617 (* Column names and types from stat structures.
4618 * NB. Can't use things like 'st_atime' because glibc header files
4619 * define some of these as macros. Ugh.
4650 (* Column names in dirent structure. *)
4653 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4658 (* Version numbers. *)
4666 (* Extended attribute. *)
4668 "attrname", FString;
4672 (* Inotify events. *)
4676 "in_cookie", FUInt32;
4680 (* Partition table entry. *)
4683 "part_start", FBytes;
4685 "part_size", FBytes;
4687 ] (* end of structs *)
4689 (* Ugh, Java has to be different ..
4690 * These names are also used by the Haskell bindings.
4692 let java_structs = [
4693 "int_bool", "IntBool";
4698 "statvfs", "StatVFS";
4700 "version", "Version";
4702 "inotify_event", "INotifyEvent";
4703 "partition", "Partition";
4706 (* What structs are actually returned. *)
4707 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4709 (* Returns a list of RStruct/RStructList structs that are returned
4710 * by any function. Each element of returned list is a pair:
4712 * (structname, RStructOnly)
4713 * == there exists function which returns RStruct (_, structname)
4714 * (structname, RStructListOnly)
4715 * == there exists function which returns RStructList (_, structname)
4716 * (structname, RStructAndList)
4717 * == there are functions returning both RStruct (_, structname)
4718 * and RStructList (_, structname)
4720 let rstructs_used_by functions =
4721 (* ||| is a "logical OR" for rstructs_used_t *)
4725 | _, RStructAndList -> RStructAndList
4726 | RStructOnly, RStructListOnly
4727 | RStructListOnly, RStructOnly -> RStructAndList
4728 | RStructOnly, RStructOnly -> RStructOnly
4729 | RStructListOnly, RStructListOnly -> RStructListOnly
4732 let h = Hashtbl.create 13 in
4734 (* if elem->oldv exists, update entry using ||| operator,
4735 * else just add elem->newv to the hash
4737 let update elem newv =
4738 try let oldv = Hashtbl.find h elem in
4739 Hashtbl.replace h elem (newv ||| oldv)
4740 with Not_found -> Hashtbl.add h elem newv
4744 fun (_, style, _, _, _, _, _) ->
4745 match fst style with
4746 | RStruct (_, structname) -> update structname RStructOnly
4747 | RStructList (_, structname) -> update structname RStructListOnly
4751 (* return key->values as a list of (key,value) *)
4752 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4754 (* Used for testing language bindings. *)
4756 | CallString of string
4757 | CallOptString of string option
4758 | CallStringList of string list
4760 | CallInt64 of int64
4763 (* Used to memoize the result of pod2text. *)
4764 let pod2text_memo_filename = "src/.pod2text.data"
4765 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4767 let chan = open_in pod2text_memo_filename in
4768 let v = input_value chan in
4772 _ -> Hashtbl.create 13
4773 let pod2text_memo_updated () =
4774 let chan = open_out pod2text_memo_filename in
4775 output_value chan pod2text_memo;
4778 (* Useful functions.
4779 * Note we don't want to use any external OCaml libraries which
4780 * makes this a bit harder than it should be.
4782 module StringMap = Map.Make (String)
4784 let failwithf fs = ksprintf failwith fs
4786 let unique = let i = ref 0 in fun () -> incr i; !i
4788 let replace_char s c1 c2 =
4789 let s2 = String.copy s in
4790 let r = ref false in
4791 for i = 0 to String.length s2 - 1 do
4792 if String.unsafe_get s2 i = c1 then (
4793 String.unsafe_set s2 i c2;
4797 if not !r then s else s2
4801 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4803 let triml ?(test = isspace) str =
4805 let n = ref (String.length str) in
4806 while !n > 0 && test str.[!i]; do
4811 else String.sub str !i !n
4813 let trimr ?(test = isspace) str =
4814 let n = ref (String.length str) in
4815 while !n > 0 && test str.[!n-1]; do
4818 if !n = String.length str then str
4819 else String.sub str 0 !n
4821 let trim ?(test = isspace) str =
4822 trimr ~test (triml ~test str)
4824 let rec find s sub =
4825 let len = String.length s in
4826 let sublen = String.length sub in
4828 if i <= len-sublen then (
4830 if j < sublen then (
4831 if s.[i+j] = sub.[j] then loop2 (j+1)
4837 if r = -1 then loop (i+1) else r
4843 let rec replace_str s s1 s2 =
4844 let len = String.length s in
4845 let sublen = String.length s1 in
4846 let i = find s s1 in
4849 let s' = String.sub s 0 i in
4850 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4851 s' ^ s2 ^ replace_str s'' s1 s2
4854 let rec string_split sep str =
4855 let len = String.length str in
4856 let seplen = String.length sep in
4857 let i = find str sep in
4858 if i = -1 then [str]
4860 let s' = String.sub str 0 i in
4861 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4862 s' :: string_split sep s''
4865 let files_equal n1 n2 =
4866 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4867 match Sys.command cmd with
4870 | i -> failwithf "%s: failed with error code %d" cmd i
4872 let rec filter_map f = function
4876 | Some y -> y :: filter_map f xs
4877 | None -> filter_map f xs
4879 let rec find_map f = function
4880 | [] -> raise Not_found
4884 | None -> find_map f xs
4887 let rec loop i = function
4889 | x :: xs -> f i x; loop (i+1) xs
4894 let rec loop i = function
4896 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4900 let count_chars c str =
4901 let count = ref 0 in
4902 for i = 0 to String.length str - 1 do
4903 if c = String.unsafe_get str i then incr count
4907 let name_of_argt = function
4908 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4909 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4910 | FileIn n | FileOut n -> n
4912 let java_name_of_struct typ =
4913 try List.assoc typ java_structs
4916 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4918 let cols_of_struct typ =
4919 try List.assoc typ structs
4921 failwithf "cols_of_struct: unknown struct %s" typ
4923 let seq_of_test = function
4924 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4925 | TestOutputListOfDevices (s, _)
4926 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4927 | TestOutputTrue s | TestOutputFalse s
4928 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4929 | TestOutputStruct (s, _)
4930 | TestLastFail s -> s
4932 (* Handling for function flags. *)
4933 let protocol_limit_warning =
4934 "Because of the message protocol, there is a transfer limit
4935 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4937 let danger_will_robinson =
4938 "B<This command is dangerous. Without careful use you
4939 can easily destroy all your data>."
4941 let deprecation_notice flags =
4944 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4946 sprintf "This function is deprecated.
4947 In new code, use the C<%s> call instead.
4949 Deprecated functions will not be removed from the API, but the
4950 fact that they are deprecated indicates that there are problems
4951 with correct use of these functions." alt in
4956 (* Create list of optional groups. *)
4958 let h = Hashtbl.create 13 in
4960 fun (name, _, _, flags, _, _, _) ->
4964 let names = try Hashtbl.find h group with Not_found -> [] in
4965 Hashtbl.replace h group (name :: names)
4969 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4972 fun group -> group, List.sort compare (Hashtbl.find h group)
4974 List.sort (fun x y -> compare (fst x) (fst y)) groups
4976 (* Check function names etc. for consistency. *)
4977 let check_functions () =
4978 let contains_uppercase str =
4979 let len = String.length str in
4981 if i >= len then false
4984 if c >= 'A' && c <= 'Z' then true
4991 (* Check function names. *)
4993 fun (name, _, _, _, _, _, _) ->
4994 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4995 failwithf "function name %s does not need 'guestfs' prefix" name;
4997 failwithf "function name is empty";
4998 if name.[0] < 'a' || name.[0] > 'z' then
4999 failwithf "function name %s must start with lowercase a-z" name;
5000 if String.contains name '-' then
5001 failwithf "function name %s should not contain '-', use '_' instead."
5005 (* Check function parameter/return names. *)
5007 fun (name, style, _, _, _, _, _) ->
5008 let check_arg_ret_name n =
5009 if contains_uppercase n then
5010 failwithf "%s param/ret %s should not contain uppercase chars"
5012 if String.contains n '-' || String.contains n '_' then
5013 failwithf "%s param/ret %s should not contain '-' or '_'"
5016 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;
5017 if n = "int" || n = "char" || n = "short" || n = "long" then
5018 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5019 if n = "i" || n = "n" then
5020 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5021 if n = "argv" || n = "args" then
5022 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5024 (* List Haskell, OCaml and C keywords here.
5025 * http://www.haskell.org/haskellwiki/Keywords
5026 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5027 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5028 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5029 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5030 * Omitting _-containing words, since they're handled above.
5031 * Omitting the OCaml reserved word, "val", is ok,
5032 * and saves us from renaming several parameters.
5035 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5036 "char"; "class"; "const"; "constraint"; "continue"; "data";
5037 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5038 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5039 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5040 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5041 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5043 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5044 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5045 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5046 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5047 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5048 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5049 "volatile"; "when"; "where"; "while";
5051 if List.mem n reserved then
5052 failwithf "%s has param/ret using reserved word %s" name n;
5055 (match fst style with
5057 | RInt n | RInt64 n | RBool n
5058 | RConstString n | RConstOptString n | RString n
5059 | RStringList n | RStruct (n, _) | RStructList (n, _)
5060 | RHashtable n | RBufferOut n ->
5061 check_arg_ret_name n
5063 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5066 (* Check short descriptions. *)
5068 fun (name, _, _, _, _, shortdesc, _) ->
5069 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5070 failwithf "short description of %s should begin with lowercase." name;
5071 let c = shortdesc.[String.length shortdesc-1] in
5072 if c = '\n' || c = '.' then
5073 failwithf "short description of %s should not end with . or \\n." name
5076 (* Check long descriptions. *)
5078 fun (name, _, _, _, _, _, longdesc) ->
5079 if longdesc.[String.length longdesc-1] = '\n' then
5080 failwithf "long description of %s should not end with \\n." name
5083 (* Check proc_nrs. *)
5085 fun (name, _, proc_nr, _, _, _, _) ->
5086 if proc_nr <= 0 then
5087 failwithf "daemon function %s should have proc_nr > 0" name
5091 fun (name, _, proc_nr, _, _, _, _) ->
5092 if proc_nr <> -1 then
5093 failwithf "non-daemon function %s should have proc_nr -1" name
5094 ) non_daemon_functions;
5097 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5100 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5101 let rec loop = function
5104 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5106 | (name1,nr1) :: (name2,nr2) :: _ ->
5107 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5115 (* Ignore functions that have no tests. We generate a
5116 * warning when the user does 'make check' instead.
5118 | name, _, _, _, [], _, _ -> ()
5119 | name, _, _, _, tests, _, _ ->
5123 match seq_of_test test with
5125 failwithf "%s has a test containing an empty sequence" name
5126 | cmds -> List.map List.hd cmds
5128 let funcs = List.flatten funcs in
5130 let tested = List.mem name funcs in
5133 failwithf "function %s has tests but does not test itself" name
5136 (* 'pr' prints to the current output file. *)
5137 let chan = ref Pervasives.stdout
5142 let i = count_chars '\n' str in
5143 lines := !lines + i;
5144 output_string !chan str
5147 let copyright_years =
5148 let this_year = 1900 + (localtime (time ())).tm_year in
5149 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5151 (* Generate a header block in a number of standard styles. *)
5152 type comment_style =
5153 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5154 type license = GPLv2plus | LGPLv2plus
5156 let generate_header ?(extra_inputs = []) comment license =
5157 let inputs = "src/generator.ml" :: extra_inputs in
5158 let c = match comment with
5159 | CStyle -> pr "/* "; " *"
5160 | CPlusPlusStyle -> pr "// "; "//"
5161 | HashStyle -> pr "# "; "#"
5162 | OCamlStyle -> pr "(* "; " *"
5163 | HaskellStyle -> pr "{- "; " " in
5164 pr "libguestfs generated file\n";
5165 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5166 List.iter (pr "%s %s\n" c) inputs;
5167 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5169 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5173 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5174 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5175 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5176 pr "%s (at your option) any later version.\n" c;
5178 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5179 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5180 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5181 pr "%s GNU General Public License for more details.\n" c;
5183 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5184 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5185 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5188 pr "%s This library is free software; you can redistribute it and/or\n" c;
5189 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5190 pr "%s License as published by the Free Software Foundation; either\n" c;
5191 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5193 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5194 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5195 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5196 pr "%s Lesser General Public License for more details.\n" c;
5198 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5199 pr "%s License along with this library; if not, write to the Free Software\n" c;
5200 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5203 | CStyle -> pr " */\n"
5206 | OCamlStyle -> pr " *)\n"
5207 | HaskellStyle -> pr "-}\n"
5211 (* Start of main code generation functions below this line. *)
5213 (* Generate the pod documentation for the C API. *)
5214 let rec generate_actions_pod () =
5216 fun (shortname, style, _, flags, _, _, longdesc) ->
5217 if not (List.mem NotInDocs flags) then (
5218 let name = "guestfs_" ^ shortname in
5219 pr "=head2 %s\n\n" name;
5221 generate_prototype ~extern:false ~handle:"g" name style;
5223 pr "%s\n\n" longdesc;
5224 (match fst style with
5226 pr "This function returns 0 on success or -1 on error.\n\n"
5228 pr "On error this function returns -1.\n\n"
5230 pr "On error this function returns -1.\n\n"
5232 pr "This function returns a C truth value on success or -1 on error.\n\n"
5234 pr "This function returns a string, or NULL on error.
5235 The string is owned by the guest handle and must I<not> be freed.\n\n"
5236 | RConstOptString _ ->
5237 pr "This function returns a string which may be NULL.
5238 There is way to return an error from this function.
5239 The string is owned by the guest handle and must I<not> be freed.\n\n"
5241 pr "This function returns a string, or NULL on error.
5242 I<The caller must free the returned string after use>.\n\n"
5244 pr "This function returns a NULL-terminated array of strings
5245 (like L<environ(3)>), or NULL if there was an error.
5246 I<The caller must free the strings and the array after use>.\n\n"
5247 | RStruct (_, typ) ->
5248 pr "This function returns a C<struct guestfs_%s *>,
5249 or NULL if there was an error.
5250 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5251 | RStructList (_, typ) ->
5252 pr "This function returns a C<struct guestfs_%s_list *>
5253 (see E<lt>guestfs-structs.hE<gt>),
5254 or NULL if there was an error.
5255 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5257 pr "This function returns a NULL-terminated array of
5258 strings, or NULL if there was an error.
5259 The array of strings will always have length C<2n+1>, where
5260 C<n> keys and values alternate, followed by the trailing NULL entry.
5261 I<The caller must free the strings and the array after use>.\n\n"
5263 pr "This function returns a buffer, or NULL on error.
5264 The size of the returned buffer is written to C<*size_r>.
5265 I<The caller must free the returned buffer after use>.\n\n"
5267 if List.mem ProtocolLimitWarning flags then
5268 pr "%s\n\n" protocol_limit_warning;
5269 if List.mem DangerWillRobinson flags then
5270 pr "%s\n\n" danger_will_robinson;
5271 match deprecation_notice flags with
5273 | Some txt -> pr "%s\n\n" txt
5275 ) all_functions_sorted
5277 and generate_structs_pod () =
5278 (* Structs documentation. *)
5281 pr "=head2 guestfs_%s\n" typ;
5283 pr " struct guestfs_%s {\n" typ;
5286 | name, FChar -> pr " char %s;\n" name
5287 | name, FUInt32 -> pr " uint32_t %s;\n" name
5288 | name, FInt32 -> pr " int32_t %s;\n" name
5289 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5290 | name, FInt64 -> pr " int64_t %s;\n" name
5291 | name, FString -> pr " char *%s;\n" name
5293 pr " /* The next two fields describe a byte array. */\n";
5294 pr " uint32_t %s_len;\n" name;
5295 pr " char *%s;\n" name
5297 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5298 pr " char %s[32];\n" name
5299 | name, FOptPercent ->
5300 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5301 pr " float %s;\n" name
5305 pr " struct guestfs_%s_list {\n" typ;
5306 pr " uint32_t len; /* Number of elements in list. */\n";
5307 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5310 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5311 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5316 and generate_availability_pod () =
5317 (* Availability documentation. *)
5321 fun (group, functions) ->
5322 pr "=item B<%s>\n" group;
5324 pr "The following functions:\n";
5325 List.iter (pr "L</guestfs_%s>\n") functions;
5331 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5332 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5334 * We have to use an underscore instead of a dash because otherwise
5335 * rpcgen generates incorrect code.
5337 * This header is NOT exported to clients, but see also generate_structs_h.
5339 and generate_xdr () =
5340 generate_header CStyle LGPLv2plus;
5342 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5343 pr "typedef string str<>;\n";
5346 (* Internal structures. *)
5350 pr "struct guestfs_int_%s {\n" typ;
5352 | name, FChar -> pr " char %s;\n" name
5353 | name, FString -> pr " string %s<>;\n" name
5354 | name, FBuffer -> pr " opaque %s<>;\n" name
5355 | name, FUUID -> pr " opaque %s[32];\n" name
5356 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5357 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5358 | name, FOptPercent -> pr " float %s;\n" name
5362 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5367 fun (shortname, style, _, _, _, _, _) ->
5368 let name = "guestfs_" ^ shortname in
5370 (match snd style with
5373 pr "struct %s_args {\n" name;
5376 | Pathname n | Device n | Dev_or_Path n | String n ->
5377 pr " string %s<>;\n" n
5378 | OptString n -> pr " str *%s;\n" n
5379 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5380 | Bool n -> pr " bool %s;\n" n
5381 | Int n -> pr " int %s;\n" n
5382 | Int64 n -> pr " hyper %s;\n" n
5383 | FileIn _ | FileOut _ -> ()
5387 (match fst style with
5390 pr "struct %s_ret {\n" name;
5394 pr "struct %s_ret {\n" name;
5395 pr " hyper %s;\n" n;
5398 pr "struct %s_ret {\n" name;
5401 | RConstString _ | RConstOptString _ ->
5402 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5404 pr "struct %s_ret {\n" name;
5405 pr " string %s<>;\n" n;
5408 pr "struct %s_ret {\n" name;
5409 pr " str %s<>;\n" n;
5411 | RStruct (n, typ) ->
5412 pr "struct %s_ret {\n" name;
5413 pr " guestfs_int_%s %s;\n" typ n;
5415 | RStructList (n, typ) ->
5416 pr "struct %s_ret {\n" name;
5417 pr " guestfs_int_%s_list %s;\n" typ n;
5420 pr "struct %s_ret {\n" name;
5421 pr " str %s<>;\n" n;
5424 pr "struct %s_ret {\n" name;
5425 pr " opaque %s<>;\n" n;
5430 (* Table of procedure numbers. *)
5431 pr "enum guestfs_procedure {\n";
5433 fun (shortname, _, proc_nr, _, _, _, _) ->
5434 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5436 pr " GUESTFS_PROC_NR_PROCS\n";
5440 (* Having to choose a maximum message size is annoying for several
5441 * reasons (it limits what we can do in the API), but it (a) makes
5442 * the protocol a lot simpler, and (b) provides a bound on the size
5443 * of the daemon which operates in limited memory space.
5445 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5448 (* Message header, etc. *)
5450 /* The communication protocol is now documented in the guestfs(3)
5454 const GUESTFS_PROGRAM = 0x2000F5F5;
5455 const GUESTFS_PROTOCOL_VERSION = 1;
5457 /* These constants must be larger than any possible message length. */
5458 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5459 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5461 enum guestfs_message_direction {
5462 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5463 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5466 enum guestfs_message_status {
5467 GUESTFS_STATUS_OK = 0,
5468 GUESTFS_STATUS_ERROR = 1
5471 const GUESTFS_ERROR_LEN = 256;
5473 struct guestfs_message_error {
5474 string error_message<GUESTFS_ERROR_LEN>;
5477 struct guestfs_message_header {
5478 unsigned prog; /* GUESTFS_PROGRAM */
5479 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5480 guestfs_procedure proc; /* GUESTFS_PROC_x */
5481 guestfs_message_direction direction;
5482 unsigned serial; /* message serial number */
5483 guestfs_message_status status;
5486 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5488 struct guestfs_chunk {
5489 int cancel; /* if non-zero, transfer is cancelled */
5490 /* data size is 0 bytes if the transfer has finished successfully */
5491 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5495 (* Generate the guestfs-structs.h file. *)
5496 and generate_structs_h () =
5497 generate_header CStyle LGPLv2plus;
5499 (* This is a public exported header file containing various
5500 * structures. The structures are carefully written to have
5501 * exactly the same in-memory format as the XDR structures that
5502 * we use on the wire to the daemon. The reason for creating
5503 * copies of these structures here is just so we don't have to
5504 * export the whole of guestfs_protocol.h (which includes much
5505 * unrelated and XDR-dependent stuff that we don't want to be
5506 * public, or required by clients).
5508 * To reiterate, we will pass these structures to and from the
5509 * client with a simple assignment or memcpy, so the format
5510 * must be identical to what rpcgen / the RFC defines.
5513 (* Public structures. *)
5516 pr "struct guestfs_%s {\n" typ;
5519 | name, FChar -> pr " char %s;\n" name
5520 | name, FString -> pr " char *%s;\n" name
5522 pr " uint32_t %s_len;\n" name;
5523 pr " char *%s;\n" name
5524 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5525 | name, FUInt32 -> pr " uint32_t %s;\n" name
5526 | name, FInt32 -> pr " int32_t %s;\n" name
5527 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5528 | name, FInt64 -> pr " int64_t %s;\n" name
5529 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5533 pr "struct guestfs_%s_list {\n" typ;
5534 pr " uint32_t len;\n";
5535 pr " struct guestfs_%s *val;\n" typ;
5538 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5539 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5543 (* Generate the guestfs-actions.h file. *)
5544 and generate_actions_h () =
5545 generate_header CStyle LGPLv2plus;
5547 fun (shortname, style, _, _, _, _, _) ->
5548 let name = "guestfs_" ^ shortname in
5549 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5553 (* Generate the guestfs-internal-actions.h file. *)
5554 and generate_internal_actions_h () =
5555 generate_header CStyle LGPLv2plus;
5557 fun (shortname, style, _, _, _, _, _) ->
5558 let name = "guestfs__" ^ shortname in
5559 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5561 ) non_daemon_functions
5563 (* Generate the client-side dispatch stubs. *)
5564 and generate_client_actions () =
5565 generate_header CStyle LGPLv2plus;
5572 #include <inttypes.h>
5574 #include \"guestfs.h\"
5575 #include \"guestfs-internal.h\"
5576 #include \"guestfs-internal-actions.h\"
5577 #include \"guestfs_protocol.h\"
5579 #define error guestfs_error
5580 //#define perrorf guestfs_perrorf
5581 #define safe_malloc guestfs_safe_malloc
5582 #define safe_realloc guestfs_safe_realloc
5583 //#define safe_strdup guestfs_safe_strdup
5584 #define safe_memdup guestfs_safe_memdup
5586 /* Check the return message from a call for validity. */
5588 check_reply_header (guestfs_h *g,
5589 const struct guestfs_message_header *hdr,
5590 unsigned int proc_nr, unsigned int serial)
5592 if (hdr->prog != GUESTFS_PROGRAM) {
5593 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5596 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5597 error (g, \"wrong protocol version (%%d/%%d)\",
5598 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5601 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5602 error (g, \"unexpected message direction (%%d/%%d)\",
5603 hdr->direction, GUESTFS_DIRECTION_REPLY);
5606 if (hdr->proc != proc_nr) {
5607 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5610 if (hdr->serial != serial) {
5611 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5618 /* Check we are in the right state to run a high-level action. */
5620 check_state (guestfs_h *g, const char *caller)
5622 if (!guestfs__is_ready (g)) {
5623 if (guestfs__is_config (g) || guestfs__is_launching (g))
5624 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5627 error (g, \"%%s called from the wrong state, %%d != READY\",
5628 caller, guestfs__get_state (g));
5636 (* Generate code to generate guestfish call traces. *)
5637 let trace_call shortname style =
5638 pr " if (guestfs__get_trace (g)) {\n";
5641 List.exists (function
5642 | StringList _ | DeviceList _ -> true
5643 | _ -> false) (snd style) in
5649 pr " printf (\"%s\");\n" shortname;
5652 | String n (* strings *)
5658 (* guestfish doesn't support string escaping, so neither do we *)
5659 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5660 | OptString n -> (* string option *)
5661 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5662 pr " else printf (\" null\");\n"
5664 | DeviceList n -> (* string list *)
5665 pr " putchar (' ');\n";
5666 pr " putchar ('\"');\n";
5667 pr " for (i = 0; %s[i]; ++i) {\n" n;
5668 pr " if (i > 0) putchar (' ');\n";
5669 pr " fputs (%s[i], stdout);\n" n;
5671 pr " putchar ('\"');\n";
5672 | Bool n -> (* boolean *)
5673 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5674 | Int n -> (* int *)
5675 pr " printf (\" %%d\", %s);\n" n
5677 pr " printf (\" %%\" PRIi64, %s);\n" n
5679 pr " putchar ('\\n');\n";
5684 (* For non-daemon functions, generate a wrapper around each function. *)
5686 fun (shortname, style, _, _, _, _, _) ->
5687 let name = "guestfs_" ^ shortname in
5689 generate_prototype ~extern:false ~semicolon:false ~newline:true
5690 ~handle:"g" name style;
5692 trace_call shortname style;
5693 pr " return guestfs__%s " shortname;
5694 generate_c_call_args ~handle:"g" style;
5698 ) non_daemon_functions;
5700 (* Client-side stubs for each function. *)
5702 fun (shortname, style, _, _, _, _, _) ->
5703 let name = "guestfs_" ^ shortname in
5705 (* Generate the action stub. *)
5706 generate_prototype ~extern:false ~semicolon:false ~newline:true
5707 ~handle:"g" name style;
5710 match fst style with
5711 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5712 | RConstString _ | RConstOptString _ ->
5713 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5714 | RString _ | RStringList _
5715 | RStruct _ | RStructList _
5716 | RHashtable _ | RBufferOut _ ->
5721 (match snd style with
5723 | _ -> pr " struct %s_args args;\n" name
5726 pr " guestfs_message_header hdr;\n";
5727 pr " guestfs_message_error err;\n";
5729 match fst style with
5731 | RConstString _ | RConstOptString _ ->
5732 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5734 | RBool _ | RString _ | RStringList _
5735 | RStruct _ | RStructList _
5736 | RHashtable _ | RBufferOut _ ->
5737 pr " struct %s_ret ret;\n" name;
5740 pr " int serial;\n";
5743 trace_call shortname style;
5744 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5745 pr " guestfs___set_busy (g);\n";
5748 (* Send the main header and arguments. *)
5749 (match snd style with
5751 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5752 (String.uppercase shortname)
5756 | Pathname n | Device n | Dev_or_Path n | String n ->
5757 pr " args.%s = (char *) %s;\n" n n
5759 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5760 | StringList n | DeviceList n ->
5761 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5762 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5764 pr " args.%s = %s;\n" n n
5766 pr " args.%s = %s;\n" n n
5768 pr " args.%s = %s;\n" n n
5769 | FileIn _ | FileOut _ -> ()
5771 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5772 (String.uppercase shortname);
5773 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5776 pr " if (serial == -1) {\n";
5777 pr " guestfs___end_busy (g);\n";
5778 pr " return %s;\n" error_code;
5782 (* Send any additional files (FileIn) requested. *)
5783 let need_read_reply_label = ref false in
5787 pr " r = guestfs___send_file (g, %s);\n" n;
5788 pr " if (r == -1) {\n";
5789 pr " guestfs___end_busy (g);\n";
5790 pr " return %s;\n" error_code;
5792 pr " if (r == -2) /* daemon cancelled */\n";
5793 pr " goto read_reply;\n";
5794 need_read_reply_label := true;
5799 (* Wait for the reply from the remote end. *)
5800 if !need_read_reply_label then pr " read_reply:\n";
5801 pr " memset (&hdr, 0, sizeof hdr);\n";
5802 pr " memset (&err, 0, sizeof err);\n";
5803 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5805 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5809 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5812 pr " if (r == -1) {\n";
5813 pr " guestfs___end_busy (g);\n";
5814 pr " return %s;\n" error_code;
5818 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5819 (String.uppercase shortname);
5820 pr " guestfs___end_busy (g);\n";
5821 pr " return %s;\n" error_code;
5825 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5826 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5827 pr " free (err.error_message);\n";
5828 pr " guestfs___end_busy (g);\n";
5829 pr " return %s;\n" error_code;
5833 (* Expecting to receive further files (FileOut)? *)
5837 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5838 pr " guestfs___end_busy (g);\n";
5839 pr " return %s;\n" error_code;
5845 pr " guestfs___end_busy (g);\n";
5847 (match fst style with
5848 | RErr -> pr " return 0;\n"
5849 | RInt n | RInt64 n | RBool n ->
5850 pr " return ret.%s;\n" n
5851 | RConstString _ | RConstOptString _ ->
5852 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5854 pr " return ret.%s; /* caller will free */\n" n
5855 | RStringList n | RHashtable n ->
5856 pr " /* caller will free this, but we need to add a NULL entry */\n";
5857 pr " ret.%s.%s_val =\n" n n;
5858 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5859 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5861 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5862 pr " return ret.%s.%s_val;\n" n n
5864 pr " /* caller will free this */\n";
5865 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5866 | RStructList (n, _) ->
5867 pr " /* caller will free this */\n";
5868 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5870 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5871 pr " * _val might be NULL here. To make the API saner for\n";
5872 pr " * callers, we turn this case into a unique pointer (using\n";
5873 pr " * malloc(1)).\n";
5875 pr " if (ret.%s.%s_len > 0) {\n" n n;
5876 pr " *size_r = ret.%s.%s_len;\n" n n;
5877 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5879 pr " free (ret.%s.%s_val);\n" n n;
5880 pr " char *p = safe_malloc (g, 1);\n";
5881 pr " *size_r = ret.%s.%s_len;\n" n n;
5889 (* Functions to free structures. *)
5890 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5891 pr " * structure format is identical to the XDR format. See note in\n";
5892 pr " * generator.ml.\n";
5899 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5901 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5907 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5909 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5916 (* Generate daemon/actions.h. *)
5917 and generate_daemon_actions_h () =
5918 generate_header CStyle GPLv2plus;
5920 pr "#include \"../src/guestfs_protocol.h\"\n";
5924 fun (name, style, _, _, _, _, _) ->
5926 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5930 (* Generate the linker script which controls the visibility of
5931 * symbols in the public ABI and ensures no other symbols get
5932 * exported accidentally.
5934 and generate_linker_script () =
5935 generate_header HashStyle GPLv2plus;
5940 "guestfs_get_error_handler";
5941 "guestfs_get_out_of_memory_handler";
5942 "guestfs_last_error";
5943 "guestfs_set_error_handler";
5944 "guestfs_set_launch_done_callback";
5945 "guestfs_set_log_message_callback";
5946 "guestfs_set_out_of_memory_handler";
5947 "guestfs_set_subprocess_quit_callback";
5949 (* Unofficial parts of the API: the bindings code use these
5950 * functions, so it is useful to export them.
5952 "guestfs_safe_calloc";
5953 "guestfs_safe_malloc";
5956 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5960 List.map (fun (typ, _) ->
5961 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5964 let globals = List.sort compare (globals @ functions @ structs) in
5968 List.iter (pr " %s;\n") globals;
5975 (* Generate the server-side stubs. *)
5976 and generate_daemon_actions () =
5977 generate_header CStyle GPLv2plus;
5979 pr "#include <config.h>\n";
5981 pr "#include <stdio.h>\n";
5982 pr "#include <stdlib.h>\n";
5983 pr "#include <string.h>\n";
5984 pr "#include <inttypes.h>\n";
5985 pr "#include <rpc/types.h>\n";
5986 pr "#include <rpc/xdr.h>\n";
5988 pr "#include \"daemon.h\"\n";
5989 pr "#include \"c-ctype.h\"\n";
5990 pr "#include \"../src/guestfs_protocol.h\"\n";
5991 pr "#include \"actions.h\"\n";
5995 fun (name, style, _, _, _, _, _) ->
5996 (* Generate server-side stubs. *)
5997 pr "static void %s_stub (XDR *xdr_in)\n" name;
6000 match fst style with
6001 | RErr | RInt _ -> pr " int r;\n"; "-1"
6002 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6003 | RBool _ -> pr " int r;\n"; "-1"
6004 | RConstString _ | RConstOptString _ ->
6005 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6006 | RString _ -> pr " char *r;\n"; "NULL"
6007 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6008 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6009 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6011 pr " size_t size = 1;\n";
6015 (match snd style with
6018 pr " struct guestfs_%s_args args;\n" name;
6021 | Device n | Dev_or_Path n
6024 | OptString n -> pr " char *%s;\n" n
6025 | StringList n | DeviceList n -> pr " char **%s;\n" n
6026 | Bool n -> pr " int %s;\n" n
6027 | Int n -> pr " int %s;\n" n
6028 | Int64 n -> pr " int64_t %s;\n" n
6029 | FileIn _ | FileOut _ -> ()
6034 (match snd style with
6037 pr " memset (&args, 0, sizeof args);\n";
6039 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6040 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6044 pr " char *%s = args.%s;\n" n n
6046 let pr_list_handling_code n =
6047 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6048 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6049 pr " if (%s == NULL) {\n" n;
6050 pr " reply_with_perror (\"realloc\");\n";
6053 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6054 pr " args.%s.%s_val = %s;\n" n n n;
6060 pr " ABS_PATH (%s, goto done);\n" n;
6063 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6066 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6067 | String n -> pr_args n
6068 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6070 pr_list_handling_code n;
6072 pr_list_handling_code n;
6073 pr " /* Ensure that each is a device,\n";
6074 pr " * and perform device name translation. */\n";
6075 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6076 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6078 | Bool n -> pr " %s = args.%s;\n" n n
6079 | Int n -> pr " %s = args.%s;\n" n n
6080 | Int64 n -> pr " %s = args.%s;\n" n n
6081 | FileIn _ | FileOut _ -> ()
6087 (* this is used at least for do_equal *)
6088 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6089 (* Emit NEED_ROOT just once, even when there are two or
6090 more Pathname args *)
6091 pr " NEED_ROOT (goto done);\n";
6094 (* Don't want to call the impl with any FileIn or FileOut
6095 * parameters, since these go "outside" the RPC protocol.
6098 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6100 pr " r = do_%s " name;
6101 generate_c_call_args (fst style, args');
6104 (match fst style with
6105 | RErr | RInt _ | RInt64 _ | RBool _
6106 | RConstString _ | RConstOptString _
6107 | RString _ | RStringList _ | RHashtable _
6108 | RStruct (_, _) | RStructList (_, _) ->
6109 pr " if (r == %s)\n" error_code;
6110 pr " /* do_%s has already called reply_with_error */\n" name;
6114 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6115 pr " * an ordinary zero-length buffer), so be careful ...\n";
6117 pr " if (size == 1 && r == %s)\n" error_code;
6118 pr " /* do_%s has already called reply_with_error */\n" name;
6123 (* If there are any FileOut parameters, then the impl must
6124 * send its own reply.
6127 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6129 pr " /* do_%s has already sent a reply */\n" name
6131 match fst style with
6132 | RErr -> pr " reply (NULL, NULL);\n"
6133 | RInt n | RInt64 n | RBool n ->
6134 pr " struct guestfs_%s_ret ret;\n" name;
6135 pr " ret.%s = r;\n" n;
6136 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6138 | RConstString _ | RConstOptString _ ->
6139 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6141 pr " struct guestfs_%s_ret ret;\n" name;
6142 pr " ret.%s = r;\n" n;
6143 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6146 | RStringList n | RHashtable n ->
6147 pr " struct guestfs_%s_ret ret;\n" name;
6148 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6149 pr " ret.%s.%s_val = r;\n" n n;
6150 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6152 pr " free_strings (r);\n"
6154 pr " struct guestfs_%s_ret ret;\n" name;
6155 pr " ret.%s = *r;\n" n;
6156 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6158 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6160 | RStructList (n, _) ->
6161 pr " struct guestfs_%s_ret ret;\n" name;
6162 pr " ret.%s = *r;\n" n;
6163 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6165 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6168 pr " struct guestfs_%s_ret ret;\n" name;
6169 pr " ret.%s.%s_val = r;\n" n n;
6170 pr " ret.%s.%s_len = size;\n" n n;
6171 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6176 (* Free the args. *)
6177 (match snd style with
6182 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6189 (* Dispatch function. *)
6190 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6192 pr " switch (proc_nr) {\n";
6195 fun (name, style, _, _, _, _, _) ->
6196 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6197 pr " %s_stub (xdr_in);\n" name;
6202 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";
6207 (* LVM columns and tokenization functions. *)
6208 (* XXX This generates crap code. We should rethink how we
6214 pr "static const char *lvm_%s_cols = \"%s\";\n"
6215 typ (String.concat "," (List.map fst cols));
6218 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6220 pr " char *tok, *p, *next;\n";
6224 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6227 pr " if (!str) {\n";
6228 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6231 pr " if (!*str || c_isspace (*str)) {\n";
6232 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6237 fun (name, coltype) ->
6238 pr " if (!tok) {\n";
6239 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6242 pr " p = strchrnul (tok, ',');\n";
6243 pr " if (*p) next = p+1; else next = NULL;\n";
6244 pr " *p = '\\0';\n";
6247 pr " r->%s = strdup (tok);\n" name;
6248 pr " if (r->%s == NULL) {\n" name;
6249 pr " perror (\"strdup\");\n";
6253 pr " for (i = j = 0; i < 32; ++j) {\n";
6254 pr " if (tok[j] == '\\0') {\n";
6255 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6257 pr " } else if (tok[j] != '-')\n";
6258 pr " r->%s[i++] = tok[j];\n" name;
6261 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6262 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6266 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6267 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6271 pr " if (tok[0] == '\\0')\n";
6272 pr " r->%s = -1;\n" name;
6273 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6274 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6277 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6278 assert false (* can never be an LVM column *)
6280 pr " tok = next;\n";
6283 pr " if (tok != NULL) {\n";
6284 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6291 pr "guestfs_int_lvm_%s_list *\n" typ;
6292 pr "parse_command_line_%ss (void)\n" typ;
6294 pr " char *out, *err;\n";
6295 pr " char *p, *pend;\n";
6297 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6298 pr " void *newp;\n";
6300 pr " ret = malloc (sizeof *ret);\n";
6301 pr " if (!ret) {\n";
6302 pr " reply_with_perror (\"malloc\");\n";
6303 pr " return NULL;\n";
6306 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6307 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6309 pr " r = command (&out, &err,\n";
6310 pr " \"lvm\", \"%ss\",\n" typ;
6311 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6312 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6313 pr " if (r == -1) {\n";
6314 pr " reply_with_error (\"%%s\", err);\n";
6315 pr " free (out);\n";
6316 pr " free (err);\n";
6317 pr " free (ret);\n";
6318 pr " return NULL;\n";
6321 pr " free (err);\n";
6323 pr " /* Tokenize each line of the output. */\n";
6326 pr " while (p) {\n";
6327 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6328 pr " if (pend) {\n";
6329 pr " *pend = '\\0';\n";
6333 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6336 pr " if (!*p) { /* Empty line? Skip it. */\n";
6341 pr " /* Allocate some space to store this next entry. */\n";
6342 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6343 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6344 pr " if (newp == NULL) {\n";
6345 pr " reply_with_perror (\"realloc\");\n";
6346 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6347 pr " free (ret);\n";
6348 pr " free (out);\n";
6349 pr " return NULL;\n";
6351 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6353 pr " /* Tokenize the next entry. */\n";
6354 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6355 pr " if (r == -1) {\n";
6356 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6357 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6358 pr " free (ret);\n";
6359 pr " free (out);\n";
6360 pr " return NULL;\n";
6367 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6369 pr " free (out);\n";
6370 pr " return ret;\n";
6373 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6375 (* Generate a list of function names, for debugging in the daemon.. *)
6376 and generate_daemon_names () =
6377 generate_header CStyle GPLv2plus;
6379 pr "#include <config.h>\n";
6381 pr "#include \"daemon.h\"\n";
6384 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6385 pr "const char *function_names[] = {\n";
6387 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6391 (* Generate the optional groups for the daemon to implement
6392 * guestfs_available.
6394 and generate_daemon_optgroups_c () =
6395 generate_header CStyle GPLv2plus;
6397 pr "#include <config.h>\n";
6399 pr "#include \"daemon.h\"\n";
6400 pr "#include \"optgroups.h\"\n";
6403 pr "struct optgroup optgroups[] = {\n";
6406 pr " { \"%s\", optgroup_%s_available },\n" group group
6408 pr " { NULL, NULL }\n";
6411 and generate_daemon_optgroups_h () =
6412 generate_header CStyle GPLv2plus;
6416 pr "extern int optgroup_%s_available (void);\n" group
6419 (* Generate the tests. *)
6420 and generate_tests () =
6421 generate_header CStyle GPLv2plus;
6428 #include <sys/types.h>
6431 #include \"guestfs.h\"
6432 #include \"guestfs-internal.h\"
6434 static guestfs_h *g;
6435 static int suppress_error = 0;
6437 static void print_error (guestfs_h *g, void *data, const char *msg)
6439 if (!suppress_error)
6440 fprintf (stderr, \"%%s\\n\", msg);
6443 /* FIXME: nearly identical code appears in fish.c */
6444 static void print_strings (char *const *argv)
6448 for (argc = 0; argv[argc] != NULL; ++argc)
6449 printf (\"\\t%%s\\n\", argv[argc]);
6453 static void print_table (char const *const *argv)
6457 for (i = 0; argv[i] != NULL; i += 2)
6458 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6464 (* Generate a list of commands which are not tested anywhere. *)
6465 pr "static void no_test_warnings (void)\n";
6468 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6470 fun (_, _, _, _, tests, _, _) ->
6471 let tests = filter_map (
6473 | (_, (Always|If _|Unless _), test) -> Some test
6474 | (_, Disabled, _) -> None
6476 let seq = List.concat (List.map seq_of_test tests) in
6477 let cmds_tested = List.map List.hd seq in
6478 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6482 fun (name, _, _, _, _, _, _) ->
6483 if not (Hashtbl.mem hash name) then
6484 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6490 (* Generate the actual tests. Note that we generate the tests
6491 * in reverse order, deliberately, so that (in general) the
6492 * newest tests run first. This makes it quicker and easier to
6497 fun (name, _, _, flags, tests, _, _) ->
6498 mapi (generate_one_test name flags) tests
6499 ) (List.rev all_functions) in
6500 let test_names = List.concat test_names in
6501 let nr_tests = List.length test_names in
6504 int main (int argc, char *argv[])
6507 unsigned long int n_failed = 0;
6508 const char *filename;
6510 int nr_tests, test_num = 0;
6512 setbuf (stdout, NULL);
6514 no_test_warnings ();
6516 g = guestfs_create ();
6518 printf (\"guestfs_create FAILED\\n\");
6519 exit (EXIT_FAILURE);
6522 guestfs_set_error_handler (g, print_error, NULL);
6524 guestfs_set_path (g, \"../appliance\");
6526 filename = \"test1.img\";
6527 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6530 exit (EXIT_FAILURE);
6532 if (lseek (fd, %d, SEEK_SET) == -1) {
6536 exit (EXIT_FAILURE);
6538 if (write (fd, &c, 1) == -1) {
6542 exit (EXIT_FAILURE);
6544 if (close (fd) == -1) {
6547 exit (EXIT_FAILURE);
6549 if (guestfs_add_drive (g, filename) == -1) {
6550 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6551 exit (EXIT_FAILURE);
6554 filename = \"test2.img\";
6555 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6558 exit (EXIT_FAILURE);
6560 if (lseek (fd, %d, SEEK_SET) == -1) {
6564 exit (EXIT_FAILURE);
6566 if (write (fd, &c, 1) == -1) {
6570 exit (EXIT_FAILURE);
6572 if (close (fd) == -1) {
6575 exit (EXIT_FAILURE);
6577 if (guestfs_add_drive (g, filename) == -1) {
6578 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6579 exit (EXIT_FAILURE);
6582 filename = \"test3.img\";
6583 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6586 exit (EXIT_FAILURE);
6588 if (lseek (fd, %d, SEEK_SET) == -1) {
6592 exit (EXIT_FAILURE);
6594 if (write (fd, &c, 1) == -1) {
6598 exit (EXIT_FAILURE);
6600 if (close (fd) == -1) {
6603 exit (EXIT_FAILURE);
6605 if (guestfs_add_drive (g, filename) == -1) {
6606 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6607 exit (EXIT_FAILURE);
6610 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6611 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6612 exit (EXIT_FAILURE);
6615 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6618 if (guestfs_launch (g) == -1) {
6619 printf (\"guestfs_launch FAILED\\n\");
6620 exit (EXIT_FAILURE);
6623 /* Cancel previous alarm. */
6628 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6632 pr " test_num++;\n";
6633 pr " if (guestfs_get_verbose (g))\n";
6634 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6635 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6636 pr " if (%s () == -1) {\n" test_name;
6637 pr " printf (\"%s FAILED\\n\");\n" test_name;
6638 pr " n_failed++;\n";
6643 pr " guestfs_close (g);\n";
6644 pr " unlink (\"test1.img\");\n";
6645 pr " unlink (\"test2.img\");\n";
6646 pr " unlink (\"test3.img\");\n";
6649 pr " if (n_failed > 0) {\n";
6650 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6651 pr " exit (EXIT_FAILURE);\n";
6655 pr " exit (EXIT_SUCCESS);\n";
6658 and generate_one_test name flags i (init, prereq, test) =
6659 let test_name = sprintf "test_%s_%d" name i in
6662 static int %s_skip (void)
6666 str = getenv (\"TEST_ONLY\");
6668 return strstr (str, \"%s\") == NULL;
6669 str = getenv (\"SKIP_%s\");
6670 if (str && STREQ (str, \"1\")) return 1;
6671 str = getenv (\"SKIP_TEST_%s\");
6672 if (str && STREQ (str, \"1\")) return 1;
6676 " test_name name (String.uppercase test_name) (String.uppercase name);
6679 | Disabled | Always -> ()
6680 | If code | Unless code ->
6681 pr "static int %s_prereq (void)\n" test_name;
6689 static int %s (void)
6692 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6696 " test_name test_name test_name;
6698 (* Optional functions should only be tested if the relevant
6699 * support is available in the daemon.
6705 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6707 pr " suppress_error = 1;\n";
6708 pr " r = guestfs_available (g, (char **) groups);\n";
6709 pr " suppress_error = 0;\n";
6710 pr " if (r == -1) {\n";
6711 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6720 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6722 pr " if (! %s_prereq ()) {\n" test_name;
6723 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6727 generate_one_test_body name i test_name init test;
6729 pr " if (%s_prereq ()) {\n" test_name;
6730 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6734 generate_one_test_body name i test_name init test;
6736 generate_one_test_body name i test_name init test
6744 and generate_one_test_body name i test_name init test =
6746 | InitNone (* XXX at some point, InitNone and InitEmpty became
6747 * folded together as the same thing. Really we should
6748 * make InitNone do nothing at all, but the tests may
6749 * need to be checked to make sure this is OK.
6752 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6753 List.iter (generate_test_command_call test_name)
6754 [["blockdev_setrw"; "/dev/sda"];
6758 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6759 List.iter (generate_test_command_call test_name)
6760 [["blockdev_setrw"; "/dev/sda"];
6763 ["part_disk"; "/dev/sda"; "mbr"]]
6765 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6766 List.iter (generate_test_command_call test_name)
6767 [["blockdev_setrw"; "/dev/sda"];
6770 ["part_disk"; "/dev/sda"; "mbr"];
6771 ["mkfs"; "ext2"; "/dev/sda1"];
6772 ["mount_options"; ""; "/dev/sda1"; "/"]]
6773 | InitBasicFSonLVM ->
6774 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6776 List.iter (generate_test_command_call test_name)
6777 [["blockdev_setrw"; "/dev/sda"];
6780 ["part_disk"; "/dev/sda"; "mbr"];
6781 ["pvcreate"; "/dev/sda1"];
6782 ["vgcreate"; "VG"; "/dev/sda1"];
6783 ["lvcreate"; "LV"; "VG"; "8"];
6784 ["mkfs"; "ext2"; "/dev/VG/LV"];
6785 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6787 pr " /* InitISOFS for %s */\n" test_name;
6788 List.iter (generate_test_command_call test_name)
6789 [["blockdev_setrw"; "/dev/sda"];
6792 ["mount_ro"; "/dev/sdd"; "/"]]
6795 let get_seq_last = function
6797 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6800 let seq = List.rev seq in
6801 List.rev (List.tl seq), List.hd seq
6806 pr " /* TestRun for %s (%d) */\n" name i;
6807 List.iter (generate_test_command_call test_name) seq
6808 | TestOutput (seq, expected) ->
6809 pr " /* TestOutput for %s (%d) */\n" name i;
6810 pr " const char *expected = \"%s\";\n" (c_quote expected);
6811 let seq, last = get_seq_last seq in
6813 pr " if (STRNEQ (r, expected)) {\n";
6814 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6818 List.iter (generate_test_command_call test_name) seq;
6819 generate_test_command_call ~test test_name last
6820 | TestOutputList (seq, expected) ->
6821 pr " /* TestOutputList for %s (%d) */\n" name i;
6822 let seq, last = get_seq_last seq in
6826 pr " if (!r[%d]) {\n" i;
6827 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6828 pr " print_strings (r);\n";
6832 pr " const char *expected = \"%s\";\n" (c_quote str);
6833 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6834 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6839 pr " if (r[%d] != NULL) {\n" (List.length expected);
6840 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6842 pr " print_strings (r);\n";
6846 List.iter (generate_test_command_call test_name) seq;
6847 generate_test_command_call ~test test_name last
6848 | TestOutputListOfDevices (seq, expected) ->
6849 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6850 let seq, last = get_seq_last seq in
6854 pr " if (!r[%d]) {\n" i;
6855 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6856 pr " print_strings (r);\n";
6860 pr " const char *expected = \"%s\";\n" (c_quote str);
6861 pr " r[%d][5] = 's';\n" i;
6862 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6863 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6868 pr " if (r[%d] != NULL) {\n" (List.length expected);
6869 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6871 pr " print_strings (r);\n";
6875 List.iter (generate_test_command_call test_name) seq;
6876 generate_test_command_call ~test test_name last
6877 | TestOutputInt (seq, expected) ->
6878 pr " /* TestOutputInt for %s (%d) */\n" name i;
6879 let seq, last = get_seq_last seq in
6881 pr " if (r != %d) {\n" expected;
6882 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6888 List.iter (generate_test_command_call test_name) seq;
6889 generate_test_command_call ~test test_name last
6890 | TestOutputIntOp (seq, op, expected) ->
6891 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6892 let seq, last = get_seq_last seq in
6894 pr " if (! (r %s %d)) {\n" op expected;
6895 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6896 test_name op expected;
6901 List.iter (generate_test_command_call test_name) seq;
6902 generate_test_command_call ~test test_name last
6903 | TestOutputTrue seq ->
6904 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6905 let seq, last = get_seq_last seq in
6908 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6913 List.iter (generate_test_command_call test_name) seq;
6914 generate_test_command_call ~test test_name last
6915 | TestOutputFalse seq ->
6916 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6917 let seq, last = get_seq_last seq in
6920 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6925 List.iter (generate_test_command_call test_name) seq;
6926 generate_test_command_call ~test test_name last
6927 | TestOutputLength (seq, expected) ->
6928 pr " /* TestOutputLength for %s (%d) */\n" name i;
6929 let seq, last = get_seq_last seq in
6932 pr " for (j = 0; j < %d; ++j)\n" expected;
6933 pr " if (r[j] == NULL) {\n";
6934 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6936 pr " print_strings (r);\n";
6939 pr " if (r[j] != NULL) {\n";
6940 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6942 pr " print_strings (r);\n";
6946 List.iter (generate_test_command_call test_name) seq;
6947 generate_test_command_call ~test test_name last
6948 | TestOutputBuffer (seq, expected) ->
6949 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6950 pr " const char *expected = \"%s\";\n" (c_quote expected);
6951 let seq, last = get_seq_last seq in
6952 let len = String.length expected in
6954 pr " if (size != %d) {\n" len;
6955 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6958 pr " if (STRNEQLEN (r, expected, size)) {\n";
6959 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6963 List.iter (generate_test_command_call test_name) seq;
6964 generate_test_command_call ~test test_name last
6965 | TestOutputStruct (seq, checks) ->
6966 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6967 let seq, last = get_seq_last seq in
6971 | CompareWithInt (field, expected) ->
6972 pr " if (r->%s != %d) {\n" field expected;
6973 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6974 test_name field expected;
6975 pr " (int) r->%s);\n" field;
6978 | CompareWithIntOp (field, op, expected) ->
6979 pr " if (!(r->%s %s %d)) {\n" field op expected;
6980 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6981 test_name field op expected;
6982 pr " (int) r->%s);\n" field;
6985 | CompareWithString (field, expected) ->
6986 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6987 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6988 test_name field expected;
6989 pr " r->%s);\n" field;
6992 | CompareFieldsIntEq (field1, field2) ->
6993 pr " if (r->%s != r->%s) {\n" field1 field2;
6994 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6995 test_name field1 field2;
6996 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6999 | CompareFieldsStrEq (field1, field2) ->
7000 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7001 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7002 test_name field1 field2;
7003 pr " r->%s, r->%s);\n" field1 field2;
7008 List.iter (generate_test_command_call test_name) seq;
7009 generate_test_command_call ~test test_name last
7010 | TestLastFail seq ->
7011 pr " /* TestLastFail for %s (%d) */\n" name i;
7012 let seq, last = get_seq_last seq in
7013 List.iter (generate_test_command_call test_name) seq;
7014 generate_test_command_call test_name ~expect_error:true last
7016 (* Generate the code to run a command, leaving the result in 'r'.
7017 * If you expect to get an error then you should set expect_error:true.
7019 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7021 | [] -> assert false
7023 (* Look up the command to find out what args/ret it has. *)
7026 let _, style, _, _, _, _, _ =
7027 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7030 failwithf "%s: in test, command %s was not found" test_name name in
7032 if List.length (snd style) <> List.length args then
7033 failwithf "%s: in test, wrong number of args given to %s"
7040 | OptString n, "NULL" -> ()
7043 | Dev_or_Path n, arg
7045 | OptString n, arg ->
7046 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7050 | FileIn _, _ | FileOut _, _ -> ()
7051 | StringList n, "" | DeviceList n, "" ->
7052 pr " const char *const %s[1] = { NULL };\n" n
7053 | StringList n, arg | DeviceList n, arg ->
7054 let strs = string_split " " arg in
7057 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7059 pr " const char *const %s[] = {\n" n;
7061 fun i _ -> pr " %s_%d,\n" n i
7065 ) (List.combine (snd style) args);
7068 match fst style with
7069 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7070 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7071 | RConstString _ | RConstOptString _ ->
7072 pr " const char *r;\n"; "NULL"
7073 | RString _ -> pr " char *r;\n"; "NULL"
7074 | RStringList _ | RHashtable _ ->
7078 | RStruct (_, typ) ->
7079 pr " struct guestfs_%s *r;\n" typ; "NULL"
7080 | RStructList (_, typ) ->
7081 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7084 pr " size_t size;\n";
7087 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7088 pr " r = guestfs_%s (g" name;
7090 (* Generate the parameters. *)
7093 | OptString _, "NULL" -> pr ", NULL"
7095 | Device n, _ | Dev_or_Path n, _
7099 | FileIn _, arg | FileOut _, arg ->
7100 pr ", \"%s\"" (c_quote arg)
7101 | StringList n, _ | DeviceList n, _ ->
7102 pr ", (char **) %s" n
7105 try int_of_string arg
7106 with Failure "int_of_string" ->
7107 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7111 try Int64.of_string arg
7112 with Failure "int_of_string" ->
7113 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7116 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7117 ) (List.combine (snd style) args);
7119 (match fst style with
7120 | RBufferOut _ -> pr ", &size"
7126 if not expect_error then
7127 pr " if (r == %s)\n" error_code
7129 pr " if (r != %s)\n" error_code;
7132 (* Insert the test code. *)
7138 (match fst style with
7139 | RErr | RInt _ | RInt64 _ | RBool _
7140 | RConstString _ | RConstOptString _ -> ()
7141 | RString _ | RBufferOut _ -> pr " free (r);\n"
7142 | RStringList _ | RHashtable _ ->
7143 pr " for (i = 0; r[i] != NULL; ++i)\n";
7144 pr " free (r[i]);\n";
7146 | RStruct (_, typ) ->
7147 pr " guestfs_free_%s (r);\n" typ
7148 | RStructList (_, typ) ->
7149 pr " guestfs_free_%s_list (r);\n" typ
7155 let str = replace_str str "\r" "\\r" in
7156 let str = replace_str str "\n" "\\n" in
7157 let str = replace_str str "\t" "\\t" in
7158 let str = replace_str str "\000" "\\0" in
7161 (* Generate a lot of different functions for guestfish. *)
7162 and generate_fish_cmds () =
7163 generate_header CStyle GPLv2plus;
7167 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7169 let all_functions_sorted =
7171 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7172 ) all_functions_sorted in
7174 pr "#include <config.h>\n";
7176 pr "#include <stdio.h>\n";
7177 pr "#include <stdlib.h>\n";
7178 pr "#include <string.h>\n";
7179 pr "#include <inttypes.h>\n";
7181 pr "#include <guestfs.h>\n";
7182 pr "#include \"c-ctype.h\"\n";
7183 pr "#include \"full-write.h\"\n";
7184 pr "#include \"xstrtol.h\"\n";
7185 pr "#include \"fish.h\"\n";
7188 (* list_commands function, which implements guestfish -h *)
7189 pr "void list_commands (void)\n";
7191 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7192 pr " list_builtin_commands ();\n";
7194 fun (name, _, _, flags, _, shortdesc, _) ->
7195 let name = replace_char name '_' '-' in
7196 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7198 ) all_functions_sorted;
7199 pr " printf (\" %%s\\n\",";
7200 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7204 (* display_command function, which implements guestfish -h cmd *)
7205 pr "int display_command (const char *cmd)\n";
7208 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7209 let name2 = replace_char name '_' '-' in
7211 try find_map (function FishAlias n -> Some n | _ -> None) flags
7212 with Not_found -> name in
7213 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7215 match snd style with
7219 name2 (String.concat " " (List.map name_of_argt args)) in
7222 if List.mem ProtocolLimitWarning flags then
7223 ("\n\n" ^ protocol_limit_warning)
7226 (* For DangerWillRobinson commands, we should probably have
7227 * guestfish prompt before allowing you to use them (especially
7228 * in interactive mode). XXX
7232 if List.mem DangerWillRobinson flags then
7233 ("\n\n" ^ danger_will_robinson)
7238 match deprecation_notice flags with
7240 | Some txt -> "\n\n" ^ txt in
7242 let describe_alias =
7243 if name <> alias then
7244 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7248 pr "STRCASEEQ (cmd, \"%s\")" name;
7249 if name <> name2 then
7250 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7251 if name <> alias then
7252 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7254 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7256 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7257 "=head1 DESCRIPTION\n\n" ^
7258 longdesc ^ warnings ^ describe_alias);
7263 pr " return display_builtin_command (cmd);\n";
7267 let emit_print_list_function typ =
7268 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7271 pr " unsigned int i;\n";
7273 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7274 pr " printf (\"[%%d] = {\\n\", i);\n";
7275 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7276 pr " printf (\"}\\n\");\n";
7282 (* print_* functions *)
7286 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7288 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7291 pr " unsigned int i;\n";
7297 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7299 pr " printf (\"%%s%s: \", indent);\n" name;
7300 pr " for (i = 0; i < 32; ++i)\n";
7301 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7302 pr " printf (\"\\n\");\n"
7304 pr " printf (\"%%s%s: \", indent);\n" name;
7305 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7306 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7307 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7309 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7310 pr " printf (\"\\n\");\n"
7311 | name, (FUInt64|FBytes) ->
7312 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7315 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7318 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7321 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7324 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7326 | name, FOptPercent ->
7327 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7328 typ name name typ name;
7329 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7335 (* Emit a print_TYPE_list function definition only if that function is used. *)
7338 | typ, (RStructListOnly | RStructAndList) ->
7339 (* generate the function for typ *)
7340 emit_print_list_function typ
7341 | typ, _ -> () (* empty *)
7342 ) (rstructs_used_by all_functions);
7344 (* Emit a print_TYPE function definition only if that function is used. *)
7347 | typ, (RStructOnly | RStructAndList) ->
7348 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7350 pr " print_%s_indent (%s, \"\");\n" typ typ;
7353 | typ, _ -> () (* empty *)
7354 ) (rstructs_used_by all_functions);
7356 (* run_<action> actions *)
7358 fun (name, style, _, flags, _, _, _) ->
7359 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7361 (match fst style with
7364 | RBool _ -> pr " int r;\n"
7365 | RInt64 _ -> pr " int64_t r;\n"
7366 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7367 | RString _ -> pr " char *r;\n"
7368 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7369 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7370 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7373 pr " size_t size;\n";
7381 | FileOut n -> pr " const char *%s;\n" n
7383 | Dev_or_Path n -> pr " char *%s;\n" n
7384 | StringList n | DeviceList n -> pr " char **%s;\n" n
7385 | Bool n -> pr " int %s;\n" n
7386 | Int n -> pr " int %s;\n" n
7387 | Int64 n -> pr " int64_t %s;\n" n
7390 (* Check and convert parameters. *)
7391 let argc_expected = List.length (snd style) in
7392 pr " if (argc != %d) {\n" argc_expected;
7393 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7395 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7399 let parse_integer fn fntyp rtyp range name i =
7401 pr " strtol_error xerr;\n";
7402 pr " %s r;\n" fntyp;
7404 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7405 pr " if (xerr != LONGINT_OK) {\n";
7406 pr " fprintf (stderr,\n";
7407 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7408 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7413 | Some (min, max, comment) ->
7414 pr " /* %s */\n" comment;
7415 pr " if (r < %s || r > %s) {\n" min max;
7416 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7420 pr " /* The check above should ensure this assignment does not overflow. */\n";
7422 pr " %s = r;\n" name;
7431 pr " %s = argv[%d];\n" name i
7433 | Dev_or_Path name ->
7434 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7435 pr " if (%s == NULL) return -1;\n" name
7437 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7440 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7443 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7445 | StringList name | DeviceList name ->
7446 pr " %s = parse_string_list (argv[%d]);\n" name i;
7447 pr " if (%s == NULL) return -1;\n" name;
7449 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7452 let min = "(-(2LL<<30))"
7453 and max = "((2LL<<30)-1)"
7455 "The Int type in the generator is a signed 31 bit int." in
7456 Some (min, max, comment) in
7457 parse_integer "xstrtoll" "long long" "int" range name i
7459 parse_integer "xstrtoll" "long long" "int64_t" None name i
7462 (* Call C API function. *)
7464 try find_map (function FishAction n -> Some n | _ -> None) flags
7465 with Not_found -> sprintf "guestfs_%s" name in
7467 generate_c_call_args ~handle:"g" style;
7472 | Device name | String name
7473 | OptString name | FileIn name | FileOut name | Bool name
7474 | Int name | Int64 name -> ()
7475 | Pathname name | Dev_or_Path name ->
7476 pr " free (%s);\n" name
7477 | StringList name | DeviceList name ->
7478 pr " free_strings (%s);\n" name
7481 (* Check return value for errors and display command results. *)
7482 (match fst style with
7483 | RErr -> pr " return r;\n"
7485 pr " if (r == -1) return -1;\n";
7486 pr " printf (\"%%d\\n\", r);\n";
7489 pr " if (r == -1) return -1;\n";
7490 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7493 pr " if (r == -1) return -1;\n";
7494 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7497 pr " if (r == NULL) return -1;\n";
7498 pr " printf (\"%%s\\n\", r);\n";
7500 | RConstOptString _ ->
7501 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7504 pr " if (r == NULL) return -1;\n";
7505 pr " printf (\"%%s\\n\", r);\n";
7509 pr " if (r == NULL) return -1;\n";
7510 pr " print_strings (r);\n";
7511 pr " free_strings (r);\n";
7513 | RStruct (_, typ) ->
7514 pr " if (r == NULL) return -1;\n";
7515 pr " print_%s (r);\n" typ;
7516 pr " guestfs_free_%s (r);\n" typ;
7518 | RStructList (_, typ) ->
7519 pr " if (r == NULL) return -1;\n";
7520 pr " print_%s_list (r);\n" typ;
7521 pr " guestfs_free_%s_list (r);\n" typ;
7524 pr " if (r == NULL) return -1;\n";
7525 pr " print_table (r);\n";
7526 pr " free_strings (r);\n";
7529 pr " if (r == NULL) return -1;\n";
7530 pr " if (full_write (1, r, size) != size) {\n";
7531 pr " perror (\"write\");\n";
7542 (* run_action function *)
7543 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7546 fun (name, _, _, flags, _, _, _) ->
7547 let name2 = replace_char name '_' '-' in
7549 try find_map (function FishAlias n -> Some n | _ -> None) flags
7550 with Not_found -> name in
7552 pr "STRCASEEQ (cmd, \"%s\")" name;
7553 if name <> name2 then
7554 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7555 if name <> alias then
7556 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7558 pr " return run_%s (cmd, argc, argv);\n" name;
7562 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7563 pr " if (command_num == 1)\n";
7564 pr " extended_help_message ();\n";
7571 (* Readline completion for guestfish. *)
7572 and generate_fish_completion () =
7573 generate_header CStyle GPLv2plus;
7577 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7587 #ifdef HAVE_LIBREADLINE
7588 #include <readline/readline.h>
7593 #ifdef HAVE_LIBREADLINE
7595 static const char *const commands[] = {
7596 BUILTIN_COMMANDS_FOR_COMPLETION,
7599 (* Get the commands, including the aliases. They don't need to be
7600 * sorted - the generator() function just does a dumb linear search.
7604 fun (name, _, _, flags, _, _, _) ->
7605 let name2 = replace_char name '_' '-' in
7607 try find_map (function FishAlias n -> Some n | _ -> None) flags
7608 with Not_found -> name in
7610 if name <> alias then [name2; alias] else [name2]
7612 let commands = List.flatten commands in
7614 List.iter (pr " \"%s\",\n") commands;
7620 generator (const char *text, int state)
7622 static int index, len;
7627 len = strlen (text);
7630 rl_attempted_completion_over = 1;
7632 while ((name = commands[index]) != NULL) {
7634 if (STRCASEEQLEN (name, text, len))
7635 return strdup (name);
7641 #endif /* HAVE_LIBREADLINE */
7643 #ifdef HAVE_RL_COMPLETION_MATCHES
7644 #define RL_COMPLETION_MATCHES rl_completion_matches
7646 #ifdef HAVE_COMPLETION_MATCHES
7647 #define RL_COMPLETION_MATCHES completion_matches
7649 #endif /* else just fail if we don't have either symbol */
7652 do_completion (const char *text, int start, int end)
7654 char **matches = NULL;
7656 #ifdef HAVE_LIBREADLINE
7657 rl_completion_append_character = ' ';
7660 matches = RL_COMPLETION_MATCHES (text, generator);
7661 else if (complete_dest_paths)
7662 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7669 (* Generate the POD documentation for guestfish. *)
7670 and generate_fish_actions_pod () =
7671 let all_functions_sorted =
7673 fun (_, _, _, flags, _, _, _) ->
7674 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7675 ) all_functions_sorted in
7677 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7680 fun (name, style, _, flags, _, _, longdesc) ->
7682 Str.global_substitute rex (
7685 try Str.matched_group 1 s
7687 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7688 "C<" ^ replace_char sub '_' '-' ^ ">"
7690 let name = replace_char name '_' '-' in
7692 try find_map (function FishAlias n -> Some n | _ -> None) flags
7693 with Not_found -> name in
7695 pr "=head2 %s" name;
7696 if name <> alias then
7703 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7704 | OptString n -> pr " %s" n
7705 | StringList n | DeviceList n -> pr " '%s ...'" n
7706 | Bool _ -> pr " true|false"
7707 | Int n -> pr " %s" n
7708 | Int64 n -> pr " %s" n
7709 | FileIn n | FileOut n -> pr " (%s|-)" n
7713 pr "%s\n\n" longdesc;
7715 if List.exists (function FileIn _ | FileOut _ -> true
7716 | _ -> false) (snd style) then
7717 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7719 if List.mem ProtocolLimitWarning flags then
7720 pr "%s\n\n" protocol_limit_warning;
7722 if List.mem DangerWillRobinson flags then
7723 pr "%s\n\n" danger_will_robinson;
7725 match deprecation_notice flags with
7727 | Some txt -> pr "%s\n\n" txt
7728 ) all_functions_sorted
7730 (* Generate a C function prototype. *)
7731 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7732 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7734 ?handle name style =
7735 if extern then pr "extern ";
7736 if static then pr "static ";
7737 (match fst style with
7739 | RInt _ -> pr "int "
7740 | RInt64 _ -> pr "int64_t "
7741 | RBool _ -> pr "int "
7742 | RConstString _ | RConstOptString _ -> pr "const char *"
7743 | RString _ | RBufferOut _ -> pr "char *"
7744 | RStringList _ | RHashtable _ -> pr "char **"
7745 | RStruct (_, typ) ->
7746 if not in_daemon then pr "struct guestfs_%s *" typ
7747 else pr "guestfs_int_%s *" typ
7748 | RStructList (_, typ) ->
7749 if not in_daemon then pr "struct guestfs_%s_list *" typ
7750 else pr "guestfs_int_%s_list *" typ
7752 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7753 pr "%s%s (" prefix name;
7754 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7757 let comma = ref false in
7760 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7764 if single_line then pr ", " else pr ",\n\t\t"
7771 | Device n | Dev_or_Path n
7775 pr "const char *%s" n
7776 | StringList n | DeviceList n ->
7778 pr "char *const *%s" n
7779 | Bool n -> next (); pr "int %s" n
7780 | Int n -> next (); pr "int %s" n
7781 | Int64 n -> next (); pr "int64_t %s" n
7784 if not in_daemon then (next (); pr "const char *%s" n)
7786 if is_RBufferOut then (next (); pr "size_t *size_r");
7789 if semicolon then pr ";";
7790 if newline then pr "\n"
7792 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7793 and generate_c_call_args ?handle ?(decl = false) style =
7795 let comma = ref false in
7797 if !comma then pr ", ";
7802 | Some handle -> pr "%s" handle; comma := true
7807 pr "%s" (name_of_argt arg)
7809 (* For RBufferOut calls, add implicit &size parameter. *)
7811 match fst style with
7819 (* Generate the OCaml bindings interface. *)
7820 and generate_ocaml_mli () =
7821 generate_header OCamlStyle LGPLv2plus;
7824 (** For API documentation you should refer to the C API
7825 in the guestfs(3) manual page. The OCaml API uses almost
7826 exactly the same calls. *)
7829 (** A [guestfs_h] handle. *)
7831 exception Error of string
7832 (** This exception is raised when there is an error. *)
7834 exception Handle_closed of string
7835 (** This exception is raised if you use a {!Guestfs.t} handle
7836 after calling {!close} on it. The string is the name of
7839 val create : unit -> t
7840 (** Create a {!Guestfs.t} handle. *)
7842 val close : t -> unit
7843 (** Close the {!Guestfs.t} handle and free up all resources used
7846 Handles are closed by the garbage collector when they become
7847 unreferenced, but callers can call this in order to provide
7848 predictable cleanup. *)
7851 generate_ocaml_structure_decls ();
7855 fun (name, style, _, _, _, shortdesc, _) ->
7856 generate_ocaml_prototype name style;
7857 pr "(** %s *)\n" shortdesc;
7859 ) all_functions_sorted
7861 (* Generate the OCaml bindings implementation. *)
7862 and generate_ocaml_ml () =
7863 generate_header OCamlStyle LGPLv2plus;
7868 exception Error of string
7869 exception Handle_closed of string
7871 external create : unit -> t = \"ocaml_guestfs_create\"
7872 external close : t -> unit = \"ocaml_guestfs_close\"
7874 (* Give the exceptions names, so they can be raised from the C code. *)
7876 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7877 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7881 generate_ocaml_structure_decls ();
7885 fun (name, style, _, _, _, shortdesc, _) ->
7886 generate_ocaml_prototype ~is_external:true name style;
7887 ) all_functions_sorted
7889 (* Generate the OCaml bindings C implementation. *)
7890 and generate_ocaml_c () =
7891 generate_header CStyle LGPLv2plus;
7898 #include <caml/config.h>
7899 #include <caml/alloc.h>
7900 #include <caml/callback.h>
7901 #include <caml/fail.h>
7902 #include <caml/memory.h>
7903 #include <caml/mlvalues.h>
7904 #include <caml/signals.h>
7906 #include <guestfs.h>
7908 #include \"guestfs_c.h\"
7910 /* Copy a hashtable of string pairs into an assoc-list. We return
7911 * the list in reverse order, but hashtables aren't supposed to be
7914 static CAMLprim value
7915 copy_table (char * const * argv)
7918 CAMLlocal5 (rv, pairv, kv, vv, cons);
7922 for (i = 0; argv[i] != NULL; i += 2) {
7923 kv = caml_copy_string (argv[i]);
7924 vv = caml_copy_string (argv[i+1]);
7925 pairv = caml_alloc (2, 0);
7926 Store_field (pairv, 0, kv);
7927 Store_field (pairv, 1, vv);
7928 cons = caml_alloc (2, 0);
7929 Store_field (cons, 1, rv);
7931 Store_field (cons, 0, pairv);
7939 (* Struct copy functions. *)
7941 let emit_ocaml_copy_list_function typ =
7942 pr "static CAMLprim value\n";
7943 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7945 pr " CAMLparam0 ();\n";
7946 pr " CAMLlocal2 (rv, v);\n";
7947 pr " unsigned int i;\n";
7949 pr " if (%ss->len == 0)\n" typ;
7950 pr " CAMLreturn (Atom (0));\n";
7952 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7953 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7954 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7955 pr " caml_modify (&Field (rv, i), v);\n";
7957 pr " CAMLreturn (rv);\n";
7965 let has_optpercent_col =
7966 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7968 pr "static CAMLprim value\n";
7969 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7971 pr " CAMLparam0 ();\n";
7972 if has_optpercent_col then
7973 pr " CAMLlocal3 (rv, v, v2);\n"
7975 pr " CAMLlocal2 (rv, v);\n";
7977 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7982 pr " v = caml_copy_string (%s->%s);\n" typ name
7984 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7985 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7988 pr " v = caml_alloc_string (32);\n";
7989 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7990 | name, (FBytes|FInt64|FUInt64) ->
7991 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7992 | name, (FInt32|FUInt32) ->
7993 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7994 | name, FOptPercent ->
7995 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7996 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7997 pr " v = caml_alloc (1, 0);\n";
7998 pr " Store_field (v, 0, v2);\n";
7999 pr " } else /* None */\n";
8000 pr " v = Val_int (0);\n";
8002 pr " v = Val_int (%s->%s);\n" typ name
8004 pr " Store_field (rv, %d, v);\n" i
8006 pr " CAMLreturn (rv);\n";
8011 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8014 | typ, (RStructListOnly | RStructAndList) ->
8015 (* generate the function for typ *)
8016 emit_ocaml_copy_list_function typ
8017 | typ, _ -> () (* empty *)
8018 ) (rstructs_used_by all_functions);
8022 fun (name, style, _, _, _, _, _) ->
8023 pr "/* Automatically generated wrapper for function\n";
8025 generate_ocaml_prototype name style;
8030 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8032 let needs_extra_vs =
8033 match fst style with RConstOptString _ -> true | _ -> false in
8035 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8036 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8037 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8040 pr "CAMLprim value\n";
8041 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8042 List.iter (pr ", value %s") (List.tl params);
8047 | [p1; p2; p3; p4; p5] ->
8048 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8049 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8050 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8051 pr " CAMLxparam%d (%s);\n"
8052 (List.length rest) (String.concat ", " rest)
8054 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8056 if not needs_extra_vs then
8057 pr " CAMLlocal1 (rv);\n"
8059 pr " CAMLlocal3 (rv, v, v2);\n";
8062 pr " guestfs_h *g = Guestfs_val (gv);\n";
8063 pr " if (g == NULL)\n";
8064 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8070 | Device n | Dev_or_Path n
8074 pr " const char *%s = String_val (%sv);\n" n n
8076 pr " const char *%s =\n" n;
8077 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8079 | StringList n | DeviceList n ->
8080 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8082 pr " int %s = Bool_val (%sv);\n" n n
8084 pr " int %s = Int_val (%sv);\n" n n
8086 pr " int64_t %s = Int64_val (%sv);\n" n n
8089 match fst style with
8090 | RErr -> pr " int r;\n"; "-1"
8091 | RInt _ -> pr " int r;\n"; "-1"
8092 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8093 | RBool _ -> pr " int r;\n"; "-1"
8094 | RConstString _ | RConstOptString _ ->
8095 pr " const char *r;\n"; "NULL"
8096 | RString _ -> pr " char *r;\n"; "NULL"
8101 | RStruct (_, typ) ->
8102 pr " struct guestfs_%s *r;\n" typ; "NULL"
8103 | RStructList (_, typ) ->
8104 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8111 pr " size_t size;\n";
8115 pr " caml_enter_blocking_section ();\n";
8116 pr " r = guestfs_%s " name;
8117 generate_c_call_args ~handle:"g" style;
8119 pr " caml_leave_blocking_section ();\n";
8123 | StringList n | DeviceList n ->
8124 pr " ocaml_guestfs_free_strings (%s);\n" n;
8125 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8126 | Bool _ | Int _ | Int64 _
8127 | FileIn _ | FileOut _ -> ()
8130 pr " if (r == %s)\n" error_code;
8131 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8134 (match fst style with
8135 | RErr -> pr " rv = Val_unit;\n"
8136 | RInt _ -> pr " rv = Val_int (r);\n"
8138 pr " rv = caml_copy_int64 (r);\n"
8139 | RBool _ -> pr " rv = Val_bool (r);\n"
8141 pr " rv = caml_copy_string (r);\n"
8142 | RConstOptString _ ->
8143 pr " if (r) { /* Some string */\n";
8144 pr " v = caml_alloc (1, 0);\n";
8145 pr " v2 = caml_copy_string (r);\n";
8146 pr " Store_field (v, 0, v2);\n";
8147 pr " } else /* None */\n";
8148 pr " v = Val_int (0);\n";
8150 pr " rv = caml_copy_string (r);\n";
8153 pr " rv = caml_copy_string_array ((const char **) r);\n";
8154 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8156 | RStruct (_, typ) ->
8157 pr " rv = copy_%s (r);\n" typ;
8158 pr " guestfs_free_%s (r);\n" typ;
8159 | RStructList (_, typ) ->
8160 pr " rv = copy_%s_list (r);\n" typ;
8161 pr " guestfs_free_%s_list (r);\n" typ;
8163 pr " rv = copy_table (r);\n";
8164 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8167 pr " rv = caml_alloc_string (size);\n";
8168 pr " memcpy (String_val (rv), r, size);\n";
8171 pr " CAMLreturn (rv);\n";
8175 if List.length params > 5 then (
8176 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8177 pr "CAMLprim value ";
8178 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8179 pr "CAMLprim value\n";
8180 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8182 pr " return ocaml_guestfs_%s (argv[0]" name;
8183 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8188 ) all_functions_sorted
8190 and generate_ocaml_structure_decls () =
8193 pr "type %s = {\n" typ;
8196 | name, FString -> pr " %s : string;\n" name
8197 | name, FBuffer -> pr " %s : string;\n" name
8198 | name, FUUID -> pr " %s : string;\n" name
8199 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8200 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8201 | name, FChar -> pr " %s : char;\n" name
8202 | name, FOptPercent -> pr " %s : float option;\n" name
8208 and generate_ocaml_prototype ?(is_external = false) name style =
8209 if is_external then pr "external " else pr "val ";
8210 pr "%s : t -> " name;
8213 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8214 | OptString _ -> pr "string option -> "
8215 | StringList _ | DeviceList _ -> pr "string array -> "
8216 | Bool _ -> pr "bool -> "
8217 | Int _ -> pr "int -> "
8218 | Int64 _ -> pr "int64 -> "
8220 (match fst style with
8221 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8222 | RInt _ -> pr "int"
8223 | RInt64 _ -> pr "int64"
8224 | RBool _ -> pr "bool"
8225 | RConstString _ -> pr "string"
8226 | RConstOptString _ -> pr "string option"
8227 | RString _ | RBufferOut _ -> pr "string"
8228 | RStringList _ -> pr "string array"
8229 | RStruct (_, typ) -> pr "%s" typ
8230 | RStructList (_, typ) -> pr "%s array" typ
8231 | RHashtable _ -> pr "(string * string) list"
8233 if is_external then (
8235 if List.length (snd style) + 1 > 5 then
8236 pr "\"ocaml_guestfs_%s_byte\" " name;
8237 pr "\"ocaml_guestfs_%s\"" name
8241 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8242 and generate_perl_xs () =
8243 generate_header CStyle LGPLv2plus;
8246 #include \"EXTERN.h\"
8250 #include <guestfs.h>
8253 #define PRId64 \"lld\"
8257 my_newSVll(long long val) {
8258 #ifdef USE_64_BIT_ALL
8259 return newSViv(val);
8263 len = snprintf(buf, 100, \"%%\" PRId64, val);
8264 return newSVpv(buf, len);
8269 #define PRIu64 \"llu\"
8273 my_newSVull(unsigned long long val) {
8274 #ifdef USE_64_BIT_ALL
8275 return newSVuv(val);
8279 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8280 return newSVpv(buf, len);
8284 /* http://www.perlmonks.org/?node_id=680842 */
8286 XS_unpack_charPtrPtr (SV *arg) {
8291 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8292 croak (\"array reference expected\");
8294 av = (AV *)SvRV (arg);
8295 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8297 croak (\"malloc failed\");
8299 for (i = 0; i <= av_len (av); i++) {
8300 SV **elem = av_fetch (av, i, 0);
8302 if (!elem || !*elem)
8303 croak (\"missing element in list\");
8305 ret[i] = SvPV_nolen (*elem);
8313 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8320 RETVAL = guestfs_create ();
8322 croak (\"could not create guestfs handle\");
8323 guestfs_set_error_handler (RETVAL, NULL, NULL);
8336 fun (name, style, _, _, _, _, _) ->
8337 (match fst style with
8338 | RErr -> pr "void\n"
8339 | RInt _ -> pr "SV *\n"
8340 | RInt64 _ -> pr "SV *\n"
8341 | RBool _ -> pr "SV *\n"
8342 | RConstString _ -> pr "SV *\n"
8343 | RConstOptString _ -> pr "SV *\n"
8344 | RString _ -> pr "SV *\n"
8345 | RBufferOut _ -> pr "SV *\n"
8347 | RStruct _ | RStructList _
8349 pr "void\n" (* all lists returned implictly on the stack *)
8351 (* Call and arguments. *)
8353 generate_c_call_args ~handle:"g" ~decl:true style;
8355 pr " guestfs_h *g;\n";
8359 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8362 (* http://www.perlmonks.org/?node_id=554277
8363 * Note that the implicit handle argument means we have
8364 * to add 1 to the ST(x) operator.
8366 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8367 | StringList n | DeviceList n -> pr " char **%s;\n" n
8368 | Bool n -> pr " int %s;\n" n
8369 | Int n -> pr " int %s;\n" n
8370 | Int64 n -> pr " int64_t %s;\n" n
8373 let do_cleanups () =
8376 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8377 | Bool _ | Int _ | Int64 _
8378 | FileIn _ | FileOut _ -> ()
8379 | StringList n | DeviceList n -> pr " free (%s);\n" n
8384 (match fst style with
8389 pr " r = guestfs_%s " name;
8390 generate_c_call_args ~handle:"g" style;
8393 pr " if (r == -1)\n";
8394 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8400 pr " %s = guestfs_%s " n name;
8401 generate_c_call_args ~handle:"g" style;
8404 pr " if (%s == -1)\n" n;
8405 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8406 pr " RETVAL = newSViv (%s);\n" n;
8411 pr " int64_t %s;\n" n;
8413 pr " %s = guestfs_%s " n name;
8414 generate_c_call_args ~handle:"g" style;
8417 pr " if (%s == -1)\n" n;
8418 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8419 pr " RETVAL = my_newSVll (%s);\n" n;
8424 pr " const char *%s;\n" n;
8426 pr " %s = guestfs_%s " n name;
8427 generate_c_call_args ~handle:"g" style;
8430 pr " if (%s == NULL)\n" n;
8431 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8432 pr " RETVAL = newSVpv (%s, 0);\n" n;
8435 | RConstOptString n ->
8437 pr " const char *%s;\n" n;
8439 pr " %s = guestfs_%s " n name;
8440 generate_c_call_args ~handle:"g" style;
8443 pr " if (%s == NULL)\n" n;
8444 pr " RETVAL = &PL_sv_undef;\n";
8446 pr " RETVAL = newSVpv (%s, 0);\n" n;
8451 pr " char *%s;\n" n;
8453 pr " %s = guestfs_%s " n name;
8454 generate_c_call_args ~handle:"g" style;
8457 pr " if (%s == NULL)\n" n;
8458 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8459 pr " RETVAL = newSVpv (%s, 0);\n" n;
8460 pr " free (%s);\n" n;
8463 | RStringList n | RHashtable n ->
8465 pr " char **%s;\n" n;
8468 pr " %s = guestfs_%s " n name;
8469 generate_c_call_args ~handle:"g" style;
8472 pr " if (%s == NULL)\n" n;
8473 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8474 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8475 pr " EXTEND (SP, n);\n";
8476 pr " for (i = 0; i < n; ++i) {\n";
8477 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8478 pr " free (%s[i]);\n" n;
8480 pr " free (%s);\n" n;
8481 | RStruct (n, typ) ->
8482 let cols = cols_of_struct typ in
8483 generate_perl_struct_code typ cols name style n do_cleanups
8484 | RStructList (n, typ) ->
8485 let cols = cols_of_struct typ in
8486 generate_perl_struct_list_code typ cols name style n do_cleanups
8489 pr " char *%s;\n" n;
8490 pr " size_t size;\n";
8492 pr " %s = guestfs_%s " n name;
8493 generate_c_call_args ~handle:"g" style;
8496 pr " if (%s == NULL)\n" n;
8497 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8498 pr " RETVAL = newSVpvn (%s, size);\n" n;
8499 pr " free (%s);\n" n;
8507 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8509 pr " struct guestfs_%s_list *%s;\n" typ n;
8513 pr " %s = guestfs_%s " n name;
8514 generate_c_call_args ~handle:"g" style;
8517 pr " if (%s == NULL)\n" n;
8518 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8519 pr " EXTEND (SP, %s->len);\n" n;
8520 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8521 pr " hv = newHV ();\n";
8525 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8526 name (String.length name) n name
8528 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8529 name (String.length name) n name
8531 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8532 name (String.length name) n name n name
8533 | name, (FBytes|FUInt64) ->
8534 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8535 name (String.length name) n name
8537 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8538 name (String.length name) n name
8539 | name, (FInt32|FUInt32) ->
8540 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8541 name (String.length name) n name
8543 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8544 name (String.length name) n name
8545 | name, FOptPercent ->
8546 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8547 name (String.length name) n name
8549 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8551 pr " guestfs_free_%s_list (%s);\n" typ n
8553 and generate_perl_struct_code typ cols name style n do_cleanups =
8555 pr " struct guestfs_%s *%s;\n" typ n;
8557 pr " %s = guestfs_%s " n name;
8558 generate_c_call_args ~handle:"g" style;
8561 pr " if (%s == NULL)\n" n;
8562 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8563 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8565 fun ((name, _) as col) ->
8566 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8570 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8573 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8576 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8578 | name, (FBytes|FUInt64) ->
8579 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8582 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8584 | name, (FInt32|FUInt32) ->
8585 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8588 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8590 | name, FOptPercent ->
8591 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8594 pr " free (%s);\n" n
8596 (* Generate Sys/Guestfs.pm. *)
8597 and generate_perl_pm () =
8598 generate_header HashStyle LGPLv2plus;
8605 Sys::Guestfs - Perl bindings for libguestfs
8611 my $h = Sys::Guestfs->new ();
8612 $h->add_drive ('guest.img');
8614 $h->mount ('/dev/sda1', '/');
8615 $h->touch ('/hello');
8620 The C<Sys::Guestfs> module provides a Perl XS binding to the
8621 libguestfs API for examining and modifying virtual machine
8624 Amongst the things this is good for: making batch configuration
8625 changes to guests, getting disk used/free statistics (see also:
8626 virt-df), migrating between virtualization systems (see also:
8627 virt-p2v), performing partial backups, performing partial guest
8628 clones, cloning guests and changing registry/UUID/hostname info, and
8631 Libguestfs uses Linux kernel and qemu code, and can access any type of
8632 guest filesystem that Linux and qemu can, including but not limited
8633 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8634 schemes, qcow, qcow2, vmdk.
8636 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8637 LVs, what filesystem is in each LV, etc.). It can also run commands
8638 in the context of the guest. Also you can access filesystems over
8641 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8642 functions for using libguestfs from Perl, including integration
8647 All errors turn into calls to C<croak> (see L<Carp(3)>).
8655 package Sys::Guestfs;
8661 XSLoader::load ('Sys::Guestfs');
8663 =item $h = Sys::Guestfs->new ();
8665 Create a new guestfs handle.
8671 my $class = ref ($proto) || $proto;
8673 my $self = Sys::Guestfs::_create ();
8674 bless $self, $class;
8680 (* Actions. We only need to print documentation for these as
8681 * they are pulled in from the XS code automatically.
8684 fun (name, style, _, flags, _, _, longdesc) ->
8685 if not (List.mem NotInDocs flags) then (
8686 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8688 generate_perl_prototype name style;
8690 pr "%s\n\n" longdesc;
8691 if List.mem ProtocolLimitWarning flags then
8692 pr "%s\n\n" protocol_limit_warning;
8693 if List.mem DangerWillRobinson flags then
8694 pr "%s\n\n" danger_will_robinson;
8695 match deprecation_notice flags with
8697 | Some txt -> pr "%s\n\n" txt
8699 ) all_functions_sorted;
8711 Copyright (C) %s Red Hat Inc.
8715 Please see the file COPYING.LIB for the full license.
8721 L<http://libguestfs.org>,
8722 L<Sys::Guestfs::Lib(3)>.
8727 and generate_perl_prototype name style =
8728 (match fst style with
8736 | RBufferOut n -> pr "$%s = " n
8738 | RHashtable n -> pr "%%%s = " n
8740 | RStructList (n,_) -> pr "@%s = " n
8743 let comma = ref false in
8746 if !comma then pr ", ";
8749 | Pathname n | Device n | Dev_or_Path n | String n
8750 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8752 | StringList n | DeviceList n ->
8757 (* Generate Python C module. *)
8758 and generate_python_c () =
8759 generate_header CStyle LGPLv2plus;
8768 #include \"guestfs.h\"
8776 get_handle (PyObject *obj)
8779 assert (obj != Py_None);
8780 return ((Pyguestfs_Object *) obj)->g;
8784 put_handle (guestfs_h *g)
8788 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8791 /* This list should be freed (but not the strings) after use. */
8793 get_string_list (PyObject *obj)
8800 if (!PyList_Check (obj)) {
8801 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8805 len = PyList_Size (obj);
8806 r = malloc (sizeof (char *) * (len+1));
8808 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8812 for (i = 0; i < len; ++i)
8813 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8820 put_string_list (char * const * const argv)
8825 for (argc = 0; argv[argc] != NULL; ++argc)
8828 list = PyList_New (argc);
8829 for (i = 0; i < argc; ++i)
8830 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8836 put_table (char * const * const argv)
8838 PyObject *list, *item;
8841 for (argc = 0; argv[argc] != NULL; ++argc)
8844 list = PyList_New (argc >> 1);
8845 for (i = 0; i < argc; i += 2) {
8846 item = PyTuple_New (2);
8847 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8848 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8849 PyList_SetItem (list, i >> 1, item);
8856 free_strings (char **argv)
8860 for (argc = 0; argv[argc] != NULL; ++argc)
8866 py_guestfs_create (PyObject *self, PyObject *args)
8870 g = guestfs_create ();
8872 PyErr_SetString (PyExc_RuntimeError,
8873 \"guestfs.create: failed to allocate handle\");
8876 guestfs_set_error_handler (g, NULL, NULL);
8877 return put_handle (g);
8881 py_guestfs_close (PyObject *self, PyObject *args)
8886 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8888 g = get_handle (py_g);
8892 Py_INCREF (Py_None);
8898 let emit_put_list_function typ =
8899 pr "static PyObject *\n";
8900 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8902 pr " PyObject *list;\n";
8905 pr " list = PyList_New (%ss->len);\n" typ;
8906 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8907 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8908 pr " return list;\n";
8913 (* Structures, turned into Python dictionaries. *)
8916 pr "static PyObject *\n";
8917 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8919 pr " PyObject *dict;\n";
8921 pr " dict = PyDict_New ();\n";
8925 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8926 pr " PyString_FromString (%s->%s));\n"
8929 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8930 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8933 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8934 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8936 | name, (FBytes|FUInt64) ->
8937 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8938 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8941 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8942 pr " PyLong_FromLongLong (%s->%s));\n"
8945 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8946 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8949 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8950 pr " PyLong_FromLong (%s->%s));\n"
8952 | name, FOptPercent ->
8953 pr " if (%s->%s >= 0)\n" typ name;
8954 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8955 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8958 pr " Py_INCREF (Py_None);\n";
8959 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8962 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8963 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8965 pr " return dict;\n";
8971 (* Emit a put_TYPE_list function definition only if that function is used. *)
8974 | typ, (RStructListOnly | RStructAndList) ->
8975 (* generate the function for typ *)
8976 emit_put_list_function typ
8977 | typ, _ -> () (* empty *)
8978 ) (rstructs_used_by all_functions);
8980 (* Python wrapper functions. *)
8982 fun (name, style, _, _, _, _, _) ->
8983 pr "static PyObject *\n";
8984 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8987 pr " PyObject *py_g;\n";
8988 pr " guestfs_h *g;\n";
8989 pr " PyObject *py_r;\n";
8992 match fst style with
8993 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8994 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8995 | RConstString _ | RConstOptString _ ->
8996 pr " const char *r;\n"; "NULL"
8997 | RString _ -> pr " char *r;\n"; "NULL"
8998 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8999 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9000 | RStructList (_, typ) ->
9001 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9004 pr " size_t size;\n";
9009 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9010 pr " const char *%s;\n" n
9011 | OptString n -> pr " const char *%s;\n" n
9012 | StringList n | DeviceList n ->
9013 pr " PyObject *py_%s;\n" n;
9014 pr " char **%s;\n" n
9015 | Bool n -> pr " int %s;\n" n
9016 | Int n -> pr " int %s;\n" n
9017 | Int64 n -> pr " long long %s;\n" n
9022 (* Convert the parameters. *)
9023 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9026 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9027 | OptString _ -> pr "z"
9028 | StringList _ | DeviceList _ -> pr "O"
9029 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9031 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9032 * emulate C's int/long/long long in Python?
9035 pr ":guestfs_%s\",\n" name;
9039 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9040 | OptString n -> pr ", &%s" n
9041 | StringList n | DeviceList n -> pr ", &py_%s" n
9042 | Bool n -> pr ", &%s" n
9043 | Int n -> pr ", &%s" n
9044 | Int64 n -> pr ", &%s" n
9048 pr " return NULL;\n";
9050 pr " g = get_handle (py_g);\n";
9053 | Pathname _ | Device _ | Dev_or_Path _ | String _
9054 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9055 | StringList n | DeviceList n ->
9056 pr " %s = get_string_list (py_%s);\n" n n;
9057 pr " if (!%s) return NULL;\n" n
9062 pr " r = guestfs_%s " name;
9063 generate_c_call_args ~handle:"g" style;
9068 | Pathname _ | Device _ | Dev_or_Path _ | String _
9069 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9070 | StringList n | DeviceList n ->
9071 pr " free (%s);\n" n
9074 pr " if (r == %s) {\n" error_code;
9075 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9076 pr " return NULL;\n";
9080 (match fst style with
9082 pr " Py_INCREF (Py_None);\n";
9083 pr " py_r = Py_None;\n"
9085 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9086 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9087 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9088 | RConstOptString _ ->
9090 pr " py_r = PyString_FromString (r);\n";
9092 pr " Py_INCREF (Py_None);\n";
9093 pr " py_r = Py_None;\n";
9096 pr " py_r = PyString_FromString (r);\n";
9099 pr " py_r = put_string_list (r);\n";
9100 pr " free_strings (r);\n"
9101 | RStruct (_, typ) ->
9102 pr " py_r = put_%s (r);\n" typ;
9103 pr " guestfs_free_%s (r);\n" typ
9104 | RStructList (_, typ) ->
9105 pr " py_r = put_%s_list (r);\n" typ;
9106 pr " guestfs_free_%s_list (r);\n" typ
9108 pr " py_r = put_table (r);\n";
9109 pr " free_strings (r);\n"
9111 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9115 pr " return py_r;\n";
9120 (* Table of functions. *)
9121 pr "static PyMethodDef methods[] = {\n";
9122 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9123 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9125 fun (name, _, _, _, _, _, _) ->
9126 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9129 pr " { NULL, NULL, 0, NULL }\n";
9133 (* Init function. *)
9136 initlibguestfsmod (void)
9138 static int initialized = 0;
9140 if (initialized) return;
9141 Py_InitModule ((char *) \"libguestfsmod\", methods);
9146 (* Generate Python module. *)
9147 and generate_python_py () =
9148 generate_header HashStyle LGPLv2plus;
9151 u\"\"\"Python bindings for libguestfs
9154 g = guestfs.GuestFS ()
9155 g.add_drive (\"guest.img\")
9157 parts = g.list_partitions ()
9159 The guestfs module provides a Python binding to the libguestfs API
9160 for examining and modifying virtual machine disk images.
9162 Amongst the things this is good for: making batch configuration
9163 changes to guests, getting disk used/free statistics (see also:
9164 virt-df), migrating between virtualization systems (see also:
9165 virt-p2v), performing partial backups, performing partial guest
9166 clones, cloning guests and changing registry/UUID/hostname info, and
9169 Libguestfs uses Linux kernel and qemu code, and can access any type of
9170 guest filesystem that Linux and qemu can, including but not limited
9171 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9172 schemes, qcow, qcow2, vmdk.
9174 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9175 LVs, what filesystem is in each LV, etc.). It can also run commands
9176 in the context of the guest. Also you can access filesystems over
9179 Errors which happen while using the API are turned into Python
9180 RuntimeError exceptions.
9182 To create a guestfs handle you usually have to perform the following
9185 # Create the handle, call add_drive at least once, and possibly
9186 # several times if the guest has multiple block devices:
9187 g = guestfs.GuestFS ()
9188 g.add_drive (\"guest.img\")
9190 # Launch the qemu subprocess and wait for it to become ready:
9193 # Now you can issue commands, for example:
9198 import libguestfsmod
9201 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9203 def __init__ (self):
9204 \"\"\"Create a new libguestfs handle.\"\"\"
9205 self._o = libguestfsmod.create ()
9208 libguestfsmod.close (self._o)
9213 fun (name, style, _, flags, _, _, longdesc) ->
9215 generate_py_call_args ~handle:"self" (snd style);
9218 if not (List.mem NotInDocs flags) then (
9219 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9221 match fst style with
9222 | RErr | RInt _ | RInt64 _ | RBool _
9223 | RConstOptString _ | RConstString _
9224 | RString _ | RBufferOut _ -> doc
9226 doc ^ "\n\nThis function returns a list of strings."
9227 | RStruct (_, typ) ->
9228 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9229 | RStructList (_, typ) ->
9230 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9232 doc ^ "\n\nThis function returns a dictionary." in
9234 if List.mem ProtocolLimitWarning flags then
9235 doc ^ "\n\n" ^ protocol_limit_warning
9238 if List.mem DangerWillRobinson flags then
9239 doc ^ "\n\n" ^ danger_will_robinson
9242 match deprecation_notice flags with
9244 | Some txt -> doc ^ "\n\n" ^ txt in
9245 let doc = pod2text ~width:60 name doc in
9246 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9247 let doc = String.concat "\n " doc in
9248 pr " u\"\"\"%s\"\"\"\n" doc;
9250 pr " return libguestfsmod.%s " name;
9251 generate_py_call_args ~handle:"self._o" (snd style);
9256 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9257 and generate_py_call_args ~handle args =
9259 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9262 (* Useful if you need the longdesc POD text as plain text. Returns a
9265 * Because this is very slow (the slowest part of autogeneration),
9266 * we memoize the results.
9268 and pod2text ~width name longdesc =
9269 let key = width, name, longdesc in
9270 try Hashtbl.find pod2text_memo key
9272 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9273 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9275 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9276 let chan = open_process_in cmd in
9277 let lines = ref [] in
9279 let line = input_line chan in
9280 if i = 1 then (* discard the first line of output *)
9283 let line = triml line in
9284 lines := line :: !lines;
9287 let lines = try loop 1 with End_of_file -> List.rev !lines in
9289 (match close_process_in chan with
9292 failwithf "pod2text: process exited with non-zero status (%d)" i
9293 | WSIGNALED i | WSTOPPED i ->
9294 failwithf "pod2text: process signalled or stopped by signal %d" i
9296 Hashtbl.add pod2text_memo key lines;
9297 pod2text_memo_updated ();
9300 (* Generate ruby bindings. *)
9301 and generate_ruby_c () =
9302 generate_header CStyle LGPLv2plus;
9310 #include \"guestfs.h\"
9312 #include \"extconf.h\"
9314 /* For Ruby < 1.9 */
9316 #define RARRAY_LEN(r) (RARRAY((r))->len)
9319 static VALUE m_guestfs; /* guestfs module */
9320 static VALUE c_guestfs; /* guestfs_h handle */
9321 static VALUE e_Error; /* used for all errors */
9323 static void ruby_guestfs_free (void *p)
9326 guestfs_close ((guestfs_h *) p);
9329 static VALUE ruby_guestfs_create (VALUE m)
9333 g = guestfs_create ();
9335 rb_raise (e_Error, \"failed to create guestfs handle\");
9337 /* Don't print error messages to stderr by default. */
9338 guestfs_set_error_handler (g, NULL, NULL);
9340 /* Wrap it, and make sure the close function is called when the
9343 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9346 static VALUE ruby_guestfs_close (VALUE gv)
9349 Data_Get_Struct (gv, guestfs_h, g);
9351 ruby_guestfs_free (g);
9352 DATA_PTR (gv) = NULL;
9360 fun (name, style, _, _, _, _, _) ->
9361 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9362 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9365 pr " guestfs_h *g;\n";
9366 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9368 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9374 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9375 pr " Check_Type (%sv, T_STRING);\n" n;
9376 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9378 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9379 pr " \"%s\", \"%s\");\n" n name
9381 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9382 | StringList n | DeviceList n ->
9383 pr " char **%s;\n" n;
9384 pr " Check_Type (%sv, T_ARRAY);\n" n;
9386 pr " int i, len;\n";
9387 pr " len = RARRAY_LEN (%sv);\n" n;
9388 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9390 pr " for (i = 0; i < len; ++i) {\n";
9391 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9392 pr " %s[i] = StringValueCStr (v);\n" n;
9394 pr " %s[len] = NULL;\n" n;
9397 pr " int %s = RTEST (%sv);\n" n n
9399 pr " int %s = NUM2INT (%sv);\n" n n
9401 pr " long long %s = NUM2LL (%sv);\n" n n
9406 match fst style with
9407 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9408 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9409 | RConstString _ | RConstOptString _ ->
9410 pr " const char *r;\n"; "NULL"
9411 | RString _ -> pr " char *r;\n"; "NULL"
9412 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9413 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9414 | RStructList (_, typ) ->
9415 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9418 pr " size_t size;\n";
9422 pr " r = guestfs_%s " name;
9423 generate_c_call_args ~handle:"g" style;
9428 | Pathname _ | Device _ | Dev_or_Path _ | String _
9429 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9430 | StringList n | DeviceList n ->
9431 pr " free (%s);\n" n
9434 pr " if (r == %s)\n" error_code;
9435 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9438 (match fst style with
9440 pr " return Qnil;\n"
9441 | RInt _ | RBool _ ->
9442 pr " return INT2NUM (r);\n"
9444 pr " return ULL2NUM (r);\n"
9446 pr " return rb_str_new2 (r);\n";
9447 | RConstOptString _ ->
9449 pr " return rb_str_new2 (r);\n";
9451 pr " return Qnil;\n";
9453 pr " VALUE rv = rb_str_new2 (r);\n";
9457 pr " int i, len = 0;\n";
9458 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9459 pr " VALUE rv = rb_ary_new2 (len);\n";
9460 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9461 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9462 pr " free (r[i]);\n";
9466 | RStruct (_, typ) ->
9467 let cols = cols_of_struct typ in
9468 generate_ruby_struct_code typ cols
9469 | RStructList (_, typ) ->
9470 let cols = cols_of_struct typ in
9471 generate_ruby_struct_list_code typ cols
9473 pr " VALUE rv = rb_hash_new ();\n";
9475 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9476 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9477 pr " free (r[i]);\n";
9478 pr " free (r[i+1]);\n";
9483 pr " VALUE rv = rb_str_new (r, size);\n";
9493 /* Initialize the module. */
9494 void Init__guestfs ()
9496 m_guestfs = rb_define_module (\"Guestfs\");
9497 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9498 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9500 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9501 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9504 (* Define the rest of the methods. *)
9506 fun (name, style, _, _, _, _, _) ->
9507 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9508 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9513 (* Ruby code to return a struct. *)
9514 and generate_ruby_struct_code typ cols =
9515 pr " VALUE rv = rb_hash_new ();\n";
9519 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9521 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9523 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9524 | name, (FBytes|FUInt64) ->
9525 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9527 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9529 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9531 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9532 | name, FOptPercent ->
9533 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9534 | name, FChar -> (* XXX wrong? *)
9535 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9537 pr " guestfs_free_%s (r);\n" typ;
9540 (* Ruby code to return a struct list. *)
9541 and generate_ruby_struct_list_code typ cols =
9542 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9544 pr " for (i = 0; i < r->len; ++i) {\n";
9545 pr " VALUE hv = rb_hash_new ();\n";
9549 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9551 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
9553 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9554 | name, (FBytes|FUInt64) ->
9555 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9557 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9559 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9561 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9562 | name, FOptPercent ->
9563 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9564 | name, FChar -> (* XXX wrong? *)
9565 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9567 pr " rb_ary_push (rv, hv);\n";
9569 pr " guestfs_free_%s_list (r);\n" typ;
9572 (* Generate Java bindings GuestFS.java file. *)
9573 and generate_java_java () =
9574 generate_header CStyle LGPLv2plus;
9577 package com.redhat.et.libguestfs;
9579 import java.util.HashMap;
9580 import com.redhat.et.libguestfs.LibGuestFSException;
9581 import com.redhat.et.libguestfs.PV;
9582 import com.redhat.et.libguestfs.VG;
9583 import com.redhat.et.libguestfs.LV;
9584 import com.redhat.et.libguestfs.Stat;
9585 import com.redhat.et.libguestfs.StatVFS;
9586 import com.redhat.et.libguestfs.IntBool;
9587 import com.redhat.et.libguestfs.Dirent;
9590 * The GuestFS object is a libguestfs handle.
9594 public class GuestFS {
9595 // Load the native code.
9597 System.loadLibrary (\"guestfs_jni\");
9601 * The native guestfs_h pointer.
9606 * Create a libguestfs handle.
9608 * @throws LibGuestFSException
9610 public GuestFS () throws LibGuestFSException
9614 private native long _create () throws LibGuestFSException;
9617 * Close a libguestfs handle.
9619 * You can also leave handles to be collected by the garbage
9620 * collector, but this method ensures that the resources used
9621 * by the handle are freed up immediately. If you call any
9622 * other methods after closing the handle, you will get an
9625 * @throws LibGuestFSException
9627 public void close () throws LibGuestFSException
9633 private native void _close (long g) throws LibGuestFSException;
9635 public void finalize () throws LibGuestFSException
9643 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9644 if not (List.mem NotInDocs flags); then (
9645 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9647 if List.mem ProtocolLimitWarning flags then
9648 doc ^ "\n\n" ^ protocol_limit_warning
9651 if List.mem DangerWillRobinson flags then
9652 doc ^ "\n\n" ^ danger_will_robinson
9655 match deprecation_notice flags with
9657 | Some txt -> doc ^ "\n\n" ^ txt in
9658 let doc = pod2text ~width:60 name doc in
9659 let doc = List.map ( (* RHBZ#501883 *)
9662 | nonempty -> nonempty
9664 let doc = String.concat "\n * " doc in
9667 pr " * %s\n" shortdesc;
9670 pr " * @throws LibGuestFSException\n";
9674 generate_java_prototype ~public:true ~semicolon:false name style;
9677 pr " if (g == 0)\n";
9678 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9681 if fst style <> RErr then pr "return ";
9683 generate_java_call_args ~handle:"g" (snd style);
9687 generate_java_prototype ~privat:true ~native:true name style;
9694 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9695 and generate_java_call_args ~handle args =
9697 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9700 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9701 ?(semicolon=true) name style =
9702 if privat then pr "private ";
9703 if public then pr "public ";
9704 if native then pr "native ";
9707 (match fst style with
9708 | RErr -> pr "void ";
9709 | RInt _ -> pr "int ";
9710 | RInt64 _ -> pr "long ";
9711 | RBool _ -> pr "boolean ";
9712 | RConstString _ | RConstOptString _ | RString _
9713 | RBufferOut _ -> pr "String ";
9714 | RStringList _ -> pr "String[] ";
9715 | RStruct (_, typ) ->
9716 let name = java_name_of_struct typ in
9718 | RStructList (_, typ) ->
9719 let name = java_name_of_struct typ in
9721 | RHashtable _ -> pr "HashMap<String,String> ";
9724 if native then pr "_%s " name else pr "%s " name;
9726 let needs_comma = ref false in
9735 if !needs_comma then pr ", ";
9736 needs_comma := true;
9740 | Device n | Dev_or_Path n
9746 | StringList n | DeviceList n ->
9757 pr " throws LibGuestFSException";
9758 if semicolon then pr ";"
9760 and generate_java_struct jtyp cols () =
9761 generate_header CStyle LGPLv2plus;
9764 package com.redhat.et.libguestfs;
9767 * Libguestfs %s structure.
9779 | name, FBuffer -> pr " public String %s;\n" name
9780 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9781 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9782 | name, FChar -> pr " public char %s;\n" name
9783 | name, FOptPercent ->
9784 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9785 pr " public float %s;\n" name
9790 and generate_java_c () =
9791 generate_header CStyle LGPLv2plus;
9798 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9799 #include \"guestfs.h\"
9801 /* Note that this function returns. The exception is not thrown
9802 * until after the wrapper function returns.
9805 throw_exception (JNIEnv *env, const char *msg)
9808 cl = (*env)->FindClass (env,
9809 \"com/redhat/et/libguestfs/LibGuestFSException\");
9810 (*env)->ThrowNew (env, cl, msg);
9813 JNIEXPORT jlong JNICALL
9814 Java_com_redhat_et_libguestfs_GuestFS__1create
9815 (JNIEnv *env, jobject obj)
9819 g = guestfs_create ();
9821 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9824 guestfs_set_error_handler (g, NULL, NULL);
9825 return (jlong) (long) g;
9828 JNIEXPORT void JNICALL
9829 Java_com_redhat_et_libguestfs_GuestFS__1close
9830 (JNIEnv *env, jobject obj, jlong jg)
9832 guestfs_h *g = (guestfs_h *) (long) jg;
9839 fun (name, style, _, _, _, _, _) ->
9841 (match fst style with
9842 | RErr -> pr "void ";
9843 | RInt _ -> pr "jint ";
9844 | RInt64 _ -> pr "jlong ";
9845 | RBool _ -> pr "jboolean ";
9846 | RConstString _ | RConstOptString _ | RString _
9847 | RBufferOut _ -> pr "jstring ";
9848 | RStruct _ | RHashtable _ ->
9850 | RStringList _ | RStructList _ ->
9854 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9855 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9857 pr " (JNIEnv *env, jobject obj, jlong jg";
9861 | Device n | Dev_or_Path n
9866 pr ", jstring j%s" n
9867 | StringList n | DeviceList n ->
9868 pr ", jobjectArray j%s" n
9870 pr ", jboolean j%s" n
9878 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9879 let error_code, no_ret =
9880 match fst style with
9881 | RErr -> pr " int r;\n"; "-1", ""
9883 | RInt _ -> pr " int r;\n"; "-1", "0"
9884 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9885 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9886 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9888 pr " jstring jr;\n";
9889 pr " char *r;\n"; "NULL", "NULL"
9891 pr " jobjectArray jr;\n";
9894 pr " jstring jstr;\n";
9895 pr " char **r;\n"; "NULL", "NULL"
9896 | RStruct (_, typ) ->
9897 pr " jobject jr;\n";
9899 pr " jfieldID fl;\n";
9900 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9901 | RStructList (_, typ) ->
9902 pr " jobjectArray jr;\n";
9904 pr " jfieldID fl;\n";
9905 pr " jobject jfl;\n";
9906 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9907 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9909 pr " jstring jr;\n";
9911 pr " size_t size;\n";
9916 | Device n | Dev_or_Path n
9921 pr " const char *%s;\n" n
9922 | StringList n | DeviceList n ->
9923 pr " int %s_len;\n" n;
9924 pr " const char **%s;\n" n
9929 pr " int64_t %s;\n" n
9933 (match fst style with
9934 | RStringList _ | RStructList _ -> true
9935 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9937 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9938 List.exists (function
9939 | StringList _ -> true
9940 | DeviceList _ -> true
9941 | _ -> false) (snd style) in
9947 (* Get the parameters. *)
9951 | Device n | Dev_or_Path n
9955 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9957 (* This is completely undocumented, but Java null becomes
9960 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9961 | StringList n | DeviceList n ->
9962 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9963 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9964 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9965 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9967 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9969 pr " %s[%s_len] = NULL;\n" n n;
9973 pr " %s = j%s;\n" n n
9976 (* Make the call. *)
9977 pr " r = guestfs_%s " name;
9978 generate_c_call_args ~handle:"g" style;
9981 (* Release the parameters. *)
9985 | Device n | Dev_or_Path n
9989 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9992 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9993 | StringList n | DeviceList n ->
9994 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9995 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9997 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9999 pr " free (%s);\n" n
10005 (* Check for errors. *)
10006 pr " if (r == %s) {\n" error_code;
10007 pr " throw_exception (env, guestfs_last_error (g));\n";
10008 pr " return %s;\n" no_ret;
10011 (* Return value. *)
10012 (match fst style with
10014 | RInt _ -> pr " return (jint) r;\n"
10015 | RBool _ -> pr " return (jboolean) r;\n"
10016 | RInt64 _ -> pr " return (jlong) r;\n"
10017 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10018 | RConstOptString _ ->
10019 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10021 pr " jr = (*env)->NewStringUTF (env, r);\n";
10025 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10026 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10027 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10028 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10029 pr " for (i = 0; i < r_len; ++i) {\n";
10030 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10031 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10032 pr " free (r[i]);\n";
10036 | RStruct (_, typ) ->
10037 let jtyp = java_name_of_struct typ in
10038 let cols = cols_of_struct typ in
10039 generate_java_struct_return typ jtyp cols
10040 | RStructList (_, typ) ->
10041 let jtyp = java_name_of_struct typ in
10042 let cols = cols_of_struct typ in
10043 generate_java_struct_list_return typ jtyp cols
10046 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10047 pr " return NULL;\n"
10049 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10058 and generate_java_struct_return typ jtyp cols =
10059 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10060 pr " jr = (*env)->AllocObject (env, cl);\n";
10064 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10065 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10068 pr " char s[33];\n";
10069 pr " memcpy (s, r->%s, 32);\n" name;
10070 pr " s[32] = 0;\n";
10071 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10072 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10076 pr " int len = r->%s_len;\n" name;
10077 pr " char s[len+1];\n";
10078 pr " memcpy (s, r->%s, len);\n" name;
10079 pr " s[len] = 0;\n";
10080 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10081 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10083 | name, (FBytes|FUInt64|FInt64) ->
10084 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10085 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10086 | name, (FUInt32|FInt32) ->
10087 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10088 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10089 | name, FOptPercent ->
10090 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10091 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10093 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10094 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10099 and generate_java_struct_list_return typ jtyp cols =
10100 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10101 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10102 pr " for (i = 0; i < r->len; ++i) {\n";
10103 pr " jfl = (*env)->AllocObject (env, cl);\n";
10107 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10108 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10111 pr " char s[33];\n";
10112 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10113 pr " s[32] = 0;\n";
10114 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10115 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10119 pr " int len = r->val[i].%s_len;\n" name;
10120 pr " char s[len+1];\n";
10121 pr " memcpy (s, r->val[i].%s, len);\n" name;
10122 pr " s[len] = 0;\n";
10123 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10124 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10126 | name, (FBytes|FUInt64|FInt64) ->
10127 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10128 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10129 | name, (FUInt32|FInt32) ->
10130 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10131 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10132 | name, FOptPercent ->
10133 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10134 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10136 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10137 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10139 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10141 pr " guestfs_free_%s_list (r);\n" typ;
10144 and generate_java_makefile_inc () =
10145 generate_header HashStyle GPLv2plus;
10147 pr "java_built_sources = \\\n";
10150 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10152 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10154 and generate_haskell_hs () =
10155 generate_header HaskellStyle LGPLv2plus;
10157 (* XXX We only know how to generate partial FFI for Haskell
10158 * at the moment. Please help out!
10160 let can_generate style =
10164 | RInt64 _, _ -> true
10166 | RConstString _, _
10167 | RConstOptString _, _
10173 | RBufferOut _, _ -> false in
10176 {-# INCLUDE <guestfs.h> #-}
10177 {-# LANGUAGE ForeignFunctionInterface #-}
10182 (* List out the names of the actions we want to export. *)
10184 fun (name, style, _, _, _, _, _) ->
10185 if can_generate style then pr ",\n %s" name
10191 -- Unfortunately some symbols duplicate ones already present
10192 -- in Prelude. We don't know which, so we hard-code a list
10194 import Prelude hiding (truncate)
10198 import Foreign.C.Types
10200 import Control.Exception
10201 import Data.Typeable
10203 data GuestfsS = GuestfsS -- represents the opaque C struct
10204 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10205 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10207 -- XXX define properly later XXX
10211 data IntBool = IntBool
10213 data StatVFS = StatVFS
10214 data Hashtable = Hashtable
10216 foreign import ccall unsafe \"guestfs_create\" c_create
10218 foreign import ccall unsafe \"&guestfs_close\" c_close
10219 :: FunPtr (GuestfsP -> IO ())
10220 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10221 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10223 create :: IO GuestfsH
10226 c_set_error_handler p nullPtr nullPtr
10227 h <- newForeignPtr c_close p
10230 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10231 :: GuestfsP -> IO CString
10233 -- last_error :: GuestfsH -> IO (Maybe String)
10234 -- last_error h = do
10235 -- str <- withForeignPtr h (\\p -> c_last_error p)
10236 -- maybePeek peekCString str
10238 last_error :: GuestfsH -> IO (String)
10240 str <- withForeignPtr h (\\p -> c_last_error p)
10241 if (str == nullPtr)
10242 then return \"no error\"
10243 else peekCString str
10247 (* Generate wrappers for each foreign function. *)
10249 fun (name, style, _, _, _, _, _) ->
10250 if can_generate style then (
10251 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10253 generate_haskell_prototype ~handle:"GuestfsP" style;
10257 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10259 pr "%s %s = do\n" name
10260 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10262 (* Convert pointer arguments using with* functions. *)
10267 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10268 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10269 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10270 | Bool _ | Int _ | Int64 _ -> ()
10272 (* Convert integer arguments. *)
10276 | Bool n -> sprintf "(fromBool %s)" n
10277 | Int n -> sprintf "(fromIntegral %s)" n
10278 | Int64 n -> sprintf "(fromIntegral %s)" n
10279 | FileIn n | FileOut n
10280 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10282 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10283 (String.concat " " ("p" :: args));
10284 (match fst style with
10285 | RErr | RInt _ | RInt64 _ | RBool _ ->
10286 pr " if (r == -1)\n";
10288 pr " err <- last_error h\n";
10290 | RConstString _ | RConstOptString _ | RString _
10291 | RStringList _ | RStruct _
10292 | RStructList _ | RHashtable _ | RBufferOut _ ->
10293 pr " if (r == nullPtr)\n";
10295 pr " err <- last_error h\n";
10298 (match fst style with
10300 pr " else return ()\n"
10302 pr " else return (fromIntegral r)\n"
10304 pr " else return (fromIntegral r)\n"
10306 pr " else return (toBool r)\n"
10308 | RConstOptString _
10315 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10321 and generate_haskell_prototype ~handle ?(hs = false) style =
10322 pr "%s -> " handle;
10323 let string = if hs then "String" else "CString" in
10324 let int = if hs then "Int" else "CInt" in
10325 let bool = if hs then "Bool" else "CInt" in
10326 let int64 = if hs then "Integer" else "Int64" in
10330 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10331 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10332 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10333 | Bool _ -> pr "%s" bool
10334 | Int _ -> pr "%s" int
10335 | Int64 _ -> pr "%s" int
10336 | FileIn _ -> pr "%s" string
10337 | FileOut _ -> pr "%s" string
10342 (match fst style with
10343 | RErr -> if not hs then pr "CInt"
10344 | RInt _ -> pr "%s" int
10345 | RInt64 _ -> pr "%s" int64
10346 | RBool _ -> pr "%s" bool
10347 | RConstString _ -> pr "%s" string
10348 | RConstOptString _ -> pr "Maybe %s" string
10349 | RString _ -> pr "%s" string
10350 | RStringList _ -> pr "[%s]" string
10351 | RStruct (_, typ) ->
10352 let name = java_name_of_struct typ in
10354 | RStructList (_, typ) ->
10355 let name = java_name_of_struct typ in
10357 | RHashtable _ -> pr "Hashtable"
10358 | RBufferOut _ -> pr "%s" string
10362 and generate_csharp () =
10363 generate_header CPlusPlusStyle LGPLv2plus;
10365 (* XXX Make this configurable by the C# assembly users. *)
10366 let library = "libguestfs.so.0" in
10369 // These C# bindings are highly experimental at present.
10371 // Firstly they only work on Linux (ie. Mono). In order to get them
10372 // to work on Windows (ie. .Net) you would need to port the library
10373 // itself to Windows first.
10375 // The second issue is that some calls are known to be incorrect and
10376 // can cause Mono to segfault. Particularly: calls which pass or
10377 // return string[], or return any structure value. This is because
10378 // we haven't worked out the correct way to do this from C#.
10380 // The third issue is that when compiling you get a lot of warnings.
10381 // We are not sure whether the warnings are important or not.
10383 // Fourthly we do not routinely build or test these bindings as part
10384 // of the make && make check cycle, which means that regressions might
10387 // Suggestions and patches are welcome.
10391 // gmcs Libguestfs.cs
10392 // mono Libguestfs.exe
10394 // (You'll probably want to add a Test class / static main function
10395 // otherwise this won't do anything useful).
10399 using System.Runtime.InteropServices;
10400 using System.Runtime.Serialization;
10401 using System.Collections;
10405 class Error : System.ApplicationException
10407 public Error (string message) : base (message) {}
10408 protected Error (SerializationInfo info, StreamingContext context) {}
10415 [DllImport (\"%s\")]
10416 static extern IntPtr guestfs_create ();
10420 _handle = guestfs_create ();
10421 if (_handle == IntPtr.Zero)
10422 throw new Error (\"could not create guestfs handle\");
10425 [DllImport (\"%s\")]
10426 static extern void guestfs_close (IntPtr h);
10430 guestfs_close (_handle);
10433 [DllImport (\"%s\")]
10434 static extern string guestfs_last_error (IntPtr h);
10436 " library library library;
10438 (* Generate C# structure bindings. We prefix struct names with
10439 * underscore because C# cannot have conflicting struct names and
10440 * method names (eg. "class stat" and "stat").
10444 pr " [StructLayout (LayoutKind.Sequential)]\n";
10445 pr " public class _%s {\n" typ;
10448 | name, FChar -> pr " char %s;\n" name
10449 | name, FString -> pr " string %s;\n" name
10451 pr " uint %s_len;\n" name;
10452 pr " string %s;\n" name
10454 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10455 pr " string %s;\n" name
10456 | name, FUInt32 -> pr " uint %s;\n" name
10457 | name, FInt32 -> pr " int %s;\n" name
10458 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10459 | name, FInt64 -> pr " long %s;\n" name
10460 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10466 (* Generate C# function bindings. *)
10468 fun (name, style, _, _, _, shortdesc, _) ->
10469 let rec csharp_return_type () =
10470 match fst style with
10472 | RBool n -> "bool"
10474 | RInt64 n -> "long"
10476 | RConstOptString n
10478 | RBufferOut n -> "string"
10479 | RStruct (_,n) -> "_" ^ n
10480 | RHashtable n -> "Hashtable"
10481 | RStringList n -> "string[]"
10482 | RStructList (_,n) -> sprintf "_%s[]" n
10484 and c_return_type () =
10485 match fst style with
10489 | RInt64 _ -> "long"
10491 | RConstOptString _
10493 | RBufferOut _ -> "string"
10494 | RStruct (_,n) -> "_" ^ n
10496 | RStringList _ -> "string[]"
10497 | RStructList (_,n) -> sprintf "_%s[]" n
10499 and c_error_comparison () =
10500 match fst style with
10504 | RInt64 _ -> "== -1"
10506 | RConstOptString _
10512 | RStructList (_,_) -> "== null"
10514 and generate_extern_prototype () =
10515 pr " static extern %s guestfs_%s (IntPtr h"
10516 (c_return_type ()) name;
10519 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10520 | FileIn n | FileOut n ->
10521 pr ", [In] string %s" n
10522 | StringList n | DeviceList n ->
10523 pr ", [In] string[] %s" n
10533 and generate_public_prototype () =
10534 pr " public %s %s (" (csharp_return_type ()) name;
10535 let comma = ref false in
10537 if !comma then pr ", ";
10542 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10543 | FileIn n | FileOut n ->
10544 next (); pr "string %s" n
10545 | StringList n | DeviceList n ->
10546 next (); pr "string[] %s" n
10548 next (); pr "bool %s" n
10550 next (); pr "int %s" n
10552 next (); pr "long %s" n
10556 and generate_call () =
10557 pr "guestfs_%s (_handle" name;
10558 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10562 pr " [DllImport (\"%s\")]\n" library;
10563 generate_extern_prototype ();
10565 pr " /// <summary>\n";
10566 pr " /// %s\n" shortdesc;
10567 pr " /// </summary>\n";
10568 generate_public_prototype ();
10570 pr " %s r;\n" (c_return_type ());
10573 pr " if (r %s)\n" (c_error_comparison ());
10574 pr " throw new Error (guestfs_last_error (_handle));\n";
10575 (match fst style with
10578 pr " return r != 0 ? true : false;\n"
10580 pr " Hashtable rr = new Hashtable ();\n";
10581 pr " for (int i = 0; i < r.Length; i += 2)\n";
10582 pr " rr.Add (r[i], r[i+1]);\n";
10584 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10585 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10591 ) all_functions_sorted;
10597 and generate_bindtests () =
10598 generate_header CStyle LGPLv2plus;
10602 #include <stdlib.h>
10603 #include <inttypes.h>
10604 #include <string.h>
10606 #include \"guestfs.h\"
10607 #include \"guestfs-internal.h\"
10608 #include \"guestfs-internal-actions.h\"
10609 #include \"guestfs_protocol.h\"
10611 #define error guestfs_error
10612 #define safe_calloc guestfs_safe_calloc
10613 #define safe_malloc guestfs_safe_malloc
10616 print_strings (char *const *argv)
10621 for (argc = 0; argv[argc] != NULL; ++argc) {
10622 if (argc > 0) printf (\", \");
10623 printf (\"\\\"%%s\\\"\", argv[argc]);
10628 /* The test0 function prints its parameters to stdout. */
10632 match test_functions with
10633 | [] -> assert false
10634 | test0 :: tests -> test0, tests in
10637 let (name, style, _, _, _, _, _) = test0 in
10638 generate_prototype ~extern:false ~semicolon:false ~newline:true
10639 ~handle:"g" ~prefix:"guestfs__" name style;
10644 | Device n | Dev_or_Path n
10647 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10648 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10649 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10650 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10651 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10652 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10654 pr " /* Java changes stdout line buffering so we need this: */\n";
10655 pr " fflush (stdout);\n";
10661 fun (name, style, _, _, _, _, _) ->
10662 if String.sub name (String.length name - 3) 3 <> "err" then (
10663 pr "/* Test normal return. */\n";
10664 generate_prototype ~extern:false ~semicolon:false ~newline:true
10665 ~handle:"g" ~prefix:"guestfs__" name style;
10667 (match fst style with
10672 pr " sscanf (val, \"%%d\", &r);\n";
10675 pr " int64_t r;\n";
10676 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10679 pr " return STREQ (val, \"true\");\n"
10681 | RConstOptString _ ->
10682 (* Can't return the input string here. Return a static
10683 * string so we ensure we get a segfault if the caller
10684 * tries to free it.
10686 pr " return \"static string\";\n"
10688 pr " return strdup (val);\n"
10690 pr " char **strs;\n";
10692 pr " sscanf (val, \"%%d\", &n);\n";
10693 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10694 pr " for (i = 0; i < n; ++i) {\n";
10695 pr " strs[i] = safe_malloc (g, 16);\n";
10696 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10698 pr " strs[n] = NULL;\n";
10699 pr " return strs;\n"
10700 | RStruct (_, typ) ->
10701 pr " struct guestfs_%s *r;\n" typ;
10702 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10704 | RStructList (_, typ) ->
10705 pr " struct guestfs_%s_list *r;\n" typ;
10706 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10707 pr " sscanf (val, \"%%d\", &r->len);\n";
10708 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10711 pr " char **strs;\n";
10713 pr " sscanf (val, \"%%d\", &n);\n";
10714 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10715 pr " for (i = 0; i < n; ++i) {\n";
10716 pr " strs[i*2] = safe_malloc (g, 16);\n";
10717 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10718 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10719 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10721 pr " strs[n*2] = NULL;\n";
10722 pr " return strs;\n"
10724 pr " return strdup (val);\n"
10729 pr "/* Test error return. */\n";
10730 generate_prototype ~extern:false ~semicolon:false ~newline:true
10731 ~handle:"g" ~prefix:"guestfs__" name style;
10733 pr " error (g, \"error\");\n";
10734 (match fst style with
10735 | RErr | RInt _ | RInt64 _ | RBool _ ->
10737 | RConstString _ | RConstOptString _
10738 | RString _ | RStringList _ | RStruct _
10742 pr " return NULL;\n"
10749 and generate_ocaml_bindtests () =
10750 generate_header OCamlStyle GPLv2plus;
10754 let g = Guestfs.create () in
10758 String.concat " " (
10761 | CallString s -> "\"" ^ s ^ "\""
10762 | CallOptString None -> "None"
10763 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10764 | CallStringList xs ->
10765 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10766 | CallInt i when i >= 0 -> string_of_int i
10767 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10768 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10769 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10770 | CallBool b -> string_of_bool b
10775 generate_lang_bindtests (
10776 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10779 pr "print_endline \"EOF\"\n"
10781 and generate_perl_bindtests () =
10782 pr "#!/usr/bin/perl -w\n";
10783 generate_header HashStyle GPLv2plus;
10790 my $g = Sys::Guestfs->new ();
10794 String.concat ", " (
10797 | CallString s -> "\"" ^ s ^ "\""
10798 | CallOptString None -> "undef"
10799 | CallOptString (Some s) -> sprintf "\"%s\"" s
10800 | CallStringList xs ->
10801 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10802 | CallInt i -> string_of_int i
10803 | CallInt64 i -> Int64.to_string i
10804 | CallBool b -> if b then "1" else "0"
10809 generate_lang_bindtests (
10810 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10813 pr "print \"EOF\\n\"\n"
10815 and generate_python_bindtests () =
10816 generate_header HashStyle GPLv2plus;
10821 g = guestfs.GuestFS ()
10825 String.concat ", " (
10828 | CallString s -> "\"" ^ s ^ "\""
10829 | CallOptString None -> "None"
10830 | CallOptString (Some s) -> sprintf "\"%s\"" s
10831 | CallStringList xs ->
10832 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10833 | CallInt i -> string_of_int i
10834 | CallInt64 i -> Int64.to_string i
10835 | CallBool b -> if b then "1" else "0"
10840 generate_lang_bindtests (
10841 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10844 pr "print \"EOF\"\n"
10846 and generate_ruby_bindtests () =
10847 generate_header HashStyle GPLv2plus;
10852 g = Guestfs::create()
10856 String.concat ", " (
10859 | CallString s -> "\"" ^ s ^ "\""
10860 | CallOptString None -> "nil"
10861 | CallOptString (Some s) -> sprintf "\"%s\"" s
10862 | CallStringList xs ->
10863 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10864 | CallInt i -> string_of_int i
10865 | CallInt64 i -> Int64.to_string i
10866 | CallBool b -> string_of_bool b
10871 generate_lang_bindtests (
10872 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10875 pr "print \"EOF\\n\"\n"
10877 and generate_java_bindtests () =
10878 generate_header CStyle GPLv2plus;
10881 import com.redhat.et.libguestfs.*;
10883 public class Bindtests {
10884 public static void main (String[] argv)
10887 GuestFS g = new GuestFS ();
10891 String.concat ", " (
10894 | CallString s -> "\"" ^ s ^ "\""
10895 | CallOptString None -> "null"
10896 | CallOptString (Some s) -> sprintf "\"%s\"" s
10897 | CallStringList xs ->
10899 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10900 | CallInt i -> string_of_int i
10901 | CallInt64 i -> Int64.to_string i
10902 | CallBool b -> string_of_bool b
10907 generate_lang_bindtests (
10908 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10912 System.out.println (\"EOF\");
10914 catch (Exception exn) {
10915 System.err.println (exn);
10922 and generate_haskell_bindtests () =
10923 generate_header HaskellStyle GPLv2plus;
10926 module Bindtests where
10927 import qualified Guestfs
10930 g <- Guestfs.create
10934 String.concat " " (
10937 | CallString s -> "\"" ^ s ^ "\""
10938 | CallOptString None -> "Nothing"
10939 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10940 | CallStringList xs ->
10941 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10942 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10943 | CallInt i -> string_of_int i
10944 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10945 | CallInt64 i -> Int64.to_string i
10946 | CallBool true -> "True"
10947 | CallBool false -> "False"
10952 generate_lang_bindtests (
10953 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10956 pr " putStrLn \"EOF\"\n"
10958 (* Language-independent bindings tests - we do it this way to
10959 * ensure there is parity in testing bindings across all languages.
10961 and generate_lang_bindtests call =
10962 call "test0" [CallString "abc"; CallOptString (Some "def");
10963 CallStringList []; CallBool false;
10964 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10965 call "test0" [CallString "abc"; CallOptString None;
10966 CallStringList []; CallBool false;
10967 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10968 call "test0" [CallString ""; CallOptString (Some "def");
10969 CallStringList []; CallBool false;
10970 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10971 call "test0" [CallString ""; CallOptString (Some "");
10972 CallStringList []; CallBool false;
10973 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10974 call "test0" [CallString "abc"; CallOptString (Some "def");
10975 CallStringList ["1"]; CallBool false;
10976 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10977 call "test0" [CallString "abc"; CallOptString (Some "def");
10978 CallStringList ["1"; "2"]; CallBool false;
10979 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10980 call "test0" [CallString "abc"; CallOptString (Some "def");
10981 CallStringList ["1"]; CallBool true;
10982 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10983 call "test0" [CallString "abc"; CallOptString (Some "def");
10984 CallStringList ["1"]; CallBool false;
10985 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10986 call "test0" [CallString "abc"; CallOptString (Some "def");
10987 CallStringList ["1"]; CallBool false;
10988 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10989 call "test0" [CallString "abc"; CallOptString (Some "def");
10990 CallStringList ["1"]; CallBool false;
10991 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10992 call "test0" [CallString "abc"; CallOptString (Some "def");
10993 CallStringList ["1"]; CallBool false;
10994 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10995 call "test0" [CallString "abc"; CallOptString (Some "def");
10996 CallStringList ["1"]; CallBool false;
10997 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10998 call "test0" [CallString "abc"; CallOptString (Some "def");
10999 CallStringList ["1"]; CallBool false;
11000 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11002 (* XXX Add here tests of the return and error functions. *)
11004 (* Code to generator bindings for virt-inspector. Currently only
11005 * implemented for OCaml code (for virt-p2v 2.0).
11007 let rng_input = "inspector/virt-inspector.rng"
11009 (* Read the input file and parse it into internal structures. This is
11010 * by no means a complete RELAX NG parser, but is just enough to be
11011 * able to parse the specific input file.
11014 | Element of string * rng list (* <element name=name/> *)
11015 | Attribute of string * rng list (* <attribute name=name/> *)
11016 | Interleave of rng list (* <interleave/> *)
11017 | ZeroOrMore of rng (* <zeroOrMore/> *)
11018 | OneOrMore of rng (* <oneOrMore/> *)
11019 | Optional of rng (* <optional/> *)
11020 | Choice of string list (* <choice><value/>*</choice> *)
11021 | Value of string (* <value>str</value> *)
11022 | Text (* <text/> *)
11024 let rec string_of_rng = function
11025 | Element (name, xs) ->
11026 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11027 | Attribute (name, xs) ->
11028 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11029 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11030 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11031 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11032 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11033 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11034 | Value value -> "Value \"" ^ value ^ "\""
11037 and string_of_rng_list xs =
11038 String.concat ", " (List.map string_of_rng xs)
11040 let rec parse_rng ?defines context = function
11042 | Xml.Element ("element", ["name", name], children) :: rest ->
11043 Element (name, parse_rng ?defines context children)
11044 :: parse_rng ?defines context rest
11045 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11046 Attribute (name, parse_rng ?defines context children)
11047 :: parse_rng ?defines context rest
11048 | Xml.Element ("interleave", [], children) :: rest ->
11049 Interleave (parse_rng ?defines context children)
11050 :: parse_rng ?defines context rest
11051 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11052 let rng = parse_rng ?defines context [child] in
11054 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11056 failwithf "%s: <zeroOrMore> contains more than one child element"
11059 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11060 let rng = parse_rng ?defines context [child] in
11062 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11064 failwithf "%s: <oneOrMore> contains more than one child element"
11067 | Xml.Element ("optional", [], [child]) :: rest ->
11068 let rng = parse_rng ?defines context [child] in
11070 | [child] -> Optional child :: parse_rng ?defines context rest
11072 failwithf "%s: <optional> contains more than one child element"
11075 | Xml.Element ("choice", [], children) :: rest ->
11076 let values = List.map (
11077 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11079 failwithf "%s: can't handle anything except <value> in <choice>"
11083 :: parse_rng ?defines context rest
11084 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11085 Value value :: parse_rng ?defines context rest
11086 | Xml.Element ("text", [], []) :: rest ->
11087 Text :: parse_rng ?defines context rest
11088 | Xml.Element ("ref", ["name", name], []) :: rest ->
11089 (* Look up the reference. Because of limitations in this parser,
11090 * we can't handle arbitrarily nested <ref> yet. You can only
11091 * use <ref> from inside <start>.
11093 (match defines with
11095 failwithf "%s: contains <ref>, but no refs are defined yet" context
11097 let rng = StringMap.find name map in
11098 rng @ parse_rng ?defines context rest
11101 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11104 let xml = Xml.parse_file rng_input in
11106 | Xml.Element ("grammar", _,
11107 Xml.Element ("start", _, gram) :: defines) ->
11108 (* The <define/> elements are referenced in the <start> section,
11109 * so build a map of those first.
11111 let defines = List.fold_left (
11113 function Xml.Element ("define", ["name", name], defn) ->
11114 StringMap.add name defn map
11116 failwithf "%s: expected <define name=name/>" rng_input
11117 ) StringMap.empty defines in
11118 let defines = StringMap.mapi parse_rng defines in
11120 (* Parse the <start> clause, passing the defines. *)
11121 parse_rng ~defines "<start>" gram
11123 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11126 let name_of_field = function
11127 | Element (name, _) | Attribute (name, _)
11128 | ZeroOrMore (Element (name, _))
11129 | OneOrMore (Element (name, _))
11130 | Optional (Element (name, _)) -> name
11131 | Optional (Attribute (name, _)) -> name
11132 | Text -> (* an unnamed field in an element *)
11135 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11137 (* At the moment this function only generates OCaml types. However we
11138 * should parameterize it later so it can generate types/structs in a
11139 * variety of languages.
11141 let generate_types xs =
11142 (* A simple type is one that can be printed out directly, eg.
11143 * "string option". A complex type is one which has a name and has
11144 * to be defined via another toplevel definition, eg. a struct.
11146 * generate_type generates code for either simple or complex types.
11147 * In the simple case, it returns the string ("string option"). In
11148 * the complex case, it returns the name ("mountpoint"). In the
11149 * complex case it has to print out the definition before returning,
11150 * so it should only be called when we are at the beginning of a
11151 * new line (BOL context).
11153 let rec generate_type = function
11154 | Text -> (* string *)
11156 | Choice values -> (* [`val1|`val2|...] *)
11157 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11158 | ZeroOrMore rng -> (* <rng> list *)
11159 let t, is_simple = generate_type rng in
11160 t ^ " list (* 0 or more *)", is_simple
11161 | OneOrMore rng -> (* <rng> list *)
11162 let t, is_simple = generate_type rng in
11163 t ^ " list (* 1 or more *)", is_simple
11164 (* virt-inspector hack: bool *)
11165 | Optional (Attribute (name, [Value "1"])) ->
11167 | Optional rng -> (* <rng> list *)
11168 let t, is_simple = generate_type rng in
11169 t ^ " option", is_simple
11170 (* type name = { fields ... } *)
11171 | Element (name, fields) when is_attrs_interleave fields ->
11172 generate_type_struct name (get_attrs_interleave fields)
11173 | Element (name, [field]) (* type name = field *)
11174 | Attribute (name, [field]) ->
11175 let t, is_simple = generate_type field in
11176 if is_simple then (t, true)
11178 pr "type %s = %s\n" name t;
11181 | Element (name, fields) -> (* type name = { fields ... } *)
11182 generate_type_struct name fields
11184 failwithf "generate_type failed at: %s" (string_of_rng rng)
11186 and is_attrs_interleave = function
11187 | [Interleave _] -> true
11188 | Attribute _ :: fields -> is_attrs_interleave fields
11189 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11192 and get_attrs_interleave = function
11193 | [Interleave fields] -> fields
11194 | ((Attribute _) as field) :: fields
11195 | ((Optional (Attribute _)) as field) :: fields ->
11196 field :: get_attrs_interleave fields
11197 | _ -> assert false
11199 and generate_types xs =
11200 List.iter (fun x -> ignore (generate_type x)) xs
11202 and generate_type_struct name fields =
11203 (* Calculate the types of the fields first. We have to do this
11204 * before printing anything so we are still in BOL context.
11206 let types = List.map fst (List.map generate_type fields) in
11208 (* Special case of a struct containing just a string and another
11209 * field. Turn it into an assoc list.
11212 | ["string"; other] ->
11213 let fname1, fname2 =
11215 | [f1; f2] -> name_of_field f1, name_of_field f2
11216 | _ -> assert false in
11217 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11221 pr "type %s = {\n" name;
11223 fun (field, ftype) ->
11224 let fname = name_of_field field in
11225 pr " %s_%s : %s;\n" name fname ftype
11226 ) (List.combine fields types);
11228 (* Return the name of this type, and
11229 * false because it's not a simple type.
11236 let generate_parsers xs =
11237 (* As for generate_type above, generate_parser makes a parser for
11238 * some type, and returns the name of the parser it has generated.
11239 * Because it (may) need to print something, it should always be
11240 * called in BOL context.
11242 let rec generate_parser = function
11243 | Text -> (* string *)
11244 "string_child_or_empty"
11245 | Choice values -> (* [`val1|`val2|...] *)
11246 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11248 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11249 | ZeroOrMore rng -> (* <rng> list *)
11250 let pa = generate_parser rng in
11251 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11252 | OneOrMore rng -> (* <rng> list *)
11253 let pa = generate_parser rng in
11254 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11255 (* virt-inspector hack: bool *)
11256 | Optional (Attribute (name, [Value "1"])) ->
11257 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11258 | Optional rng -> (* <rng> list *)
11259 let pa = generate_parser rng in
11260 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11261 (* type name = { fields ... } *)
11262 | Element (name, fields) when is_attrs_interleave fields ->
11263 generate_parser_struct name (get_attrs_interleave fields)
11264 | Element (name, [field]) -> (* type name = field *)
11265 let pa = generate_parser field in
11266 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11267 pr "let %s =\n" parser_name;
11269 pr "let parse_%s = %s\n" name parser_name;
11271 | Attribute (name, [field]) ->
11272 let pa = generate_parser field in
11273 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11274 pr "let %s =\n" parser_name;
11276 pr "let parse_%s = %s\n" name parser_name;
11278 | Element (name, fields) -> (* type name = { fields ... } *)
11279 generate_parser_struct name ([], fields)
11281 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11283 and is_attrs_interleave = function
11284 | [Interleave _] -> true
11285 | Attribute _ :: fields -> is_attrs_interleave fields
11286 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11289 and get_attrs_interleave = function
11290 | [Interleave fields] -> [], fields
11291 | ((Attribute _) as field) :: fields
11292 | ((Optional (Attribute _)) as field) :: fields ->
11293 let attrs, interleaves = get_attrs_interleave fields in
11294 (field :: attrs), interleaves
11295 | _ -> assert false
11297 and generate_parsers xs =
11298 List.iter (fun x -> ignore (generate_parser x)) xs
11300 and generate_parser_struct name (attrs, interleaves) =
11301 (* Generate parsers for the fields first. We have to do this
11302 * before printing anything so we are still in BOL context.
11304 let fields = attrs @ interleaves in
11305 let pas = List.map generate_parser fields in
11307 (* Generate an intermediate tuple from all the fields first.
11308 * If the type is just a string + another field, then we will
11309 * return this directly, otherwise it is turned into a record.
11311 * RELAX NG note: This code treats <interleave> and plain lists of
11312 * fields the same. In other words, it doesn't bother enforcing
11313 * any ordering of fields in the XML.
11315 pr "let parse_%s x =\n" name;
11316 pr " let t = (\n ";
11317 let comma = ref false in
11320 if !comma then pr ",\n ";
11323 | Optional (Attribute (fname, [field])), pa ->
11325 | Optional (Element (fname, [field])), pa ->
11326 pr "%s (optional_child %S x)" pa fname
11327 | Attribute (fname, [Text]), _ ->
11328 pr "attribute %S x" fname
11329 | (ZeroOrMore _ | OneOrMore _), pa ->
11334 let fname = name_of_field field in
11335 pr "%s (child %S x)" pa fname
11336 ) (List.combine fields pas);
11340 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11344 pr " (Obj.magic t : %s)\n" name
11348 | (Optional (Attribute (fname, [field])), pa) ->
11349 pr " %s_%s =\n" name fname;
11351 | (Optional (Element (fname, [field])), pa) ->
11352 pr " %s_%s =\n" name fname;
11353 pr " (let x = optional_child %S x in\n" fname;
11356 let fname = name_of_field field in
11357 pr " %s_%s =\n" name fname;
11358 pr " (let x = child %S x in\n" fname;
11360 ) (List.combine fields pas);
11364 sprintf "parse_%s" name
11367 generate_parsers xs
11369 (* Generate ocaml/guestfs_inspector.mli. *)
11370 let generate_ocaml_inspector_mli () =
11371 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11374 (** This is an OCaml language binding to the external [virt-inspector]
11377 For more information, please read the man page [virt-inspector(1)].
11382 generate_types grammar;
11383 pr "(** The nested information returned from the {!inspect} function. *)\n";
11387 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11388 (** To inspect a libvirt domain called [name], pass a singleton
11389 list: [inspect [name]]. When using libvirt only, you may
11390 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11392 To inspect a disk image or images, pass a list of the filenames
11393 of the disk images: [inspect filenames]
11395 This function inspects the given guest or disk images and
11396 returns a list of operating system(s) found and a large amount
11397 of information about them. In the vast majority of cases,
11398 a virtual machine only contains a single operating system.
11400 If the optional [~xml] parameter is given, then this function
11401 skips running the external virt-inspector program and just
11402 parses the given XML directly (which is expected to be XML
11403 produced from a previous run of virt-inspector). The list of
11404 names and connect URI are ignored in this case.
11406 This function can throw a wide variety of exceptions, for example
11407 if the external virt-inspector program cannot be found, or if
11408 it doesn't generate valid XML.
11412 (* Generate ocaml/guestfs_inspector.ml. *)
11413 let generate_ocaml_inspector_ml () =
11414 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11419 generate_types grammar;
11423 (* Misc functions which are used by the parser code below. *)
11424 let first_child = function
11425 | Xml.Element (_, _, c::_) -> c
11426 | Xml.Element (name, _, []) ->
11427 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11428 | Xml.PCData str ->
11429 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11431 let string_child_or_empty = function
11432 | Xml.Element (_, _, [Xml.PCData s]) -> s
11433 | Xml.Element (_, _, []) -> \"\"
11434 | Xml.Element (x, _, _) ->
11435 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11437 | Xml.PCData str ->
11438 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11440 let optional_child name xml =
11441 let children = Xml.children xml in
11443 Some (List.find (function
11444 | Xml.Element (n, _, _) when n = name -> true
11445 | _ -> false) children)
11449 let child name xml =
11450 match optional_child name xml with
11453 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11455 let attribute name xml =
11456 try Xml.attrib xml name
11457 with Xml.No_attribute _ ->
11458 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11462 generate_parsers grammar;
11466 (* Run external virt-inspector, then use parser to parse the XML. *)
11467 let inspect ?connect ?xml names =
11471 if names = [] then invalid_arg \"inspect: no names given\";
11472 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11473 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11475 let cmd = List.map Filename.quote cmd in
11476 let cmd = String.concat \" \" cmd in
11477 let chan = open_process_in cmd in
11478 let xml = Xml.parse_in chan in
11479 (match close_process_in chan with
11481 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11482 | WSIGNALED i | WSTOPPED i ->
11483 failwith (\"external virt-inspector command died or stopped on sig \" ^
11488 Xml.parse_string doc in
11489 parse_operatingsystems xml
11492 (* This is used to generate the src/MAX_PROC_NR file which
11493 * contains the maximum procedure number, a surrogate for the
11494 * ABI version number. See src/Makefile.am for the details.
11496 and generate_max_proc_nr () =
11497 let proc_nrs = List.map (
11498 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11499 ) daemon_functions in
11501 let max_proc_nr = List.fold_left max 0 proc_nrs in
11503 pr "%d\n" max_proc_nr
11505 let output_to filename k =
11506 let filename_new = filename ^ ".new" in
11507 chan := open_out filename_new;
11510 chan := Pervasives.stdout;
11512 (* Is the new file different from the current file? *)
11513 if Sys.file_exists filename && files_equal filename filename_new then
11514 unlink filename_new (* same, so skip it *)
11516 (* different, overwrite old one *)
11517 (try chmod filename 0o644 with Unix_error _ -> ());
11518 rename filename_new filename;
11519 chmod filename 0o444;
11520 printf "written %s\n%!" filename;
11523 let perror msg = function
11524 | Unix_error (err, _, _) ->
11525 eprintf "%s: %s\n" msg (error_message err)
11527 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11529 (* Main program. *)
11532 try openfile "HACKING" [O_RDWR] 0
11534 | Unix_error (ENOENT, _, _) ->
11536 You are probably running this from the wrong directory.
11537 Run it from the top source directory using the command
11542 perror "open: HACKING" exn;
11545 (* Acquire a lock so parallel builds won't try to run the generator
11546 * twice at the same time. Subsequent builds will wait for the first
11547 * one to finish. Note the lock is released implicitly when the
11550 (try lockf lock_fd F_LOCK 1
11552 perror "lock: HACKING" exn;
11555 check_functions ();
11557 output_to "src/guestfs_protocol.x" generate_xdr;
11558 output_to "src/guestfs-structs.h" generate_structs_h;
11559 output_to "src/guestfs-actions.h" generate_actions_h;
11560 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11561 output_to "src/guestfs-actions.c" generate_client_actions;
11562 output_to "src/guestfs-bindtests.c" generate_bindtests;
11563 output_to "src/guestfs-structs.pod" generate_structs_pod;
11564 output_to "src/guestfs-actions.pod" generate_actions_pod;
11565 output_to "src/guestfs-availability.pod" generate_availability_pod;
11566 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11567 output_to "src/libguestfs.syms" generate_linker_script;
11568 output_to "daemon/actions.h" generate_daemon_actions_h;
11569 output_to "daemon/stubs.c" generate_daemon_actions;
11570 output_to "daemon/names.c" generate_daemon_names;
11571 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11572 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11573 output_to "capitests/tests.c" generate_tests;
11574 output_to "fish/cmds.c" generate_fish_cmds;
11575 output_to "fish/completion.c" generate_fish_completion;
11576 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11577 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11578 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11579 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11580 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11581 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11582 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11583 output_to "perl/Guestfs.xs" generate_perl_xs;
11584 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11585 output_to "perl/bindtests.pl" generate_perl_bindtests;
11586 output_to "python/guestfs-py.c" generate_python_c;
11587 output_to "python/guestfs.py" generate_python_py;
11588 output_to "python/bindtests.py" generate_python_bindtests;
11589 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11590 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11591 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11595 let cols = cols_of_struct typ in
11596 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11597 output_to filename (generate_java_struct jtyp cols);
11600 output_to "java/Makefile.inc" generate_java_makefile_inc;
11601 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11602 output_to "java/Bindtests.java" generate_java_bindtests;
11603 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11604 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11605 output_to "csharp/Libguestfs.cs" generate_csharp;
11607 (* Always generate this file last, and unconditionally. It's used
11608 * by the Makefile to know when we must re-run the generator.
11610 let chan = open_out "src/stamp-generator" in
11611 fprintf chan "1\n";
11614 printf "generated %d lines of code\n" !lines