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. Distro backports makes this unreliable. Use
811 C<guestfs_available> instead.");
813 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814 [InitNone, Always, TestOutputTrue (
815 [["set_selinux"; "true"];
817 "set SELinux enabled or disabled at appliance boot",
819 This sets the selinux flag that is passed to the appliance
820 at boot time. The default is C<selinux=0> (disabled).
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
828 ("get_selinux", (RBool "selinux", []), -1, [],
830 "get SELinux enabled flag",
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
838 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839 [InitNone, Always, TestOutputFalse (
840 [["set_trace"; "false"];
842 "enable or disable command traces",
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish. In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858 ("get_trace", (RBool "trace", []), -1, [],
860 "get command trace enabled flag",
862 Return the command trace flag.");
864 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865 [InitNone, Always, TestOutputFalse (
866 [["set_direct"; "false"];
868 "enable or disable direct appliance mode",
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
878 You probably don't want to use this unless you know what you
881 The default is disabled.");
883 ("get_direct", (RBool "direct", []), -1, [],
885 "get direct appliance mode flag",
887 Return the direct appliance mode flag.");
889 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890 [InitNone, Always, TestOutputTrue (
891 [["set_recovery_proc"; "true"];
892 ["get_recovery_proc"]])],
893 "enable or disable the recovery process",
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process. The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself). In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
909 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911 "get recovery process enabled flag",
913 Return the recovery process enabled flag.");
915 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917 "add a drive specifying the QEMU block emulation to use",
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
922 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924 "add a drive read-only specifying the QEMU block emulation to use",
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
931 (* daemon_functions are any functions which cause some action
932 * to take place in the daemon.
935 let daemon_functions = [
936 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937 [InitEmpty, Always, TestOutput (
938 [["part_disk"; "/dev/sda"; "mbr"];
939 ["mkfs"; "ext2"; "/dev/sda1"];
940 ["mount"; "/dev/sda1"; "/"];
941 ["write_file"; "/new"; "new file contents"; "0"];
942 ["cat"; "/new"]], "new file contents")],
943 "mount a guest disk at a position in the filesystem",
945 Mount a guest disk at a position in the filesystem. Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest. If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
951 The rules are the same as for L<mount(2)>: A filesystem must
952 first be mounted on C</> before others can be mounted. Other
953 filesystems can only be mounted on directories which already
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly. This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability. Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
969 ("sync", (RErr, []), 2, [],
970 [ InitEmpty, Always, TestRun [["sync"]]],
971 "sync disks, writes are flushed through to the disk image",
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
979 ("touch", (RErr, [Pathname "path"]), 3, [],
980 [InitBasicFS, Always, TestOutputTrue (
982 ["exists"; "/new"]])],
983 "update file timestamps or create a new file",
985 Touch acts like the L<touch(1)> command. It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
989 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990 [InitISOFS, Always, TestOutput (
991 [["cat"; "/known-2"]], "abcdef\n")],
992 "list the contents of a file",
994 Return the contents of the file named C<path>.
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string). For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1001 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002 [], (* XXX Tricky to test because it depends on the exact format
1003 * of the 'ls -l' command, which changes between F10 and F11.
1005 "list the files in a directory (long format)",
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1010 This command is mostly useful for interactive sessions. It
1011 is I<not> intended that you try to parse the output string.");
1013 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014 [InitBasicFS, Always, TestOutputList (
1016 ["touch"; "/newer"];
1017 ["touch"; "/newest"];
1018 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019 "list the files in a directory",
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd). The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1025 This command is mostly useful for interactive sessions. Programs
1026 should probably use C<guestfs_readdir> instead.");
1028 ("list_devices", (RStringList "devices", []), 7, [],
1029 [InitEmpty, Always, TestOutputListOfDevices (
1030 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031 "list the block devices",
1033 List all the block devices.
1035 The full block device names are returned, eg. C</dev/sda>");
1037 ("list_partitions", (RStringList "partitions", []), 8, [],
1038 [InitBasicFS, Always, TestOutputListOfDevices (
1039 [["list_partitions"]], ["/dev/sda1"]);
1040 InitEmpty, Always, TestOutputListOfDevices (
1041 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043 "list the partitions",
1045 List all the partitions detected on all block devices.
1047 The full partition device names are returned, eg. C</dev/sda1>
1049 This does not return logical volumes. For that you will need to
1050 call C<guestfs_lvs>.");
1052 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054 [["pvs"]], ["/dev/sda1"]);
1055 InitEmpty, Always, TestOutputListOfDevices (
1056 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057 ["pvcreate"; "/dev/sda1"];
1058 ["pvcreate"; "/dev/sda2"];
1059 ["pvcreate"; "/dev/sda3"];
1060 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061 "list the LVM physical volumes (PVs)",
1063 List all the physical volumes detected. This is the equivalent
1064 of the L<pvs(8)> command.
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1069 See also C<guestfs_pvs_full>.");
1071 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072 [InitBasicFSonLVM, Always, TestOutputList (
1074 InitEmpty, Always, TestOutputList (
1075 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076 ["pvcreate"; "/dev/sda1"];
1077 ["pvcreate"; "/dev/sda2"];
1078 ["pvcreate"; "/dev/sda3"];
1079 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080 ["vgcreate"; "VG2"; "/dev/sda3"];
1081 ["vgs"]], ["VG1"; "VG2"])],
1082 "list the LVM volume groups (VGs)",
1084 List all the volumes groups detected. This is the equivalent
1085 of the L<vgs(8)> command.
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1090 See also C<guestfs_vgs_full>.");
1092 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093 [InitBasicFSonLVM, Always, TestOutputList (
1094 [["lvs"]], ["/dev/VG/LV"]);
1095 InitEmpty, Always, TestOutputList (
1096 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097 ["pvcreate"; "/dev/sda1"];
1098 ["pvcreate"; "/dev/sda2"];
1099 ["pvcreate"; "/dev/sda3"];
1100 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101 ["vgcreate"; "VG2"; "/dev/sda3"];
1102 ["lvcreate"; "LV1"; "VG1"; "50"];
1103 ["lvcreate"; "LV2"; "VG1"; "50"];
1104 ["lvcreate"; "LV3"; "VG2"; "50"];
1105 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106 "list the LVM logical volumes (LVs)",
1108 List all the logical volumes detected. This is the equivalent
1109 of the L<lvs(8)> command.
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1114 See also C<guestfs_lvs_full>.");
1116 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117 [], (* XXX how to test? *)
1118 "list the LVM physical volumes (PVs)",
1120 List all the physical volumes detected. This is the equivalent
1121 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1123 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124 [], (* XXX how to test? *)
1125 "list the LVM volume groups (VGs)",
1127 List all the volumes groups detected. This is the equivalent
1128 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1130 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131 [], (* XXX how to test? *)
1132 "list the LVM logical volumes (LVs)",
1134 List all the logical volumes detected. This is the equivalent
1135 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1137 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138 [InitISOFS, Always, TestOutputList (
1139 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140 InitISOFS, Always, TestOutputList (
1141 [["read_lines"; "/empty"]], [])],
1142 "read file as lines",
1144 Return the contents of the file named C<path>.
1146 The file contents are returned as a list of lines. Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line). For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1154 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155 [], (* XXX Augeas code needs tests. *)
1156 "create a new Augeas handle",
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1162 You must call this before using any other C<guestfs_aug_*>
1165 C<root> is the filesystem root. C<root> must not be NULL,
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1174 =item C<AUG_SAVE_BACKUP> = 1
1176 Keep the original file with a C<.augsave> extension.
1178 =item C<AUG_SAVE_NEWFILE> = 2
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1183 =item C<AUG_TYPE_CHECK> = 4
1185 Typecheck lenses (can be expensive).
1187 =item C<AUG_NO_STDINC> = 8
1189 Do not use standard load path for modules.
1191 =item C<AUG_SAVE_NOOP> = 16
1193 Make save a no-op, just record what would have been changed.
1195 =item C<AUG_NO_LOAD> = 32
1197 Do not load the tree in C<guestfs_aug_init>.
1201 To close the handle, you can call C<guestfs_aug_close>.
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1205 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206 [], (* XXX Augeas code needs tests. *)
1207 "close the current Augeas handle",
1209 Close the current Augeas handle and free up any resources
1210 used by it. After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1214 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "define an Augeas variable",
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226 [], (* XXX Augeas code needs tests. *)
1227 "define an Augeas node",
1229 Defines a variable C<name> whose value is the result of
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1240 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241 [], (* XXX Augeas code needs tests. *)
1242 "look up the value of an Augeas path",
1244 Look up the value associated with C<path>. If C<path>
1245 matches exactly one node, the C<value> is returned.");
1247 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248 [], (* XXX Augeas code needs tests. *)
1249 "set Augeas path to value",
1251 Set the value associated with C<path> to C<value>.");
1253 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254 [], (* XXX Augeas code needs tests. *)
1255 "insert a sibling Augeas node",
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1265 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266 [], (* XXX Augeas code needs tests. *)
1267 "remove an Augeas path",
1269 Remove C<path> and all of its children.
1271 On success this returns the number of entries which were removed.");
1273 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274 [], (* XXX Augeas code needs tests. *)
1277 Move the node C<src> to C<dest>. C<src> must match exactly
1278 one node. C<dest> is overwritten if it exists.");
1280 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1282 "return Augeas nodes which match augpath",
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1288 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289 [], (* XXX Augeas code needs tests. *)
1290 "write all pending Augeas changes to disk",
1292 This writes all pending changes to disk.
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1297 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298 [], (* XXX Augeas code needs tests. *)
1299 "load files into the tree",
1301 Load files into the tree.
1303 See C<aug_load> in the Augeas documentation for the full gory
1306 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307 [], (* XXX Augeas code needs tests. *)
1308 "list Augeas nodes under augpath",
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1313 ("rm", (RErr, [Pathname "path"]), 29, [],
1314 [InitBasicFS, Always, TestRun
1317 InitBasicFS, Always, TestLastFail
1319 InitBasicFS, Always, TestLastFail
1324 Remove the single file C<path>.");
1326 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327 [InitBasicFS, Always, TestRun
1330 InitBasicFS, Always, TestLastFail
1331 [["rmdir"; "/new"]];
1332 InitBasicFS, Always, TestLastFail
1334 ["rmdir"; "/new"]]],
1335 "remove a directory",
1337 Remove the single directory C<path>.");
1339 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340 [InitBasicFS, Always, TestOutputFalse
1342 ["mkdir"; "/new/foo"];
1343 ["touch"; "/new/foo/bar"];
1345 ["exists"; "/new"]]],
1346 "remove a file or directory recursively",
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory. This is like the C<rm -rf> shell
1352 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353 [InitBasicFS, Always, TestOutputTrue
1355 ["is_dir"; "/new"]];
1356 InitBasicFS, Always, TestLastFail
1357 [["mkdir"; "/new/foo/bar"]]],
1358 "create a directory",
1360 Create a directory named C<path>.");
1362 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363 [InitBasicFS, Always, TestOutputTrue
1364 [["mkdir_p"; "/new/foo/bar"];
1365 ["is_dir"; "/new/foo/bar"]];
1366 InitBasicFS, Always, TestOutputTrue
1367 [["mkdir_p"; "/new/foo/bar"];
1368 ["is_dir"; "/new/foo"]];
1369 InitBasicFS, Always, TestOutputTrue
1370 [["mkdir_p"; "/new/foo/bar"];
1371 ["is_dir"; "/new"]];
1372 (* Regression tests for RHBZ#503133: *)
1373 InitBasicFS, Always, TestRun
1375 ["mkdir_p"; "/new"]];
1376 InitBasicFS, Always, TestLastFail
1378 ["mkdir_p"; "/new"]]],
1379 "create a directory and parents",
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary. This is like the C<mkdir -p> shell command.");
1384 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385 [], (* XXX Need stat command to test *)
1388 Change the mode (permissions) of C<path> to C<mode>. Only
1389 numeric modes are supported.
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1395 The mode actually set is affected by the umask.");
1397 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398 [], (* XXX Need stat command to test *)
1399 "change file owner and group",
1401 Change the file owner to C<owner> and group to C<group>.
1403 Only numeric uid and gid are supported. If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1407 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408 [InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/empty"]]);
1410 InitISOFS, Always, TestOutputTrue (
1411 [["exists"; "/directory"]])],
1412 "test if file or directory exists",
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1419 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420 [InitISOFS, Always, TestOutputTrue (
1421 [["is_file"; "/known-1"]]);
1422 InitISOFS, Always, TestOutputFalse (
1423 [["is_file"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name. Note that it returns false for
1428 other objects like directories.
1430 See also C<guestfs_stat>.");
1432 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433 [InitISOFS, Always, TestOutputFalse (
1434 [["is_dir"; "/known-3"]]);
1435 InitISOFS, Always, TestOutputTrue (
1436 [["is_dir"; "/directory"]])],
1437 "test if file exists",
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name. Note that it returns false for
1441 other objects like files.
1443 See also C<guestfs_stat>.");
1445 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputListOfDevices (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452 "create an LVM physical volume",
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1458 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459 [InitEmpty, Always, TestOutputList (
1460 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461 ["pvcreate"; "/dev/sda1"];
1462 ["pvcreate"; "/dev/sda2"];
1463 ["pvcreate"; "/dev/sda3"];
1464 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465 ["vgcreate"; "VG2"; "/dev/sda3"];
1466 ["vgs"]], ["VG1"; "VG2"])],
1467 "create an LVM volume group",
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1472 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473 [InitEmpty, Always, TestOutputList (
1474 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475 ["pvcreate"; "/dev/sda1"];
1476 ["pvcreate"; "/dev/sda2"];
1477 ["pvcreate"; "/dev/sda3"];
1478 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479 ["vgcreate"; "VG2"; "/dev/sda3"];
1480 ["lvcreate"; "LV1"; "VG1"; "50"];
1481 ["lvcreate"; "LV2"; "VG1"; "50"];
1482 ["lvcreate"; "LV3"; "VG2"; "50"];
1483 ["lvcreate"; "LV4"; "VG2"; "50"];
1484 ["lvcreate"; "LV5"; "VG2"; "50"];
1486 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488 "create an LVM logical volume",
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1493 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494 [InitEmpty, Always, TestOutput (
1495 [["part_disk"; "/dev/sda"; "mbr"];
1496 ["mkfs"; "ext2"; "/dev/sda1"];
1497 ["mount_options"; ""; "/dev/sda1"; "/"];
1498 ["write_file"; "/new"; "new file contents"; "0"];
1499 ["cat"; "/new"]], "new file contents")],
1500 "make a filesystem",
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume). The filesystem type is C<fstype>, for
1506 ("sfdisk", (RErr, [Device "device";
1507 Int "cyls"; Int "heads"; Int "sectors";
1508 StringList "lines"]), 43, [DangerWillRobinson],
1510 "create partitions on a block device",
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1515 C<device> should be a block device, for example C</dev/sda>.
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted. Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1525 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1526 information refer to the L<sfdisk(8)> manpage.
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1535 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536 [InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "new file contents"; "0"];
1538 ["cat"; "/new"]], "new file contents");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541 ["cat"; "/new"]], "\nnew file contents\n");
1542 InitBasicFS, Always, TestOutput (
1543 [["write_file"; "/new"; "\n\n"; "0"];
1544 ["cat"; "/new"]], "\n\n");
1545 InitBasicFS, Always, TestOutput (
1546 [["write_file"; "/new"; ""; "0"];
1547 ["cat"; "/new"]], "");
1548 InitBasicFS, Always, TestOutput (
1549 [["write_file"; "/new"; "\n\n\n"; "0"];
1550 ["cat"; "/new"]], "\n\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["write_file"; "/new"; "\n"; "0"];
1553 ["cat"; "/new"]], "\n")],
1556 This call creates a file called C<path>. The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version. In the meantime
1567 use C<guestfs_upload>.");
1569 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570 [InitEmpty, Always, TestOutputListOfDevices (
1571 [["part_disk"; "/dev/sda"; "mbr"];
1572 ["mkfs"; "ext2"; "/dev/sda1"];
1573 ["mount_options"; ""; "/dev/sda1"; "/"];
1574 ["mounts"]], ["/dev/sda1"]);
1575 InitEmpty, Always, TestOutputList (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 "unmount a filesystem",
1583 This unmounts the given filesystem. The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1587 ("mounts", (RStringList "devices", []), 46, [],
1588 [InitBasicFS, Always, TestOutputListOfDevices (
1589 [["mounts"]], ["/dev/sda1"])],
1590 "show mounted filesystems",
1592 This returns the list of currently mounted filesystems. It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1595 Some internal mounts are not shown.
1597 See also: C<guestfs_mountpoints>");
1599 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600 [InitBasicFS, Always, TestOutputList (
1603 (* check that umount_all can unmount nested mounts correctly: *)
1604 InitEmpty, Always, TestOutputList (
1605 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606 ["mkfs"; "ext2"; "/dev/sda1"];
1607 ["mkfs"; "ext2"; "/dev/sda2"];
1608 ["mkfs"; "ext2"; "/dev/sda3"];
1609 ["mount_options"; ""; "/dev/sda1"; "/"];
1611 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612 ["mkdir"; "/mp1/mp2"];
1613 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614 ["mkdir"; "/mp1/mp2/mp3"];
1617 "unmount all filesystems",
1619 This unmounts all mounted filesystems.
1621 Some internal mounts are not unmounted by this call.");
1623 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1625 "remove all LVM LVs, VGs and PVs",
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1630 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631 [InitISOFS, Always, TestOutput (
1632 [["file"; "/empty"]], "empty");
1633 InitISOFS, Always, TestOutput (
1634 [["file"; "/known-1"]], "ASCII text");
1635 InitISOFS, Always, TestLastFail (
1636 [["file"; "/notexists"]])],
1637 "determine file type",
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file. This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zbsL path>. Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1650 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651 [InitBasicFS, Always, TestOutput (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command"; "/test-command 1"]], "Result1");
1655 InitBasicFS, Always, TestOutput (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command"; "/test-command 2"]], "Result2\n");
1659 InitBasicFS, Always, TestOutput (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command"; "/test-command 3"]], "\nResult3");
1663 InitBasicFS, Always, TestOutput (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command"; "/test-command 4"]], "\nResult4\n");
1667 InitBasicFS, Always, TestOutput (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command"; "/test-command 5"]], "\nResult5\n\n");
1671 InitBasicFS, Always, TestOutput (
1672 [["upload"; "test-command"; "/test-command"];
1673 ["chmod"; "0o755"; "/test-command"];
1674 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675 InitBasicFS, Always, TestOutput (
1676 [["upload"; "test-command"; "/test-command"];
1677 ["chmod"; "0o755"; "/test-command"];
1678 ["command"; "/test-command 7"]], "");
1679 InitBasicFS, Always, TestOutput (
1680 [["upload"; "test-command"; "/test-command"];
1681 ["chmod"; "0o755"; "/test-command"];
1682 ["command"; "/test-command 8"]], "\n");
1683 InitBasicFS, Always, TestOutput (
1684 [["upload"; "test-command"; "/test-command"];
1685 ["chmod"; "0o755"; "/test-command"];
1686 ["command"; "/test-command 9"]], "\n\n");
1687 InitBasicFS, Always, TestOutput (
1688 [["upload"; "test-command"; "/test-command"];
1689 ["chmod"; "0o755"; "/test-command"];
1690 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691 InitBasicFS, Always, TestOutput (
1692 [["upload"; "test-command"; "/test-command"];
1693 ["chmod"; "0o755"; "/test-command"];
1694 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695 InitBasicFS, Always, TestLastFail (
1696 [["upload"; "test-command"; "/test-command"];
1697 ["chmod"; "0o755"; "/test-command"];
1698 ["command"; "/test-command"]])],
1699 "run a command from the guest filesystem",
1701 This call runs a command from the guest filesystem. The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters. The list must be
1709 non-empty (ie. must contain a program name). Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1713 The return value is anything printed to I<stdout> by
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message. The error message
1718 string is the content of I<stderr> from the command.
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>. If you require a program from
1722 another location, you should provide the full path in the
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places. It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1731 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732 [InitBasicFS, Always, TestOutputList (
1733 [["upload"; "test-command"; "/test-command"];
1734 ["chmod"; "0o755"; "/test-command"];
1735 ["command_lines"; "/test-command 1"]], ["Result1"]);
1736 InitBasicFS, Always, TestOutputList (
1737 [["upload"; "test-command"; "/test-command"];
1738 ["chmod"; "0o755"; "/test-command"];
1739 ["command_lines"; "/test-command 2"]], ["Result2"]);
1740 InitBasicFS, Always, TestOutputList (
1741 [["upload"; "test-command"; "/test-command"];
1742 ["chmod"; "0o755"; "/test-command"];
1743 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744 InitBasicFS, Always, TestOutputList (
1745 [["upload"; "test-command"; "/test-command"];
1746 ["chmod"; "0o755"; "/test-command"];
1747 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748 InitBasicFS, Always, TestOutputList (
1749 [["upload"; "test-command"; "/test-command"];
1750 ["chmod"; "0o755"; "/test-command"];
1751 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752 InitBasicFS, Always, TestOutputList (
1753 [["upload"; "test-command"; "/test-command"];
1754 ["chmod"; "0o755"; "/test-command"];
1755 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756 InitBasicFS, Always, TestOutputList (
1757 [["upload"; "test-command"; "/test-command"];
1758 ["chmod"; "0o755"; "/test-command"];
1759 ["command_lines"; "/test-command 7"]], []);
1760 InitBasicFS, Always, TestOutputList (
1761 [["upload"; "test-command"; "/test-command"];
1762 ["chmod"; "0o755"; "/test-command"];
1763 ["command_lines"; "/test-command 8"]], [""]);
1764 InitBasicFS, Always, TestOutputList (
1765 [["upload"; "test-command"; "/test-command"];
1766 ["chmod"; "0o755"; "/test-command"];
1767 ["command_lines"; "/test-command 9"]], ["";""]);
1768 InitBasicFS, Always, TestOutputList (
1769 [["upload"; "test-command"; "/test-command"];
1770 ["chmod"; "0o755"; "/test-command"];
1771 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772 InitBasicFS, Always, TestOutputList (
1773 [["upload"; "test-command"; "/test-command"];
1774 ["chmod"; "0o755"; "/test-command"];
1775 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776 "run a command, returning lines",
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1781 See also: C<guestfs_sh_lines>");
1783 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784 [InitISOFS, Always, TestOutputStruct (
1785 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786 "get file information",
1788 Returns file information for the given C<path>.
1790 This is the same as the C<stat(2)> system call.");
1792 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795 "get file information for a symbolic link",
1797 Returns file information for the given C<path>.
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1803 This is the same as the C<lstat(2)> system call.");
1805 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806 [InitISOFS, Always, TestOutputStruct (
1807 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808 "get file system statistics",
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1814 This is the same as the C<statvfs(2)> system call.");
1816 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1818 "get ext2/ext3/ext4 superblock details",
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1823 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1824 manpage for more details. The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1828 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829 [InitEmpty, Always, TestOutputTrue (
1830 [["blockdev_setro"; "/dev/sda"];
1831 ["blockdev_getro"; "/dev/sda"]])],
1832 "set block device to read-only",
1834 Sets the block device named C<device> to read-only.
1836 This uses the L<blockdev(8)> command.");
1838 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839 [InitEmpty, Always, TestOutputFalse (
1840 [["blockdev_setrw"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-write",
1844 Sets the block device named C<device> to read-write.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849 [InitEmpty, Always, TestOutputTrue (
1850 [["blockdev_setro"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "is block device set to read-only",
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getss"; "/dev/sda"]], 512)],
1862 "get sectorsize of block device",
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 This uses the L<blockdev(8)> command.");
1872 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873 [InitEmpty, Always, TestOutputInt (
1874 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875 "get blocksize of block device",
1877 This returns the block size of a device.
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1882 This uses the L<blockdev(8)> command.");
1884 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1886 "set blocksize of block device",
1888 This sets the block size of a device.
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1893 This uses the L<blockdev(8)> command.");
1895 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896 [InitEmpty, Always, TestOutputInt (
1897 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898 "get total size of device in 512-byte sectors",
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1907 This uses the L<blockdev(8)> command.");
1909 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910 [InitEmpty, Always, TestOutputInt (
1911 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912 "get total size of device in bytes",
1914 This returns the size of the device in bytes.
1916 See also C<guestfs_blockdev_getsz>.
1918 This uses the L<blockdev(8)> command.");
1920 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921 [InitEmpty, Always, TestRun
1922 [["blockdev_flushbufs"; "/dev/sda"]]],
1923 "flush device buffers",
1925 This tells the kernel to flush internal buffers associated
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_rereadpt"; "/dev/sda"]]],
1933 "reread partition table",
1935 Reread the partition table on C<device>.
1937 This uses the L<blockdev(8)> command.");
1939 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940 [InitBasicFS, Always, TestOutput (
1941 (* Pick a file from cwd which isn't likely to change. *)
1942 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943 ["checksum"; "md5"; "/COPYING.LIB"]],
1944 Digest.to_hex (Digest.file "COPYING.LIB"))],
1945 "upload a file from the local machine",
1947 Upload local file C<filename> to C<remotefilename> on the
1950 C<filename> can also be a named pipe.
1952 See also C<guestfs_download>.");
1954 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955 [InitBasicFS, Always, TestOutput (
1956 (* Pick a file from cwd which isn't likely to change. *)
1957 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959 ["upload"; "testdownload.tmp"; "/upload"];
1960 ["checksum"; "md5"; "/upload"]],
1961 Digest.to_hex (Digest.file "COPYING.LIB"))],
1962 "download a file to the local machine",
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1967 C<filename> can also be a named pipe.
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1971 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972 [InitISOFS, Always, TestOutput (
1973 [["checksum"; "crc"; "/known-3"]], "2891671662");
1974 InitISOFS, Always, TestLastFail (
1975 [["checksum"; "crc"; "/notexists"]]);
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988 "compute MD5, SHAx or CRC checksum of file",
1990 This call computes the MD5, SHAx or CRC checksum of the
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2005 Compute the MD5 hash (using the C<md5sum> program).
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2029 The checksum is returned as a printable string.");
2031 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2032 [InitBasicFS, Always, TestOutput (
2033 [["tar_in"; "../images/helloworld.tar"; "/"];
2034 ["cat"; "/hello"]], "hello\n")],
2035 "unpack tarfile to directory",
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2040 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2042 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2044 "pack directory into tarfile",
2046 This command packs the contents of C<directory> and downloads
2047 it to local file C<tarfile>.
2049 To download a compressed tarball, use C<guestfs_tgz_out>.");
2051 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2052 [InitBasicFS, Always, TestOutput (
2053 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054 ["cat"; "/hello"]], "hello\n")],
2055 "unpack compressed tarball to directory",
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2062 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2064 "pack directory into compressed tarball",
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2071 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072 [InitBasicFS, Always, TestLastFail (
2074 ["mount_ro"; "/dev/sda1"; "/"];
2075 ["touch"; "/new"]]);
2076 InitBasicFS, Always, TestOutput (
2077 [["write_file"; "/new"; "data"; "0"];
2079 ["mount_ro"; "/dev/sda1"; "/"];
2080 ["cat"; "/new"]], "data")],
2081 "mount a guest disk, read-only",
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2086 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2088 "mount a guest disk with mount options",
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.
2094 If the C<options> parameter is an empty string, then
2095 no options are passed (all options default to whatever
2096 the filesystem uses).");
2098 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2100 "mount a guest disk with mount options and vfstype",
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2106 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2108 "debugging and internals",
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2114 There is no comprehensive help for this command. You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2118 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119 [InitEmpty, Always, TestOutputList (
2120 [["part_disk"; "/dev/sda"; "mbr"];
2121 ["pvcreate"; "/dev/sda1"];
2122 ["vgcreate"; "VG"; "/dev/sda1"];
2123 ["lvcreate"; "LV1"; "VG"; "50"];
2124 ["lvcreate"; "LV2"; "VG"; "50"];
2125 ["lvremove"; "/dev/VG/LV1"];
2126 ["lvs"]], ["/dev/VG/LV2"]);
2127 InitEmpty, Always, TestOutputList (
2128 [["part_disk"; "/dev/sda"; "mbr"];
2129 ["pvcreate"; "/dev/sda1"];
2130 ["vgcreate"; "VG"; "/dev/sda1"];
2131 ["lvcreate"; "LV1"; "VG"; "50"];
2132 ["lvcreate"; "LV2"; "VG"; "50"];
2133 ["lvremove"; "/dev/VG"];
2135 InitEmpty, Always, TestOutputList (
2136 [["part_disk"; "/dev/sda"; "mbr"];
2137 ["pvcreate"; "/dev/sda1"];
2138 ["vgcreate"; "VG"; "/dev/sda1"];
2139 ["lvcreate"; "LV1"; "VG"; "50"];
2140 ["lvcreate"; "LV2"; "VG"; "50"];
2141 ["lvremove"; "/dev/VG"];
2143 "remove an LVM logical volume",
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2151 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152 [InitEmpty, Always, TestOutputList (
2153 [["part_disk"; "/dev/sda"; "mbr"];
2154 ["pvcreate"; "/dev/sda1"];
2155 ["vgcreate"; "VG"; "/dev/sda1"];
2156 ["lvcreate"; "LV1"; "VG"; "50"];
2157 ["lvcreate"; "LV2"; "VG"; "50"];
2160 InitEmpty, Always, TestOutputList (
2161 [["part_disk"; "/dev/sda"; "mbr"];
2162 ["pvcreate"; "/dev/sda1"];
2163 ["vgcreate"; "VG"; "/dev/sda1"];
2164 ["lvcreate"; "LV1"; "VG"; "50"];
2165 ["lvcreate"; "LV2"; "VG"; "50"];
2168 "remove an LVM volume group",
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2172 This also forcibly removes all logical volumes in the volume
2175 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2176 [InitEmpty, Always, TestOutputListOfDevices (
2177 [["part_disk"; "/dev/sda"; "mbr"];
2178 ["pvcreate"; "/dev/sda1"];
2179 ["vgcreate"; "VG"; "/dev/sda1"];
2180 ["lvcreate"; "LV1"; "VG"; "50"];
2181 ["lvcreate"; "LV2"; "VG"; "50"];
2183 ["pvremove"; "/dev/sda1"];
2185 InitEmpty, Always, TestOutputListOfDevices (
2186 [["part_disk"; "/dev/sda"; "mbr"];
2187 ["pvcreate"; "/dev/sda1"];
2188 ["vgcreate"; "VG"; "/dev/sda1"];
2189 ["lvcreate"; "LV1"; "VG"; "50"];
2190 ["lvcreate"; "LV2"; "VG"; "50"];
2192 ["pvremove"; "/dev/sda1"];
2194 InitEmpty, Always, TestOutputListOfDevices (
2195 [["part_disk"; "/dev/sda"; "mbr"];
2196 ["pvcreate"; "/dev/sda1"];
2197 ["vgcreate"; "VG"; "/dev/sda1"];
2198 ["lvcreate"; "LV1"; "VG"; "50"];
2199 ["lvcreate"; "LV2"; "VG"; "50"];
2201 ["pvremove"; "/dev/sda1"];
2203 "remove an LVM physical volume",
2205 This wipes a physical volume C<device> so that LVM will no longer
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2212 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213 [InitBasicFS, Always, TestOutput (
2214 [["set_e2label"; "/dev/sda1"; "testlabel"];
2215 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216 "set the ext2/3/4 filesystem label",
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>. Filesystem labels are limited to
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2225 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2227 "get the ext2/3/4 filesystem label",
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2232 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233 (let uuid = uuidgen () in
2234 [InitBasicFS, Always, TestOutput (
2235 [["set_e2uuid"; "/dev/sda1"; uuid];
2236 ["get_e2uuid"; "/dev/sda1"]], uuid);
2237 InitBasicFS, Always, TestOutput (
2238 [["set_e2uuid"; "/dev/sda1"; "clear"];
2239 ["get_e2uuid"; "/dev/sda1"]], "");
2240 (* We can't predict what UUIDs will be, so just check the commands run. *)
2241 InitBasicFS, Always, TestRun (
2242 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243 InitBasicFS, Always, TestRun (
2244 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245 "set the ext2/3/4 filesystem UUID",
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>. The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2255 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2257 "get the ext2/3/4 filesystem UUID",
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2262 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2263 [InitBasicFS, Always, TestOutputInt (
2264 [["umount"; "/dev/sda1"];
2265 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266 InitBasicFS, Always, TestOutputInt (
2267 [["umount"; "/dev/sda1"];
2268 ["zero"; "/dev/sda1"];
2269 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270 "run the filesystem checker",
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2275 The returned integer is the status. See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2284 Multiple status codes can be summed together.
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2293 Checking or repairing NTFS volumes is not supported
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2300 ("zero", (RErr, [Device "device"]), 85, [],
2301 [InitBasicFS, Always, TestOutput (
2302 [["umount"; "/dev/sda1"];
2303 ["zero"; "/dev/sda1"];
2304 ["file"; "/dev/sda1"]], "data")],
2305 "write zeroes to the device",
2307 This command writes zeroes over the first few blocks of C<device>.
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device). It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2313 See also: C<guestfs_scrub_device>.");
2315 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316 (* Test disabled because grub-install incompatible with virtio-blk driver.
2317 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2319 [InitBasicFS, Disabled, TestOutputTrue (
2320 [["grub_install"; "/"; "/dev/sda1"];
2321 ["is_dir"; "/boot"]])],
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2327 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328 [InitBasicFS, Always, TestOutput (
2329 [["write_file"; "/old"; "file content"; "0"];
2330 ["cp"; "/old"; "/new"];
2331 ["cat"; "/new"]], "file content");
2332 InitBasicFS, Always, TestOutputTrue (
2333 [["write_file"; "/old"; "file content"; "0"];
2334 ["cp"; "/old"; "/new"];
2335 ["is_file"; "/old"]]);
2336 InitBasicFS, Always, TestOutput (
2337 [["write_file"; "/old"; "file content"; "0"];
2339 ["cp"; "/old"; "/dir/new"];
2340 ["cat"; "/dir/new"]], "file content")],
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2346 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347 [InitBasicFS, Always, TestOutput (
2348 [["mkdir"; "/olddir"];
2349 ["mkdir"; "/newdir"];
2350 ["write_file"; "/olddir/file"; "file content"; "0"];
2351 ["cp_a"; "/olddir"; "/newdir"];
2352 ["cat"; "/newdir/olddir/file"]], "file content")],
2353 "copy a file or directory recursively",
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2358 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359 [InitBasicFS, Always, TestOutput (
2360 [["write_file"; "/old"; "file content"; "0"];
2361 ["mv"; "/old"; "/new"];
2362 ["cat"; "/new"]], "file content");
2363 InitBasicFS, Always, TestOutputFalse (
2364 [["write_file"; "/old"; "file content"; "0"];
2365 ["mv"; "/old"; "/new"];
2366 ["is_file"; "/old"]])],
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2372 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373 [InitEmpty, Always, TestRun (
2374 [["drop_caches"; "3"]])],
2375 "drop kernel page cache, dentries and inodes",
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches. The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2382 Setting C<whattodrop> to 3 should drop everything.
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2387 ("dmesg", (RString "kmsgs", []), 91, [],
2388 [InitEmpty, Always, TestRun (
2390 "return kernel messages",
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel. This is sometimes useful for extended
2394 debugging of problems.
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2401 ("ping_daemon", (RErr, []), 92, [],
2402 [InitEmpty, Always, TestRun (
2403 [["ping_daemon"]])],
2404 "ping the guest daemon",
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess. Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2411 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412 [InitBasicFS, Always, TestOutputTrue (
2413 [["write_file"; "/file1"; "contents of a file"; "0"];
2414 ["cp"; "/file1"; "/file2"];
2415 ["equal"; "/file1"; "/file2"]]);
2416 InitBasicFS, Always, TestOutputFalse (
2417 [["write_file"; "/file1"; "contents of a file"; "0"];
2418 ["write_file"; "/file2"; "contents of another file"; "0"];
2419 ["equal"; "/file1"; "/file2"]]);
2420 InitBasicFS, Always, TestLastFail (
2421 [["equal"; "/file1"; "/file2"]])],
2422 "test if two files have equal contents",
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2427 The external L<cmp(1)> program is used for the comparison.");
2429 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430 [InitISOFS, Always, TestOutputList (
2431 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432 InitISOFS, Always, TestOutputList (
2433 [["strings"; "/empty"]], [])],
2434 "print the printable strings in a file",
2436 This runs the L<strings(1)> command on a file and returns
2437 the list of printable strings found.");
2439 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2440 [InitISOFS, Always, TestOutputList (
2441 [["strings_e"; "b"; "/known-5"]], []);
2442 InitBasicFS, Disabled, TestOutputList (
2443 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2444 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2445 "print the printable strings in a file",
2447 This is like the C<guestfs_strings> command, but allows you to
2448 specify the encoding of strings that are looked for in
2449 the source file C<path>.
2451 Allowed encodings are:
2457 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2458 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2462 Single 8-bit-byte characters.
2466 16-bit big endian strings such as those encoded in
2467 UTF-16BE or UCS-2BE.
2469 =item l (lower case letter L)
2471 16-bit little endian such as UTF-16LE and UCS-2LE.
2472 This is useful for examining binaries in Windows guests.
2476 32-bit big endian such as UCS-4BE.
2480 32-bit little endian such as UCS-4LE.
2484 The returned strings are transcoded to UTF-8.");
2486 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2487 [InitISOFS, Always, TestOutput (
2488 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2489 (* Test for RHBZ#501888c2 regression which caused large hexdump
2490 * commands to segfault.
2492 InitISOFS, Always, TestRun (
2493 [["hexdump"; "/100krandom"]])],
2494 "dump a file in hexadecimal",
2496 This runs C<hexdump -C> on the given C<path>. The result is
2497 the human-readable, canonical hex dump of the file.");
2499 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2500 [InitNone, Always, TestOutput (
2501 [["part_disk"; "/dev/sda"; "mbr"];
2502 ["mkfs"; "ext3"; "/dev/sda1"];
2503 ["mount_options"; ""; "/dev/sda1"; "/"];
2504 ["write_file"; "/new"; "test file"; "0"];
2505 ["umount"; "/dev/sda1"];
2506 ["zerofree"; "/dev/sda1"];
2507 ["mount_options"; ""; "/dev/sda1"; "/"];
2508 ["cat"; "/new"]], "test file")],
2509 "zero unused inodes and disk blocks on ext2/3 filesystem",
2511 This runs the I<zerofree> program on C<device>. This program
2512 claims to zero unused inodes and disk blocks on an ext2/3
2513 filesystem, thus making it possible to compress the filesystem
2516 You should B<not> run this program if the filesystem is
2519 It is possible that using this program can damage the filesystem
2520 or data on the filesystem.");
2522 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2524 "resize an LVM physical volume",
2526 This resizes (expands or shrinks) an existing LVM physical
2527 volume to match the new size of the underlying device.");
2529 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2530 Int "cyls"; Int "heads"; Int "sectors";
2531 String "line"]), 99, [DangerWillRobinson],
2533 "modify a single partition on a block device",
2535 This runs L<sfdisk(8)> option to modify just the single
2536 partition C<n> (note: C<n> counts from 1).
2538 For other parameters, see C<guestfs_sfdisk>. You should usually
2539 pass C<0> for the cyls/heads/sectors parameters.
2541 See also: C<guestfs_part_add>");
2543 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2545 "display the partition table",
2547 This displays the partition table on C<device>, in the
2548 human-readable output of the L<sfdisk(8)> command. It is
2549 not intended to be parsed.
2551 See also: C<guestfs_part_list>");
2553 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2555 "display the kernel geometry",
2557 This displays the kernel's idea of the geometry of C<device>.
2559 The result is in human-readable format, and not designed to
2562 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2564 "display the disk geometry from the partition table",
2566 This displays the disk geometry of C<device> read from the
2567 partition table. Especially in the case where the underlying
2568 block device has been resized, this can be different from the
2569 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2571 The result is in human-readable format, and not designed to
2574 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2576 "activate or deactivate all volume groups",
2578 This command activates or (if C<activate> is false) deactivates
2579 all logical volumes in all volume groups.
2580 If activated, then they are made known to the
2581 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2582 then those devices disappear.
2584 This command is the same as running C<vgchange -a y|n>");
2586 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2588 "activate or deactivate some volume groups",
2590 This command activates or (if C<activate> is false) deactivates
2591 all logical volumes in the listed volume groups C<volgroups>.
2592 If activated, then they are made known to the
2593 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2594 then those devices disappear.
2596 This command is the same as running C<vgchange -a y|n volgroups...>
2598 Note that if C<volgroups> is an empty list then B<all> volume groups
2599 are activated or deactivated.");
2601 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2602 [InitNone, Always, TestOutput (
2603 [["part_disk"; "/dev/sda"; "mbr"];
2604 ["pvcreate"; "/dev/sda1"];
2605 ["vgcreate"; "VG"; "/dev/sda1"];
2606 ["lvcreate"; "LV"; "VG"; "10"];
2607 ["mkfs"; "ext2"; "/dev/VG/LV"];
2608 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2609 ["write_file"; "/new"; "test content"; "0"];
2611 ["lvresize"; "/dev/VG/LV"; "20"];
2612 ["e2fsck_f"; "/dev/VG/LV"];
2613 ["resize2fs"; "/dev/VG/LV"];
2614 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2615 ["cat"; "/new"]], "test content");
2616 InitNone, Always, TestRun (
2617 (* Make an LV smaller to test RHBZ#587484. *)
2618 [["part_disk"; "/dev/sda"; "mbr"];
2619 ["pvcreate"; "/dev/sda1"];
2620 ["vgcreate"; "VG"; "/dev/sda1"];
2621 ["lvcreate"; "LV"; "VG"; "20"];
2622 ["lvresize"; "/dev/VG/LV"; "10"]])],
2623 "resize an LVM logical volume",
2625 This resizes (expands or shrinks) an existing LVM logical
2626 volume to C<mbytes>. When reducing, data in the reduced part
2629 ("resize2fs", (RErr, [Device "device"]), 106, [],
2630 [], (* lvresize tests this *)
2631 "resize an ext2/ext3 filesystem",
2633 This resizes an ext2 or ext3 filesystem to match the size of
2634 the underlying device.
2636 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2637 on the C<device> before calling this command. For unknown reasons
2638 C<resize2fs> sometimes gives an error about this and sometimes not.
2639 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2640 calling this function.");
2642 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2643 [InitBasicFS, Always, TestOutputList (
2644 [["find"; "/"]], ["lost+found"]);
2645 InitBasicFS, Always, TestOutputList (
2649 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2650 InitBasicFS, Always, TestOutputList (
2651 [["mkdir_p"; "/a/b/c"];
2652 ["touch"; "/a/b/c/d"];
2653 ["find"; "/a/b/"]], ["c"; "c/d"])],
2654 "find all files and directories",
2656 This command lists out all files and directories, recursively,
2657 starting at C<directory>. It is essentially equivalent to
2658 running the shell command C<find directory -print> but some
2659 post-processing happens on the output, described below.
2661 This returns a list of strings I<without any prefix>. Thus
2662 if the directory structure was:
2668 then the returned list from C<guestfs_find> C</tmp> would be
2676 If C<directory> is not a directory, then this command returns
2679 The returned list is sorted.
2681 See also C<guestfs_find0>.");
2683 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2684 [], (* lvresize tests this *)
2685 "check an ext2/ext3 filesystem",
2687 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2688 filesystem checker on C<device>, noninteractively (C<-p>),
2689 even if the filesystem appears to be clean (C<-f>).
2691 This command is only needed because of C<guestfs_resize2fs>
2692 (q.v.). Normally you should use C<guestfs_fsck>.");
2694 ("sleep", (RErr, [Int "secs"]), 109, [],
2695 [InitNone, Always, TestRun (
2697 "sleep for some seconds",
2699 Sleep for C<secs> seconds.");
2701 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2702 [InitNone, Always, TestOutputInt (
2703 [["part_disk"; "/dev/sda"; "mbr"];
2704 ["mkfs"; "ntfs"; "/dev/sda1"];
2705 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2706 InitNone, Always, TestOutputInt (
2707 [["part_disk"; "/dev/sda"; "mbr"];
2708 ["mkfs"; "ext2"; "/dev/sda1"];
2709 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2710 "probe NTFS volume",
2712 This command runs the L<ntfs-3g.probe(8)> command which probes
2713 an NTFS C<device> for mountability. (Not all NTFS volumes can
2714 be mounted read-write, and some cannot be mounted at all).
2716 C<rw> is a boolean flag. Set it to true if you want to test
2717 if the volume can be mounted read-write. Set it to false if
2718 you want to test if the volume can be mounted read-only.
2720 The return value is an integer which C<0> if the operation
2721 would succeed, or some non-zero value documented in the
2722 L<ntfs-3g.probe(8)> manual page.");
2724 ("sh", (RString "output", [String "command"]), 111, [],
2725 [], (* XXX needs tests *)
2726 "run a command via the shell",
2728 This call runs a command from the guest filesystem via the
2731 This is like C<guestfs_command>, but passes the command to:
2733 /bin/sh -c \"command\"
2735 Depending on the guest's shell, this usually results in
2736 wildcards being expanded, shell expressions being interpolated
2739 All the provisos about C<guestfs_command> apply to this call.");
2741 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2742 [], (* XXX needs tests *)
2743 "run a command via the shell returning lines",
2745 This is the same as C<guestfs_sh>, but splits the result
2746 into a list of lines.
2748 See also: C<guestfs_command_lines>");
2750 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2751 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2752 * code in stubs.c, since all valid glob patterns must start with "/".
2753 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2755 [InitBasicFS, Always, TestOutputList (
2756 [["mkdir_p"; "/a/b/c"];
2757 ["touch"; "/a/b/c/d"];
2758 ["touch"; "/a/b/c/e"];
2759 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2760 InitBasicFS, Always, TestOutputList (
2761 [["mkdir_p"; "/a/b/c"];
2762 ["touch"; "/a/b/c/d"];
2763 ["touch"; "/a/b/c/e"];
2764 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2765 InitBasicFS, Always, TestOutputList (
2766 [["mkdir_p"; "/a/b/c"];
2767 ["touch"; "/a/b/c/d"];
2768 ["touch"; "/a/b/c/e"];
2769 ["glob_expand"; "/a/*/x/*"]], [])],
2770 "expand a wildcard path",
2772 This command searches for all the pathnames matching
2773 C<pattern> according to the wildcard expansion rules
2776 If no paths match, then this returns an empty list
2777 (note: not an error).
2779 It is just a wrapper around the C L<glob(3)> function
2780 with flags C<GLOB_MARK|GLOB_BRACE>.
2781 See that manual page for more details.");
2783 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2784 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2785 [["scrub_device"; "/dev/sdc"]])],
2786 "scrub (securely wipe) a device",
2788 This command writes patterns over C<device> to make data retrieval
2791 It is an interface to the L<scrub(1)> program. See that
2792 manual page for more details.");
2794 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2795 [InitBasicFS, Always, TestRun (
2796 [["write_file"; "/file"; "content"; "0"];
2797 ["scrub_file"; "/file"]])],
2798 "scrub (securely wipe) a file",
2800 This command writes patterns over a file to make data retrieval
2803 The file is I<removed> after scrubbing.
2805 It is an interface to the L<scrub(1)> program. See that
2806 manual page for more details.");
2808 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2809 [], (* XXX needs testing *)
2810 "scrub (securely wipe) free space",
2812 This command creates the directory C<dir> and then fills it
2813 with files until the filesystem is full, and scrubs the files
2814 as for C<guestfs_scrub_file>, and deletes them.
2815 The intention is to scrub any free space on the partition
2818 It is an interface to the L<scrub(1)> program. See that
2819 manual page for more details.");
2821 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2822 [InitBasicFS, Always, TestRun (
2824 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2825 "create a temporary directory",
2827 This command creates a temporary directory. The
2828 C<template> parameter should be a full pathname for the
2829 temporary directory name with the final six characters being
2832 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2833 the second one being suitable for Windows filesystems.
2835 The name of the temporary directory that was created
2838 The temporary directory is created with mode 0700
2839 and is owned by root.
2841 The caller is responsible for deleting the temporary
2842 directory and its contents after use.
2844 See also: L<mkdtemp(3)>");
2846 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2847 [InitISOFS, Always, TestOutputInt (
2848 [["wc_l"; "/10klines"]], 10000)],
2849 "count lines in a file",
2851 This command counts the lines in a file, using the
2852 C<wc -l> external command.");
2854 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2855 [InitISOFS, Always, TestOutputInt (
2856 [["wc_w"; "/10klines"]], 10000)],
2857 "count words in a file",
2859 This command counts the words in a file, using the
2860 C<wc -w> external command.");
2862 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2863 [InitISOFS, Always, TestOutputInt (
2864 [["wc_c"; "/100kallspaces"]], 102400)],
2865 "count characters in a file",
2867 This command counts the characters in a file, using the
2868 C<wc -c> external command.");
2870 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2871 [InitISOFS, Always, TestOutputList (
2872 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2873 "return first 10 lines of a file",
2875 This command returns up to the first 10 lines of a file as
2876 a list of strings.");
2878 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2879 [InitISOFS, Always, TestOutputList (
2880 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881 InitISOFS, Always, TestOutputList (
2882 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2883 InitISOFS, Always, TestOutputList (
2884 [["head_n"; "0"; "/10klines"]], [])],
2885 "return first N lines of a file",
2887 If the parameter C<nrlines> is a positive number, this returns the first
2888 C<nrlines> lines of the file C<path>.
2890 If the parameter C<nrlines> is a negative number, this returns lines
2891 from the file C<path>, excluding the last C<nrlines> lines.
2893 If the parameter C<nrlines> is zero, this returns an empty list.");
2895 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2896 [InitISOFS, Always, TestOutputList (
2897 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2898 "return last 10 lines of a file",
2900 This command returns up to the last 10 lines of a file as
2901 a list of strings.");
2903 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2904 [InitISOFS, Always, TestOutputList (
2905 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906 InitISOFS, Always, TestOutputList (
2907 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2908 InitISOFS, Always, TestOutputList (
2909 [["tail_n"; "0"; "/10klines"]], [])],
2910 "return last N lines of a file",
2912 If the parameter C<nrlines> is a positive number, this returns the last
2913 C<nrlines> lines of the file C<path>.
2915 If the parameter C<nrlines> is a negative number, this returns lines
2916 from the file C<path>, starting with the C<-nrlines>th line.
2918 If the parameter C<nrlines> is zero, this returns an empty list.");
2920 ("df", (RString "output", []), 125, [],
2921 [], (* XXX Tricky to test because it depends on the exact format
2922 * of the 'df' command and other imponderables.
2924 "report file system disk space usage",
2926 This command runs the C<df> command to report disk space used.
2928 This command is mostly useful for interactive sessions. It
2929 is I<not> intended that you try to parse the output string.
2930 Use C<statvfs> from programs.");
2932 ("df_h", (RString "output", []), 126, [],
2933 [], (* XXX Tricky to test because it depends on the exact format
2934 * of the 'df' command and other imponderables.
2936 "report file system disk space usage (human readable)",
2938 This command runs the C<df -h> command to report disk space used
2939 in human-readable format.
2941 This command is mostly useful for interactive sessions. It
2942 is I<not> intended that you try to parse the output string.
2943 Use C<statvfs> from programs.");
2945 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2946 [InitISOFS, Always, TestOutputInt (
2947 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2948 "estimate file space usage",
2950 This command runs the C<du -s> command to estimate file space
2953 C<path> can be a file or a directory. If C<path> is a directory
2954 then the estimate includes the contents of the directory and all
2955 subdirectories (recursively).
2957 The result is the estimated size in I<kilobytes>
2958 (ie. units of 1024 bytes).");
2960 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2961 [InitISOFS, Always, TestOutputList (
2962 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2963 "list files in an initrd",
2965 This command lists out files contained in an initrd.
2967 The files are listed without any initial C</> character. The
2968 files are listed in the order they appear (not necessarily
2969 alphabetical). Directory names are listed as separate items.
2971 Old Linux kernels (2.4 and earlier) used a compressed ext2
2972 filesystem as initrd. We I<only> support the newer initramfs
2973 format (compressed cpio files).");
2975 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2977 "mount a file using the loop device",
2979 This command lets you mount C<file> (a filesystem image
2980 in a file) on a mount point. It is entirely equivalent to
2981 the command C<mount -o loop file mountpoint>.");
2983 ("mkswap", (RErr, [Device "device"]), 130, [],
2984 [InitEmpty, Always, TestRun (
2985 [["part_disk"; "/dev/sda"; "mbr"];
2986 ["mkswap"; "/dev/sda1"]])],
2987 "create a swap partition",
2989 Create a swap partition on C<device>.");
2991 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2992 [InitEmpty, Always, TestRun (
2993 [["part_disk"; "/dev/sda"; "mbr"];
2994 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2995 "create a swap partition with a label",
2997 Create a swap partition on C<device> with label C<label>.
2999 Note that you cannot attach a swap label to a block device
3000 (eg. C</dev/sda>), just to a partition. This appears to be
3001 a limitation of the kernel or swap tools.");
3003 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3004 (let uuid = uuidgen () in
3005 [InitEmpty, Always, TestRun (
3006 [["part_disk"; "/dev/sda"; "mbr"];
3007 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3008 "create a swap partition with an explicit UUID",
3010 Create a swap partition on C<device> with UUID C<uuid>.");
3012 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3013 [InitBasicFS, Always, TestOutputStruct (
3014 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3015 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3016 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3017 InitBasicFS, Always, TestOutputStruct (
3018 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3019 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3020 "make block, character or FIFO devices",
3022 This call creates block or character special devices, or
3023 named pipes (FIFOs).
3025 The C<mode> parameter should be the mode, using the standard
3026 constants. C<devmajor> and C<devminor> are the
3027 device major and minor numbers, only used when creating block
3028 and character special devices.
3030 Note that, just like L<mknod(2)>, the mode must be bitwise
3031 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3032 just creates a regular file). These constants are
3033 available in the standard Linux header files, or you can use
3034 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3035 which are wrappers around this command which bitwise OR
3036 in the appropriate constant for you.
3038 The mode actually set is affected by the umask.");
3040 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3041 [InitBasicFS, Always, TestOutputStruct (
3042 [["mkfifo"; "0o777"; "/node"];
3043 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3044 "make FIFO (named pipe)",
3046 This call creates a FIFO (named pipe) called C<path> with
3047 mode C<mode>. It is just a convenient wrapper around
3050 The mode actually set is affected by the umask.");
3052 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3053 [InitBasicFS, Always, TestOutputStruct (
3054 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3055 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3056 "make block device node",
3058 This call creates a block device node called C<path> with
3059 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3060 It is just a convenient wrapper around C<guestfs_mknod>.
3062 The mode actually set is affected by the umask.");
3064 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3065 [InitBasicFS, Always, TestOutputStruct (
3066 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3067 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3068 "make char device node",
3070 This call creates a char device node called C<path> with
3071 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3072 It is just a convenient wrapper around C<guestfs_mknod>.
3074 The mode actually set is affected by the umask.");
3076 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3077 [InitEmpty, Always, TestOutputInt (
3078 [["umask"; "0o22"]], 0o22)],
3079 "set file mode creation mask (umask)",
3081 This function sets the mask used for creating new files and
3082 device nodes to C<mask & 0777>.
3084 Typical umask values would be C<022> which creates new files
3085 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3086 C<002> which creates new files with permissions like
3087 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3089 The default umask is C<022>. This is important because it
3090 means that directories and device nodes will be created with
3091 C<0644> or C<0755> mode even if you specify C<0777>.
3093 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3095 This call returns the previous umask.");
3097 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3099 "read directories entries",
3101 This returns the list of directory entries in directory C<dir>.
3103 All entries in the directory are returned, including C<.> and
3104 C<..>. The entries are I<not> sorted, but returned in the same
3105 order as the underlying filesystem.
3107 Also this call returns basic file type information about each
3108 file. The C<ftyp> field will contain one of the following characters:
3146 The L<readdir(3)> call returned a C<d_type> field with an
3151 This function is primarily intended for use by programs. To
3152 get a simple list of names, use C<guestfs_ls>. To get a printable
3153 directory for human consumption, use C<guestfs_ll>.");
3155 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3157 "create partitions on a block device",
3159 This is a simplified interface to the C<guestfs_sfdisk>
3160 command, where partition sizes are specified in megabytes
3161 only (rounded to the nearest cylinder) and you don't need
3162 to specify the cyls, heads and sectors parameters which
3163 were rarely if ever used anyway.
3165 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3166 and C<guestfs_part_disk>");
3168 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3170 "determine file type inside a compressed file",
3172 This command runs C<file> after first decompressing C<path>
3175 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3177 Since 1.0.63, use C<guestfs_file> instead which can now
3178 process compressed files.");
3180 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3182 "list extended attributes of a file or directory",
3184 This call lists the extended attributes of the file or directory
3187 At the system call level, this is a combination of the
3188 L<listxattr(2)> and L<getxattr(2)> calls.
3190 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3192 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3194 "list extended attributes of a file or directory",
3196 This is the same as C<guestfs_getxattrs>, but if C<path>
3197 is a symbolic link, then it returns the extended attributes
3198 of the link itself.");
3200 ("setxattr", (RErr, [String "xattr";
3201 String "val"; Int "vallen"; (* will be BufferIn *)
3202 Pathname "path"]), 143, [Optional "linuxxattrs"],
3204 "set extended attribute of a file or directory",
3206 This call sets the extended attribute named C<xattr>
3207 of the file C<path> to the value C<val> (of length C<vallen>).
3208 The value is arbitrary 8 bit data.
3210 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3212 ("lsetxattr", (RErr, [String "xattr";
3213 String "val"; Int "vallen"; (* will be BufferIn *)
3214 Pathname "path"]), 144, [Optional "linuxxattrs"],
3216 "set extended attribute of a file or directory",
3218 This is the same as C<guestfs_setxattr>, but if C<path>
3219 is a symbolic link, then it sets an extended attribute
3220 of the link itself.");
3222 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3224 "remove extended attribute of a file or directory",
3226 This call removes the extended attribute named C<xattr>
3227 of the file C<path>.
3229 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3231 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3233 "remove extended attribute of a file or directory",
3235 This is the same as C<guestfs_removexattr>, but if C<path>
3236 is a symbolic link, then it removes an extended attribute
3237 of the link itself.");
3239 ("mountpoints", (RHashtable "mps", []), 147, [],
3243 This call is similar to C<guestfs_mounts>. That call returns
3244 a list of devices. This one returns a hash table (map) of
3245 device name to directory where the device is mounted.");
3247 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3248 (* This is a special case: while you would expect a parameter
3249 * of type "Pathname", that doesn't work, because it implies
3250 * NEED_ROOT in the generated calling code in stubs.c, and
3251 * this function cannot use NEED_ROOT.
3254 "create a mountpoint",
3256 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3257 specialized calls that can be used to create extra mountpoints
3258 before mounting the first filesystem.
3260 These calls are I<only> necessary in some very limited circumstances,
3261 mainly the case where you want to mount a mix of unrelated and/or
3262 read-only filesystems together.
3264 For example, live CDs often contain a \"Russian doll\" nest of
3265 filesystems, an ISO outer layer, with a squashfs image inside, with
3266 an ext2/3 image inside that. You can unpack this as follows
3269 add-ro Fedora-11-i686-Live.iso
3272 mkmountpoint /squash
3275 mount-loop /cd/LiveOS/squashfs.img /squash
3276 mount-loop /squash/LiveOS/ext3fs.img /ext3
3278 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3280 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3282 "remove a mountpoint",
3284 This calls removes a mountpoint that was previously created
3285 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3286 for full details.");
3288 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3289 [InitISOFS, Always, TestOutputBuffer (
3290 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3291 (* Test various near large, large and too large files (RHBZ#589039). *)
3292 InitBasicFS, Always, TestLastFail (
3294 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3295 ["read_file"; "/a"]]);
3296 InitBasicFS, Always, TestLastFail (
3298 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3299 ["read_file"; "/a"]]);
3300 InitBasicFS, Always, TestLastFail (
3302 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3303 ["read_file"; "/a"]])],
3306 This calls returns the contents of the file C<path> as a
3309 Unlike C<guestfs_cat>, this function can correctly
3310 handle files that contain embedded ASCII NUL characters.
3311 However unlike C<guestfs_download>, this function is limited
3312 in the total size of file that can be handled.");
3314 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3315 [InitISOFS, Always, TestOutputList (
3316 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3317 InitISOFS, Always, TestOutputList (
3318 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3319 "return lines matching a pattern",
3321 This calls the external C<grep> program and returns the
3324 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3325 [InitISOFS, Always, TestOutputList (
3326 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3327 "return lines matching a pattern",
3329 This calls the external C<egrep> program and returns the
3332 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3333 [InitISOFS, Always, TestOutputList (
3334 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3335 "return lines matching a pattern",
3337 This calls the external C<fgrep> program and returns the
3340 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3341 [InitISOFS, Always, TestOutputList (
3342 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3343 "return lines matching a pattern",
3345 This calls the external C<grep -i> program and returns the
3348 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3349 [InitISOFS, Always, TestOutputList (
3350 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3351 "return lines matching a pattern",
3353 This calls the external C<egrep -i> program and returns the
3356 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3357 [InitISOFS, Always, TestOutputList (
3358 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359 "return lines matching a pattern",
3361 This calls the external C<fgrep -i> program and returns the
3364 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3365 [InitISOFS, Always, TestOutputList (
3366 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3367 "return lines matching a pattern",
3369 This calls the external C<zgrep> program and returns the
3372 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3373 [InitISOFS, Always, TestOutputList (
3374 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3375 "return lines matching a pattern",
3377 This calls the external C<zegrep> program and returns the
3380 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3381 [InitISOFS, Always, TestOutputList (
3382 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383 "return lines matching a pattern",
3385 This calls the external C<zfgrep> program and returns the
3388 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3389 [InitISOFS, Always, TestOutputList (
3390 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3391 "return lines matching a pattern",
3393 This calls the external C<zgrep -i> program and returns the
3396 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3397 [InitISOFS, Always, TestOutputList (
3398 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3399 "return lines matching a pattern",
3401 This calls the external C<zegrep -i> program and returns the
3404 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3405 [InitISOFS, Always, TestOutputList (
3406 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407 "return lines matching a pattern",
3409 This calls the external C<zfgrep -i> program and returns the
3412 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3413 [InitISOFS, Always, TestOutput (
3414 [["realpath"; "/../directory"]], "/directory")],
3415 "canonicalized absolute pathname",
3417 Return the canonicalized absolute pathname of C<path>. The
3418 returned path has no C<.>, C<..> or symbolic link path elements.");
3420 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3421 [InitBasicFS, Always, TestOutputStruct (
3424 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3425 "create a hard link",
3427 This command creates a hard link using the C<ln> command.");
3429 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3430 [InitBasicFS, Always, TestOutputStruct (
3433 ["ln_f"; "/a"; "/b"];
3434 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3435 "create a hard link",
3437 This command creates a hard link using the C<ln -f> command.
3438 The C<-f> option removes the link (C<linkname>) if it exists already.");
3440 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3441 [InitBasicFS, Always, TestOutputStruct (
3443 ["ln_s"; "a"; "/b"];
3444 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3445 "create a symbolic link",
3447 This command creates a symbolic link using the C<ln -s> command.");
3449 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3450 [InitBasicFS, Always, TestOutput (
3451 [["mkdir_p"; "/a/b"];
3452 ["touch"; "/a/b/c"];
3453 ["ln_sf"; "../d"; "/a/b/c"];
3454 ["readlink"; "/a/b/c"]], "../d")],
3455 "create a symbolic link",
3457 This command creates a symbolic link using the C<ln -sf> command,
3458 The C<-f> option removes the link (C<linkname>) if it exists already.");
3460 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3461 [] (* XXX tested above *),
3462 "read the target of a symbolic link",
3464 This command reads the target of a symbolic link.");
3466 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3467 [InitBasicFS, Always, TestOutputStruct (
3468 [["fallocate"; "/a"; "1000000"];
3469 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3470 "preallocate a file in the guest filesystem",
3472 This command preallocates a file (containing zero bytes) named
3473 C<path> of size C<len> bytes. If the file exists already, it
3476 Do not confuse this with the guestfish-specific
3477 C<alloc> command which allocates a file in the host and
3478 attaches it as a device.");
3480 ("swapon_device", (RErr, [Device "device"]), 170, [],
3481 [InitPartition, Always, TestRun (
3482 [["mkswap"; "/dev/sda1"];
3483 ["swapon_device"; "/dev/sda1"];
3484 ["swapoff_device"; "/dev/sda1"]])],
3485 "enable swap on device",
3487 This command enables the libguestfs appliance to use the
3488 swap device or partition named C<device>. The increased
3489 memory is made available for all commands, for example
3490 those run using C<guestfs_command> or C<guestfs_sh>.
3492 Note that you should not swap to existing guest swap
3493 partitions unless you know what you are doing. They may
3494 contain hibernation information, or other information that
3495 the guest doesn't want you to trash. You also risk leaking
3496 information about the host to the guest this way. Instead,
3497 attach a new host device to the guest and swap on that.");
3499 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3500 [], (* XXX tested by swapon_device *)
3501 "disable swap on device",
3503 This command disables the libguestfs appliance swap
3504 device or partition named C<device>.
3505 See C<guestfs_swapon_device>.");
3507 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3508 [InitBasicFS, Always, TestRun (
3509 [["fallocate"; "/swap"; "8388608"];
3510 ["mkswap_file"; "/swap"];
3511 ["swapon_file"; "/swap"];
3512 ["swapoff_file"; "/swap"]])],
3513 "enable swap on file",
3515 This command enables swap to a file.
3516 See C<guestfs_swapon_device> for other notes.");
3518 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3519 [], (* XXX tested by swapon_file *)
3520 "disable swap on file",
3522 This command disables the libguestfs appliance swap on file.");
3524 ("swapon_label", (RErr, [String "label"]), 174, [],
3525 [InitEmpty, Always, TestRun (
3526 [["part_disk"; "/dev/sdb"; "mbr"];
3527 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3528 ["swapon_label"; "swapit"];
3529 ["swapoff_label"; "swapit"];
3530 ["zero"; "/dev/sdb"];
3531 ["blockdev_rereadpt"; "/dev/sdb"]])],
3532 "enable swap on labeled swap partition",
3534 This command enables swap to a labeled swap partition.
3535 See C<guestfs_swapon_device> for other notes.");
3537 ("swapoff_label", (RErr, [String "label"]), 175, [],
3538 [], (* XXX tested by swapon_label *)
3539 "disable swap on labeled swap partition",
3541 This command disables the libguestfs appliance swap on
3542 labeled swap partition.");
3544 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3545 (let uuid = uuidgen () in
3546 [InitEmpty, Always, TestRun (
3547 [["mkswap_U"; uuid; "/dev/sdb"];
3548 ["swapon_uuid"; uuid];
3549 ["swapoff_uuid"; uuid]])]),
3550 "enable swap on swap partition by UUID",
3552 This command enables swap to a swap partition with the given UUID.
3553 See C<guestfs_swapon_device> for other notes.");
3555 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3556 [], (* XXX tested by swapon_uuid *)
3557 "disable swap on swap partition by UUID",
3559 This command disables the libguestfs appliance swap partition
3560 with the given UUID.");
3562 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3563 [InitBasicFS, Always, TestRun (
3564 [["fallocate"; "/swap"; "8388608"];
3565 ["mkswap_file"; "/swap"]])],
3566 "create a swap file",
3570 This command just writes a swap file signature to an existing
3571 file. To create the file itself, use something like C<guestfs_fallocate>.");
3573 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3574 [InitISOFS, Always, TestRun (
3575 [["inotify_init"; "0"]])],
3576 "create an inotify handle",
3578 This command creates a new inotify handle.
3579 The inotify subsystem can be used to notify events which happen to
3580 objects in the guest filesystem.
3582 C<maxevents> is the maximum number of events which will be
3583 queued up between calls to C<guestfs_inotify_read> or
3584 C<guestfs_inotify_files>.
3585 If this is passed as C<0>, then the kernel (or previously set)
3586 default is used. For Linux 2.6.29 the default was 16384 events.
3587 Beyond this limit, the kernel throws away events, but records
3588 the fact that it threw them away by setting a flag
3589 C<IN_Q_OVERFLOW> in the returned structure list (see
3590 C<guestfs_inotify_read>).
3592 Before any events are generated, you have to add some
3593 watches to the internal watch list. See:
3594 C<guestfs_inotify_add_watch>,
3595 C<guestfs_inotify_rm_watch> and
3596 C<guestfs_inotify_watch_all>.
3598 Queued up events should be read periodically by calling
3599 C<guestfs_inotify_read>
3600 (or C<guestfs_inotify_files> which is just a helpful
3601 wrapper around C<guestfs_inotify_read>). If you don't
3602 read the events out often enough then you risk the internal
3605 The handle should be closed after use by calling
3606 C<guestfs_inotify_close>. This also removes any
3607 watches automatically.
3609 See also L<inotify(7)> for an overview of the inotify interface
3610 as exposed by the Linux kernel, which is roughly what we expose
3611 via libguestfs. Note that there is one global inotify handle
3612 per libguestfs instance.");
3614 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3615 [InitBasicFS, Always, TestOutputList (
3616 [["inotify_init"; "0"];
3617 ["inotify_add_watch"; "/"; "1073741823"];
3620 ["inotify_files"]], ["a"; "b"])],
3621 "add an inotify watch",
3623 Watch C<path> for the events listed in C<mask>.
3625 Note that if C<path> is a directory then events within that
3626 directory are watched, but this does I<not> happen recursively
3627 (in subdirectories).
3629 Note for non-C or non-Linux callers: the inotify events are
3630 defined by the Linux kernel ABI and are listed in
3631 C</usr/include/sys/inotify.h>.");
3633 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3635 "remove an inotify watch",
3637 Remove a previously defined inotify watch.
3638 See C<guestfs_inotify_add_watch>.");
3640 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3642 "return list of inotify events",
3644 Return the complete queue of events that have happened
3645 since the previous read call.
3647 If no events have happened, this returns an empty list.
3649 I<Note>: In order to make sure that all events have been
3650 read, you must call this function repeatedly until it
3651 returns an empty list. The reason is that the call will
3652 read events up to the maximum appliance-to-host message
3653 size and leave remaining events in the queue.");
3655 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3657 "return list of watched files that had events",
3659 This function is a helpful wrapper around C<guestfs_inotify_read>
3660 which just returns a list of pathnames of objects that were
3661 touched. The returned pathnames are sorted and deduplicated.");
3663 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3665 "close the inotify handle",
3667 This closes the inotify handle which was previously
3668 opened by inotify_init. It removes all watches, throws
3669 away any pending events, and deallocates all resources.");
3671 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3673 "set SELinux security context",
3675 This sets the SELinux security context of the daemon
3676 to the string C<context>.
3678 See the documentation about SELINUX in L<guestfs(3)>.");
3680 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3682 "get SELinux security context",
3684 This gets the SELinux security context of the daemon.
3686 See the documentation about SELINUX in L<guestfs(3)>,
3687 and C<guestfs_setcon>");
3689 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3690 [InitEmpty, Always, TestOutput (
3691 [["part_disk"; "/dev/sda"; "mbr"];
3692 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3693 ["mount_options"; ""; "/dev/sda1"; "/"];
3694 ["write_file"; "/new"; "new file contents"; "0"];
3695 ["cat"; "/new"]], "new file contents")],
3696 "make a filesystem with block size",
3698 This call is similar to C<guestfs_mkfs>, but it allows you to
3699 control the block size of the resulting filesystem. Supported
3700 block sizes depend on the filesystem type, but typically they
3701 are C<1024>, C<2048> or C<4096> only.");
3703 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3704 [InitEmpty, Always, TestOutput (
3705 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3706 ["mke2journal"; "4096"; "/dev/sda1"];
3707 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3708 ["mount_options"; ""; "/dev/sda2"; "/"];
3709 ["write_file"; "/new"; "new file contents"; "0"];
3710 ["cat"; "/new"]], "new file contents")],
3711 "make ext2/3/4 external journal",
3713 This creates an ext2 external journal on C<device>. It is equivalent
3716 mke2fs -O journal_dev -b blocksize device");
3718 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3719 [InitEmpty, Always, TestOutput (
3720 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3721 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3722 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3723 ["mount_options"; ""; "/dev/sda2"; "/"];
3724 ["write_file"; "/new"; "new file contents"; "0"];
3725 ["cat"; "/new"]], "new file contents")],
3726 "make ext2/3/4 external journal with label",
3728 This creates an ext2 external journal on C<device> with label C<label>.");
3730 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3731 (let uuid = uuidgen () in
3732 [InitEmpty, Always, TestOutput (
3733 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3734 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3735 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3736 ["mount_options"; ""; "/dev/sda2"; "/"];
3737 ["write_file"; "/new"; "new file contents"; "0"];
3738 ["cat"; "/new"]], "new file contents")]),
3739 "make ext2/3/4 external journal with UUID",
3741 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3743 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3745 "make ext2/3/4 filesystem with external journal",
3747 This creates an ext2/3/4 filesystem on C<device> with
3748 an external journal on C<journal>. It is equivalent
3751 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3753 See also C<guestfs_mke2journal>.");
3755 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3757 "make ext2/3/4 filesystem with external journal",
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on the journal labeled C<label>.
3762 See also C<guestfs_mke2journal_L>.");
3764 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3766 "make ext2/3/4 filesystem with external journal",
3768 This creates an ext2/3/4 filesystem on C<device> with
3769 an external journal on the journal with UUID C<uuid>.
3771 See also C<guestfs_mke2journal_U>.");
3773 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3774 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3775 "load a kernel module",
3777 This loads a kernel module in the appliance.
3779 The kernel module must have been whitelisted when libguestfs
3780 was built (see C<appliance/kmod.whitelist.in> in the source).");
3782 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3783 [InitNone, Always, TestOutput (
3784 [["echo_daemon"; "This is a test"]], "This is a test"
3786 "echo arguments back to the client",
3788 This command concatenates the list of C<words> passed with single spaces
3789 between them and returns the resulting string.
3791 You can use this command to test the connection through to the daemon.
3793 See also C<guestfs_ping_daemon>.");
3795 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3796 [], (* There is a regression test for this. *)
3797 "find all files and directories, returning NUL-separated list",
3799 This command lists out all files and directories, recursively,
3800 starting at C<directory>, placing the resulting list in the
3801 external file called C<files>.
3803 This command works the same way as C<guestfs_find> with the
3804 following exceptions:
3810 The resulting list is written to an external file.
3814 Items (filenames) in the result are separated
3815 by C<\\0> characters. See L<find(1)> option I<-print0>.
3819 This command is not limited in the number of names that it
3824 The result list is not sorted.
3828 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3829 [InitISOFS, Always, TestOutput (
3830 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3831 InitISOFS, Always, TestOutput (
3832 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3833 InitISOFS, Always, TestOutput (
3834 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3835 InitISOFS, Always, TestLastFail (
3836 [["case_sensitive_path"; "/Known-1/"]]);
3837 InitBasicFS, Always, TestOutput (
3839 ["mkdir"; "/a/bbb"];
3840 ["touch"; "/a/bbb/c"];
3841 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3842 InitBasicFS, Always, TestOutput (
3844 ["mkdir"; "/a/bbb"];
3845 ["touch"; "/a/bbb/c"];
3846 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3847 InitBasicFS, Always, TestLastFail (
3849 ["mkdir"; "/a/bbb"];
3850 ["touch"; "/a/bbb/c"];
3851 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3852 "return true path on case-insensitive filesystem",
3854 This can be used to resolve case insensitive paths on
3855 a filesystem which is case sensitive. The use case is
3856 to resolve paths which you have read from Windows configuration
3857 files or the Windows Registry, to the true path.
3859 The command handles a peculiarity of the Linux ntfs-3g
3860 filesystem driver (and probably others), which is that although
3861 the underlying filesystem is case-insensitive, the driver
3862 exports the filesystem to Linux as case-sensitive.
3864 One consequence of this is that special directories such
3865 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3866 (or other things) depending on the precise details of how
3867 they were created. In Windows itself this would not be
3870 Bug or feature? You decide:
3871 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3873 This function resolves the true case of each element in the
3874 path and returns the case-sensitive path.
3876 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3877 might return C<\"/WINDOWS/system32\"> (the exact return value
3878 would depend on details of how the directories were originally
3879 created under Windows).
3882 This function does not handle drive names, backslashes etc.
3884 See also C<guestfs_realpath>.");
3886 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3887 [InitBasicFS, Always, TestOutput (
3888 [["vfs_type"; "/dev/sda1"]], "ext2")],
3889 "get the Linux VFS type corresponding to a mounted device",
3891 This command gets the block device type corresponding to
3892 a mounted device called C<device>.
3894 Usually the result is the name of the Linux VFS module that
3895 is used to mount this device (probably determined automatically
3896 if you used the C<guestfs_mount> call).");
3898 ("truncate", (RErr, [Pathname "path"]), 199, [],
3899 [InitBasicFS, Always, TestOutputStruct (
3900 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3901 ["truncate"; "/test"];
3902 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3903 "truncate a file to zero size",
3905 This command truncates C<path> to a zero-length file. The
3906 file must exist already.");
3908 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3909 [InitBasicFS, Always, TestOutputStruct (
3910 [["touch"; "/test"];
3911 ["truncate_size"; "/test"; "1000"];
3912 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3913 "truncate a file to a particular size",
3915 This command truncates C<path> to size C<size> bytes. The file
3918 If the current file size is less than C<size> then
3919 the file is extended to the required size with zero bytes.
3920 This creates a sparse file (ie. disk blocks are not allocated
3921 for the file until you write to it). To create a non-sparse
3922 file of zeroes, use C<guestfs_fallocate64> instead.");
3924 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3925 [InitBasicFS, Always, TestOutputStruct (
3926 [["touch"; "/test"];
3927 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3928 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3929 "set timestamp of a file with nanosecond precision",
3931 This command sets the timestamps of a file with nanosecond
3934 C<atsecs, atnsecs> are the last access time (atime) in secs and
3935 nanoseconds from the epoch.
3937 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3938 secs and nanoseconds from the epoch.
3940 If the C<*nsecs> field contains the special value C<-1> then
3941 the corresponding timestamp is set to the current time. (The
3942 C<*secs> field is ignored in this case).
3944 If the C<*nsecs> field contains the special value C<-2> then
3945 the corresponding timestamp is left unchanged. (The
3946 C<*secs> field is ignored in this case).");
3948 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3949 [InitBasicFS, Always, TestOutputStruct (
3950 [["mkdir_mode"; "/test"; "0o111"];
3951 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3952 "create a directory with a particular mode",
3954 This command creates a directory, setting the initial permissions
3955 of the directory to C<mode>.
3957 For common Linux filesystems, the actual mode which is set will
3958 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3959 interpret the mode in other ways.
3961 See also C<guestfs_mkdir>, C<guestfs_umask>");
3963 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3965 "change file owner and group",
3967 Change the file owner to C<owner> and group to C<group>.
3968 This is like C<guestfs_chown> but if C<path> is a symlink then
3969 the link itself is changed, not the target.
3971 Only numeric uid and gid are supported. If you want to use
3972 names, you will need to locate and parse the password file
3973 yourself (Augeas support makes this relatively easy).");
3975 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3977 "lstat on multiple files",
3979 This call allows you to perform the C<guestfs_lstat> operation
3980 on multiple files, where all files are in the directory C<path>.
3981 C<names> is the list of files from this directory.
3983 On return you get a list of stat structs, with a one-to-one
3984 correspondence to the C<names> list. If any name did not exist
3985 or could not be lstat'd, then the C<ino> field of that structure
3988 This call is intended for programs that want to efficiently
3989 list a directory contents without making many round-trips.
3990 See also C<guestfs_lxattrlist> for a similarly efficient call
3991 for getting extended attributes. Very long directory listings
3992 might cause the protocol message size to be exceeded, causing
3993 this call to fail. The caller must split up such requests
3994 into smaller groups of names.");
3996 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3998 "lgetxattr on multiple files",
4000 This call allows you to get the extended attributes
4001 of multiple files, where all files are in the directory C<path>.
4002 C<names> is the list of files from this directory.
4004 On return you get a flat list of xattr structs which must be
4005 interpreted sequentially. The first xattr struct always has a zero-length
4006 C<attrname>. C<attrval> in this struct is zero-length
4007 to indicate there was an error doing C<lgetxattr> for this
4008 file, I<or> is a C string which is a decimal number
4009 (the number of following attributes for this file, which could
4010 be C<\"0\">). Then after the first xattr struct are the
4011 zero or more attributes for the first named file.
4012 This repeats for the second and subsequent files.
4014 This call is intended for programs that want to efficiently
4015 list a directory contents without making many round-trips.
4016 See also C<guestfs_lstatlist> for a similarly efficient call
4017 for getting standard stats. Very long directory listings
4018 might cause the protocol message size to be exceeded, causing
4019 this call to fail. The caller must split up such requests
4020 into smaller groups of names.");
4022 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4024 "readlink on multiple files",
4026 This call allows you to do a C<readlink> operation
4027 on multiple files, where all files are in the directory C<path>.
4028 C<names> is the list of files from this directory.
4030 On return you get a list of strings, with a one-to-one
4031 correspondence to the C<names> list. Each string is the
4032 value of the symbolic link.
4034 If the C<readlink(2)> operation fails on any name, then
4035 the corresponding result string is the empty string C<\"\">.
4036 However the whole operation is completed even if there
4037 were C<readlink(2)> errors, and so you can call this
4038 function with names where you don't know if they are
4039 symbolic links already (albeit slightly less efficient).
4041 This call is intended for programs that want to efficiently
4042 list a directory contents without making many round-trips.
4043 Very long directory listings might cause the protocol
4044 message size to be exceeded, causing
4045 this call to fail. The caller must split up such requests
4046 into smaller groups of names.");
4048 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4049 [InitISOFS, Always, TestOutputBuffer (
4050 [["pread"; "/known-4"; "1"; "3"]], "\n");
4051 InitISOFS, Always, TestOutputBuffer (
4052 [["pread"; "/empty"; "0"; "100"]], "")],
4053 "read part of a file",
4055 This command lets you read part of a file. It reads C<count>
4056 bytes of the file, starting at C<offset>, from file C<path>.
4058 This may read fewer bytes than requested. For further details
4059 see the L<pread(2)> system call.");
4061 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4062 [InitEmpty, Always, TestRun (
4063 [["part_init"; "/dev/sda"; "gpt"]])],
4064 "create an empty partition table",
4066 This creates an empty partition table on C<device> of one of the
4067 partition types listed below. Usually C<parttype> should be
4068 either C<msdos> or C<gpt> (for large disks).
4070 Initially there are no partitions. Following this, you should
4071 call C<guestfs_part_add> for each partition required.
4073 Possible values for C<parttype> are:
4077 =item B<efi> | B<gpt>
4079 Intel EFI / GPT partition table.
4081 This is recommended for >= 2 TB partitions that will be accessed
4082 from Linux and Intel-based Mac OS X. It also has limited backwards
4083 compatibility with the C<mbr> format.
4085 =item B<mbr> | B<msdos>
4087 The standard PC \"Master Boot Record\" (MBR) format used
4088 by MS-DOS and Windows. This partition type will B<only> work
4089 for device sizes up to 2 TB. For large disks we recommend
4094 Other partition table types that may work but are not
4103 =item B<amiga> | B<rdb>
4105 Amiga \"Rigid Disk Block\" format.
4113 DASD, used on IBM mainframes.
4121 Old Mac partition format. Modern Macs use C<gpt>.
4125 NEC PC-98 format, common in Japan apparently.
4133 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4134 [InitEmpty, Always, TestRun (
4135 [["part_init"; "/dev/sda"; "mbr"];
4136 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4137 InitEmpty, Always, TestRun (
4138 [["part_init"; "/dev/sda"; "gpt"];
4139 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4140 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4141 InitEmpty, Always, TestRun (
4142 [["part_init"; "/dev/sda"; "mbr"];
4143 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4144 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4145 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4146 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4147 "add a partition to the device",
4149 This command adds a partition to C<device>. If there is no partition
4150 table on the device, call C<guestfs_part_init> first.
4152 The C<prlogex> parameter is the type of partition. Normally you
4153 should pass C<p> or C<primary> here, but MBR partition tables also
4154 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4157 C<startsect> and C<endsect> are the start and end of the partition
4158 in I<sectors>. C<endsect> may be negative, which means it counts
4159 backwards from the end of the disk (C<-1> is the last sector).
4161 Creating a partition which covers the whole disk is not so easy.
4162 Use C<guestfs_part_disk> to do that.");
4164 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4165 [InitEmpty, Always, TestRun (
4166 [["part_disk"; "/dev/sda"; "mbr"]]);
4167 InitEmpty, Always, TestRun (
4168 [["part_disk"; "/dev/sda"; "gpt"]])],
4169 "partition whole disk with a single primary partition",
4171 This command is simply a combination of C<guestfs_part_init>
4172 followed by C<guestfs_part_add> to create a single primary partition
4173 covering the whole disk.
4175 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4176 but other possible values are described in C<guestfs_part_init>.");
4178 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4179 [InitEmpty, Always, TestRun (
4180 [["part_disk"; "/dev/sda"; "mbr"];
4181 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4182 "make a partition bootable",
4184 This sets the bootable flag on partition numbered C<partnum> on
4185 device C<device>. Note that partitions are numbered from 1.
4187 The bootable flag is used by some operating systems (notably
4188 Windows) to determine which partition to boot from. It is by
4189 no means universally recognized.");
4191 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4192 [InitEmpty, Always, TestRun (
4193 [["part_disk"; "/dev/sda"; "gpt"];
4194 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4195 "set partition name",
4197 This sets the partition name on partition numbered C<partnum> on
4198 device C<device>. Note that partitions are numbered from 1.
4200 The partition name can only be set on certain types of partition
4201 table. This works on C<gpt> but not on C<mbr> partitions.");
4203 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4204 [], (* XXX Add a regression test for this. *)
4205 "list partitions on a device",
4207 This command parses the partition table on C<device> and
4208 returns the list of partitions found.
4210 The fields in the returned structure are:
4216 Partition number, counting from 1.
4220 Start of the partition I<in bytes>. To get sectors you have to
4221 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4225 End of the partition in bytes.
4229 Size of the partition in bytes.
4233 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4234 [InitEmpty, Always, TestOutput (
4235 [["part_disk"; "/dev/sda"; "gpt"];
4236 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4237 "get the partition table type",
4239 This command examines the partition table on C<device> and
4240 returns the partition table type (format) being used.
4242 Common return values include: C<msdos> (a DOS/Windows style MBR
4243 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4244 values are possible, although unusual. See C<guestfs_part_init>
4247 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4248 [InitBasicFS, Always, TestOutputBuffer (
4249 [["fill"; "0x63"; "10"; "/test"];
4250 ["read_file"; "/test"]], "cccccccccc")],
4251 "fill a file with octets",
4253 This command creates a new file called C<path>. The initial
4254 content of the file is C<len> octets of C<c>, where C<c>
4255 must be a number in the range C<[0..255]>.
4257 To fill a file with zero bytes (sparsely), it is
4258 much more efficient to use C<guestfs_truncate_size>.");
4260 ("available", (RErr, [StringList "groups"]), 216, [],
4261 [InitNone, Always, TestRun [["available"; ""]]],
4262 "test availability of some parts of the API",
4264 This command is used to check the availability of some
4265 groups of functionality in the appliance, which not all builds of
4266 the libguestfs appliance will be able to provide.
4268 The libguestfs groups, and the functions that those
4269 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4271 The argument C<groups> is a list of group names, eg:
4272 C<[\"inotify\", \"augeas\"]> would check for the availability of
4273 the Linux inotify functions and Augeas (configuration file
4276 The command returns no error if I<all> requested groups are available.
4278 It fails with an error if one or more of the requested
4279 groups is unavailable in the appliance.
4281 If an unknown group name is included in the
4282 list of groups then an error is always returned.
4290 You must call C<guestfs_launch> before calling this function.
4292 The reason is because we don't know what groups are
4293 supported by the appliance/daemon until it is running and can
4298 If a group of functions is available, this does not necessarily
4299 mean that they will work. You still have to check for errors
4300 when calling individual API functions even if they are
4305 It is usually the job of distro packagers to build
4306 complete functionality into the libguestfs appliance.
4307 Upstream libguestfs, if built from source with all
4308 requirements satisfied, will support everything.
4312 This call was added in version C<1.0.80>. In previous
4313 versions of libguestfs all you could do would be to speculatively
4314 execute a command to find out if the daemon implemented it.
4315 See also C<guestfs_version>.
4319 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4320 [InitBasicFS, Always, TestOutputBuffer (
4321 [["write_file"; "/src"; "hello, world"; "0"];
4322 ["dd"; "/src"; "/dest"];
4323 ["read_file"; "/dest"]], "hello, world")],
4324 "copy from source to destination using dd",
4326 This command copies from one source device or file C<src>
4327 to another destination device or file C<dest>. Normally you
4328 would use this to copy to or from a device or partition, for
4329 example to duplicate a filesystem.
4331 If the destination is a device, it must be as large or larger
4332 than the source file or device, otherwise the copy will fail.
4333 This command cannot do partial copies (see C<guestfs_copy_size>).");
4335 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4336 [InitBasicFS, Always, TestOutputInt (
4337 [["write_file"; "/file"; "hello, world"; "0"];
4338 ["filesize"; "/file"]], 12)],
4339 "return the size of the file in bytes",
4341 This command returns the size of C<file> in bytes.
4343 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4344 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4345 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4347 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4348 [InitBasicFSonLVM, Always, TestOutputList (
4349 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4350 ["lvs"]], ["/dev/VG/LV2"])],
4351 "rename an LVM logical volume",
4353 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4355 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4356 [InitBasicFSonLVM, Always, TestOutputList (
4358 ["vg_activate"; "false"; "VG"];
4359 ["vgrename"; "VG"; "VG2"];
4360 ["vg_activate"; "true"; "VG2"];
4361 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4362 ["vgs"]], ["VG2"])],
4363 "rename an LVM volume group",
4365 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4367 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4368 [InitISOFS, Always, TestOutputBuffer (
4369 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4370 "list the contents of a single file in an initrd",
4372 This command unpacks the file C<filename> from the initrd file
4373 called C<initrdpath>. The filename must be given I<without> the
4374 initial C</> character.
4376 For example, in guestfish you could use the following command
4377 to examine the boot script (usually called C</init>)
4378 contained in a Linux initrd or initramfs image:
4380 initrd-cat /boot/initrd-<version>.img init
4382 See also C<guestfs_initrd_list>.");
4384 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4386 "get the UUID of a physical volume",
4388 This command returns the UUID of the LVM PV C<device>.");
4390 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4392 "get the UUID of a volume group",
4394 This command returns the UUID of the LVM VG named C<vgname>.");
4396 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4398 "get the UUID of a logical volume",
4400 This command returns the UUID of the LVM LV C<device>.");
4402 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4404 "get the PV UUIDs containing the volume group",
4406 Given a VG called C<vgname>, this returns the UUIDs of all
4407 the physical volumes that this volume group resides on.
4409 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4410 calls to associate physical volumes and volume groups.
4412 See also C<guestfs_vglvuuids>.");
4414 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4416 "get the LV UUIDs of all LVs in the volume group",
4418 Given a VG called C<vgname>, this returns the UUIDs of all
4419 the logical volumes created in this volume group.
4421 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4422 calls to associate logical volumes and volume groups.
4424 See also C<guestfs_vgpvuuids>.");
4426 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4427 [InitBasicFS, Always, TestOutputBuffer (
4428 [["write_file"; "/src"; "hello, world"; "0"];
4429 ["copy_size"; "/src"; "/dest"; "5"];
4430 ["read_file"; "/dest"]], "hello")],
4431 "copy size bytes from source to destination using dd",
4433 This command copies exactly C<size> bytes from one source device
4434 or file C<src> to another destination device or file C<dest>.
4436 Note this will fail if the source is too short or if the destination
4437 is not large enough.");
4439 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4440 [InitEmpty, Always, TestRun (
4441 [["part_init"; "/dev/sda"; "mbr"];
4442 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4443 ["part_del"; "/dev/sda"; "1"]])],
4444 "delete a partition",
4446 This command deletes the partition numbered C<partnum> on C<device>.
4448 Note that in the case of MBR partitioning, deleting an
4449 extended partition also deletes any logical partitions
4452 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4453 [InitEmpty, Always, TestOutputTrue (
4454 [["part_init"; "/dev/sda"; "mbr"];
4455 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4456 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4457 ["part_get_bootable"; "/dev/sda"; "1"]])],
4458 "return true if a partition is bootable",
4460 This command returns true if the partition C<partnum> on
4461 C<device> has the bootable flag set.
4463 See also C<guestfs_part_set_bootable>.");
4465 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4466 [InitEmpty, Always, TestOutputInt (
4467 [["part_init"; "/dev/sda"; "mbr"];
4468 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4469 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4470 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4471 "get the MBR type byte (ID byte) from a partition",
4473 Returns the MBR type byte (also known as the ID byte) from
4474 the numbered partition C<partnum>.
4476 Note that only MBR (old DOS-style) partitions have type bytes.
4477 You will get undefined results for other partition table
4478 types (see C<guestfs_part_get_parttype>).");
4480 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4481 [], (* tested by part_get_mbr_id *)
4482 "set the MBR type byte (ID byte) of a partition",
4484 Sets the MBR type byte (also known as the ID byte) of
4485 the numbered partition C<partnum> to C<idbyte>. Note
4486 that the type bytes quoted in most documentation are
4487 in fact hexadecimal numbers, but usually documented
4488 without any leading \"0x\" which might be confusing.
4490 Note that only MBR (old DOS-style) partitions have type bytes.
4491 You will get undefined results for other partition table
4492 types (see C<guestfs_part_get_parttype>).");
4496 let all_functions = non_daemon_functions @ daemon_functions
4498 (* In some places we want the functions to be displayed sorted
4499 * alphabetically, so this is useful:
4501 let all_functions_sorted =
4502 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4503 compare n1 n2) all_functions
4505 (* Field types for structures. *)
4507 | FChar (* C 'char' (really, a 7 bit byte). *)
4508 | FString (* nul-terminated ASCII string, NOT NULL. *)
4509 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4514 | FBytes (* Any int measure that counts bytes. *)
4515 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4516 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4518 (* Because we generate extra parsing code for LVM command line tools,
4519 * we have to pull out the LVM columns separately here.
4529 "pv_attr", FString (* XXX *);
4530 "pv_pe_count", FInt64;
4531 "pv_pe_alloc_count", FInt64;
4534 "pv_mda_count", FInt64;
4535 "pv_mda_free", FBytes;
4536 (* Not in Fedora 10:
4537 "pv_mda_size", FBytes;
4544 "vg_attr", FString (* XXX *);
4547 "vg_sysid", FString;
4548 "vg_extent_size", FBytes;
4549 "vg_extent_count", FInt64;
4550 "vg_free_count", FInt64;
4555 "snap_count", FInt64;
4558 "vg_mda_count", FInt64;
4559 "vg_mda_free", FBytes;
4560 (* Not in Fedora 10:
4561 "vg_mda_size", FBytes;
4567 "lv_attr", FString (* XXX *);
4570 "lv_kernel_major", FInt64;
4571 "lv_kernel_minor", FInt64;
4573 "seg_count", FInt64;
4575 "snap_percent", FOptPercent;
4576 "copy_percent", FOptPercent;
4579 "mirror_log", FString;
4583 (* Names and fields in all structures (in RStruct and RStructList)
4587 (* The old RIntBool return type, only ever used for aug_defnode. Do
4588 * not use this struct in any new code.
4591 "i", FInt32; (* for historical compatibility *)
4592 "b", FInt32; (* for historical compatibility *)
4595 (* LVM PVs, VGs, LVs. *)
4596 "lvm_pv", lvm_pv_cols;
4597 "lvm_vg", lvm_vg_cols;
4598 "lvm_lv", lvm_lv_cols;
4600 (* Column names and types from stat structures.
4601 * NB. Can't use things like 'st_atime' because glibc header files
4602 * define some of these as macros. Ugh.
4633 (* Column names in dirent structure. *)
4636 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4641 (* Version numbers. *)
4649 (* Extended attribute. *)
4651 "attrname", FString;
4655 (* Inotify events. *)
4659 "in_cookie", FUInt32;
4663 (* Partition table entry. *)
4666 "part_start", FBytes;
4668 "part_size", FBytes;
4670 ] (* end of structs *)
4672 (* Ugh, Java has to be different ..
4673 * These names are also used by the Haskell bindings.
4675 let java_structs = [
4676 "int_bool", "IntBool";
4681 "statvfs", "StatVFS";
4683 "version", "Version";
4685 "inotify_event", "INotifyEvent";
4686 "partition", "Partition";
4689 (* What structs are actually returned. *)
4690 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4692 (* Returns a list of RStruct/RStructList structs that are returned
4693 * by any function. Each element of returned list is a pair:
4695 * (structname, RStructOnly)
4696 * == there exists function which returns RStruct (_, structname)
4697 * (structname, RStructListOnly)
4698 * == there exists function which returns RStructList (_, structname)
4699 * (structname, RStructAndList)
4700 * == there are functions returning both RStruct (_, structname)
4701 * and RStructList (_, structname)
4703 let rstructs_used_by functions =
4704 (* ||| is a "logical OR" for rstructs_used_t *)
4708 | _, RStructAndList -> RStructAndList
4709 | RStructOnly, RStructListOnly
4710 | RStructListOnly, RStructOnly -> RStructAndList
4711 | RStructOnly, RStructOnly -> RStructOnly
4712 | RStructListOnly, RStructListOnly -> RStructListOnly
4715 let h = Hashtbl.create 13 in
4717 (* if elem->oldv exists, update entry using ||| operator,
4718 * else just add elem->newv to the hash
4720 let update elem newv =
4721 try let oldv = Hashtbl.find h elem in
4722 Hashtbl.replace h elem (newv ||| oldv)
4723 with Not_found -> Hashtbl.add h elem newv
4727 fun (_, style, _, _, _, _, _) ->
4728 match fst style with
4729 | RStruct (_, structname) -> update structname RStructOnly
4730 | RStructList (_, structname) -> update structname RStructListOnly
4734 (* return key->values as a list of (key,value) *)
4735 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4737 (* Used for testing language bindings. *)
4739 | CallString of string
4740 | CallOptString of string option
4741 | CallStringList of string list
4743 | CallInt64 of int64
4746 (* Used to memoize the result of pod2text. *)
4747 let pod2text_memo_filename = "src/.pod2text.data"
4748 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4750 let chan = open_in pod2text_memo_filename in
4751 let v = input_value chan in
4755 _ -> Hashtbl.create 13
4756 let pod2text_memo_updated () =
4757 let chan = open_out pod2text_memo_filename in
4758 output_value chan pod2text_memo;
4761 (* Useful functions.
4762 * Note we don't want to use any external OCaml libraries which
4763 * makes this a bit harder than it should be.
4765 module StringMap = Map.Make (String)
4767 let failwithf fs = ksprintf failwith fs
4769 let unique = let i = ref 0 in fun () -> incr i; !i
4771 let replace_char s c1 c2 =
4772 let s2 = String.copy s in
4773 let r = ref false in
4774 for i = 0 to String.length s2 - 1 do
4775 if String.unsafe_get s2 i = c1 then (
4776 String.unsafe_set s2 i c2;
4780 if not !r then s else s2
4784 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4786 let triml ?(test = isspace) str =
4788 let n = ref (String.length str) in
4789 while !n > 0 && test str.[!i]; do
4794 else String.sub str !i !n
4796 let trimr ?(test = isspace) str =
4797 let n = ref (String.length str) in
4798 while !n > 0 && test str.[!n-1]; do
4801 if !n = String.length str then str
4802 else String.sub str 0 !n
4804 let trim ?(test = isspace) str =
4805 trimr ~test (triml ~test str)
4807 let rec find s sub =
4808 let len = String.length s in
4809 let sublen = String.length sub in
4811 if i <= len-sublen then (
4813 if j < sublen then (
4814 if s.[i+j] = sub.[j] then loop2 (j+1)
4820 if r = -1 then loop (i+1) else r
4826 let rec replace_str s s1 s2 =
4827 let len = String.length s in
4828 let sublen = String.length s1 in
4829 let i = find s s1 in
4832 let s' = String.sub s 0 i in
4833 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4834 s' ^ s2 ^ replace_str s'' s1 s2
4837 let rec string_split sep str =
4838 let len = String.length str in
4839 let seplen = String.length sep in
4840 let i = find str sep in
4841 if i = -1 then [str]
4843 let s' = String.sub str 0 i in
4844 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4845 s' :: string_split sep s''
4848 let files_equal n1 n2 =
4849 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4850 match Sys.command cmd with
4853 | i -> failwithf "%s: failed with error code %d" cmd i
4855 let rec filter_map f = function
4859 | Some y -> y :: filter_map f xs
4860 | None -> filter_map f xs
4862 let rec find_map f = function
4863 | [] -> raise Not_found
4867 | None -> find_map f xs
4870 let rec loop i = function
4872 | x :: xs -> f i x; loop (i+1) xs
4877 let rec loop i = function
4879 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4883 let count_chars c str =
4884 let count = ref 0 in
4885 for i = 0 to String.length str - 1 do
4886 if c = String.unsafe_get str i then incr count
4890 let name_of_argt = function
4891 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4892 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4893 | FileIn n | FileOut n -> n
4895 let java_name_of_struct typ =
4896 try List.assoc typ java_structs
4899 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4901 let cols_of_struct typ =
4902 try List.assoc typ structs
4904 failwithf "cols_of_struct: unknown struct %s" typ
4906 let seq_of_test = function
4907 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4908 | TestOutputListOfDevices (s, _)
4909 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4910 | TestOutputTrue s | TestOutputFalse s
4911 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4912 | TestOutputStruct (s, _)
4913 | TestLastFail s -> s
4915 (* Handling for function flags. *)
4916 let protocol_limit_warning =
4917 "Because of the message protocol, there is a transfer limit
4918 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4920 let danger_will_robinson =
4921 "B<This command is dangerous. Without careful use you
4922 can easily destroy all your data>."
4924 let deprecation_notice flags =
4927 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4929 sprintf "This function is deprecated.
4930 In new code, use the C<%s> call instead.
4932 Deprecated functions will not be removed from the API, but the
4933 fact that they are deprecated indicates that there are problems
4934 with correct use of these functions." alt in
4939 (* Create list of optional groups. *)
4941 let h = Hashtbl.create 13 in
4943 fun (name, _, _, flags, _, _, _) ->
4947 let names = try Hashtbl.find h group with Not_found -> [] in
4948 Hashtbl.replace h group (name :: names)
4952 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4955 fun group -> group, List.sort compare (Hashtbl.find h group)
4957 List.sort (fun x y -> compare (fst x) (fst y)) groups
4959 (* Check function names etc. for consistency. *)
4960 let check_functions () =
4961 let contains_uppercase str =
4962 let len = String.length str in
4964 if i >= len then false
4967 if c >= 'A' && c <= 'Z' then true
4974 (* Check function names. *)
4976 fun (name, _, _, _, _, _, _) ->
4977 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4978 failwithf "function name %s does not need 'guestfs' prefix" name;
4980 failwithf "function name is empty";
4981 if name.[0] < 'a' || name.[0] > 'z' then
4982 failwithf "function name %s must start with lowercase a-z" name;
4983 if String.contains name '-' then
4984 failwithf "function name %s should not contain '-', use '_' instead."
4988 (* Check function parameter/return names. *)
4990 fun (name, style, _, _, _, _, _) ->
4991 let check_arg_ret_name n =
4992 if contains_uppercase n then
4993 failwithf "%s param/ret %s should not contain uppercase chars"
4995 if String.contains n '-' || String.contains n '_' then
4996 failwithf "%s param/ret %s should not contain '-' or '_'"
4999 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;
5000 if n = "int" || n = "char" || n = "short" || n = "long" then
5001 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5002 if n = "i" || n = "n" then
5003 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5004 if n = "argv" || n = "args" then
5005 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5007 (* List Haskell, OCaml and C keywords here.
5008 * http://www.haskell.org/haskellwiki/Keywords
5009 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5010 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5011 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5012 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5013 * Omitting _-containing words, since they're handled above.
5014 * Omitting the OCaml reserved word, "val", is ok,
5015 * and saves us from renaming several parameters.
5018 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5019 "char"; "class"; "const"; "constraint"; "continue"; "data";
5020 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5021 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5022 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5023 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5024 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5026 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5027 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5028 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5029 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5030 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5031 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5032 "volatile"; "when"; "where"; "while";
5034 if List.mem n reserved then
5035 failwithf "%s has param/ret using reserved word %s" name n;
5038 (match fst style with
5040 | RInt n | RInt64 n | RBool n
5041 | RConstString n | RConstOptString n | RString n
5042 | RStringList n | RStruct (n, _) | RStructList (n, _)
5043 | RHashtable n | RBufferOut n ->
5044 check_arg_ret_name n
5046 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5049 (* Check short descriptions. *)
5051 fun (name, _, _, _, _, shortdesc, _) ->
5052 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5053 failwithf "short description of %s should begin with lowercase." name;
5054 let c = shortdesc.[String.length shortdesc-1] in
5055 if c = '\n' || c = '.' then
5056 failwithf "short description of %s should not end with . or \\n." name
5059 (* Check long descriptions. *)
5061 fun (name, _, _, _, _, _, longdesc) ->
5062 if longdesc.[String.length longdesc-1] = '\n' then
5063 failwithf "long description of %s should not end with \\n." name
5066 (* Check proc_nrs. *)
5068 fun (name, _, proc_nr, _, _, _, _) ->
5069 if proc_nr <= 0 then
5070 failwithf "daemon function %s should have proc_nr > 0" name
5074 fun (name, _, proc_nr, _, _, _, _) ->
5075 if proc_nr <> -1 then
5076 failwithf "non-daemon function %s should have proc_nr -1" name
5077 ) non_daemon_functions;
5080 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5083 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5084 let rec loop = function
5087 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5089 | (name1,nr1) :: (name2,nr2) :: _ ->
5090 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5098 (* Ignore functions that have no tests. We generate a
5099 * warning when the user does 'make check' instead.
5101 | name, _, _, _, [], _, _ -> ()
5102 | name, _, _, _, tests, _, _ ->
5106 match seq_of_test test with
5108 failwithf "%s has a test containing an empty sequence" name
5109 | cmds -> List.map List.hd cmds
5111 let funcs = List.flatten funcs in
5113 let tested = List.mem name funcs in
5116 failwithf "function %s has tests but does not test itself" name
5119 (* 'pr' prints to the current output file. *)
5120 let chan = ref Pervasives.stdout
5125 let i = count_chars '\n' str in
5126 lines := !lines + i;
5127 output_string !chan str
5130 let copyright_years =
5131 let this_year = 1900 + (localtime (time ())).tm_year in
5132 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5134 (* Generate a header block in a number of standard styles. *)
5135 type comment_style =
5136 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5137 type license = GPLv2plus | LGPLv2plus
5139 let generate_header ?(extra_inputs = []) comment license =
5140 let inputs = "src/generator.ml" :: extra_inputs in
5141 let c = match comment with
5142 | CStyle -> pr "/* "; " *"
5143 | CPlusPlusStyle -> pr "// "; "//"
5144 | HashStyle -> pr "# "; "#"
5145 | OCamlStyle -> pr "(* "; " *"
5146 | HaskellStyle -> pr "{- "; " " in
5147 pr "libguestfs generated file\n";
5148 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5149 List.iter (pr "%s %s\n" c) inputs;
5150 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5152 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5156 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5157 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5158 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5159 pr "%s (at your option) any later version.\n" c;
5161 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5162 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5163 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5164 pr "%s GNU General Public License for more details.\n" c;
5166 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5167 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5168 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5171 pr "%s This library is free software; you can redistribute it and/or\n" c;
5172 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5173 pr "%s License as published by the Free Software Foundation; either\n" c;
5174 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5176 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5177 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5178 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5179 pr "%s Lesser General Public License for more details.\n" c;
5181 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5182 pr "%s License along with this library; if not, write to the Free Software\n" c;
5183 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5186 | CStyle -> pr " */\n"
5189 | OCamlStyle -> pr " *)\n"
5190 | HaskellStyle -> pr "-}\n"
5194 (* Start of main code generation functions below this line. *)
5196 (* Generate the pod documentation for the C API. *)
5197 let rec generate_actions_pod () =
5199 fun (shortname, style, _, flags, _, _, longdesc) ->
5200 if not (List.mem NotInDocs flags) then (
5201 let name = "guestfs_" ^ shortname in
5202 pr "=head2 %s\n\n" name;
5204 generate_prototype ~extern:false ~handle:"g" name style;
5206 pr "%s\n\n" longdesc;
5207 (match fst style with
5209 pr "This function returns 0 on success or -1 on error.\n\n"
5211 pr "On error this function returns -1.\n\n"
5213 pr "On error this function returns -1.\n\n"
5215 pr "This function returns a C truth value on success or -1 on error.\n\n"
5217 pr "This function returns a string, or NULL on error.
5218 The string is owned by the guest handle and must I<not> be freed.\n\n"
5219 | RConstOptString _ ->
5220 pr "This function returns a string which may be NULL.
5221 There is way to return an error from this function.
5222 The string is owned by the guest handle and must I<not> be freed.\n\n"
5224 pr "This function returns a string, or NULL on error.
5225 I<The caller must free the returned string after use>.\n\n"
5227 pr "This function returns a NULL-terminated array of strings
5228 (like L<environ(3)>), or NULL if there was an error.
5229 I<The caller must free the strings and the array after use>.\n\n"
5230 | RStruct (_, typ) ->
5231 pr "This function returns a C<struct guestfs_%s *>,
5232 or NULL if there was an error.
5233 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5234 | RStructList (_, typ) ->
5235 pr "This function returns a C<struct guestfs_%s_list *>
5236 (see E<lt>guestfs-structs.hE<gt>),
5237 or NULL if there was an error.
5238 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5240 pr "This function returns a NULL-terminated array of
5241 strings, or NULL if there was an error.
5242 The array of strings will always have length C<2n+1>, where
5243 C<n> keys and values alternate, followed by the trailing NULL entry.
5244 I<The caller must free the strings and the array after use>.\n\n"
5246 pr "This function returns a buffer, or NULL on error.
5247 The size of the returned buffer is written to C<*size_r>.
5248 I<The caller must free the returned buffer after use>.\n\n"
5250 if List.mem ProtocolLimitWarning flags then
5251 pr "%s\n\n" protocol_limit_warning;
5252 if List.mem DangerWillRobinson flags then
5253 pr "%s\n\n" danger_will_robinson;
5254 match deprecation_notice flags with
5256 | Some txt -> pr "%s\n\n" txt
5258 ) all_functions_sorted
5260 and generate_structs_pod () =
5261 (* Structs documentation. *)
5264 pr "=head2 guestfs_%s\n" typ;
5266 pr " struct guestfs_%s {\n" typ;
5269 | name, FChar -> pr " char %s;\n" name
5270 | name, FUInt32 -> pr " uint32_t %s;\n" name
5271 | name, FInt32 -> pr " int32_t %s;\n" name
5272 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5273 | name, FInt64 -> pr " int64_t %s;\n" name
5274 | name, FString -> pr " char *%s;\n" name
5276 pr " /* The next two fields describe a byte array. */\n";
5277 pr " uint32_t %s_len;\n" name;
5278 pr " char *%s;\n" name
5280 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5281 pr " char %s[32];\n" name
5282 | name, FOptPercent ->
5283 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5284 pr " float %s;\n" name
5288 pr " struct guestfs_%s_list {\n" typ;
5289 pr " uint32_t len; /* Number of elements in list. */\n";
5290 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5293 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5294 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5299 and generate_availability_pod () =
5300 (* Availability documentation. *)
5304 fun (group, functions) ->
5305 pr "=item B<%s>\n" group;
5307 pr "The following functions:\n";
5308 List.iter (pr "L</guestfs_%s>\n") functions;
5314 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5315 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5317 * We have to use an underscore instead of a dash because otherwise
5318 * rpcgen generates incorrect code.
5320 * This header is NOT exported to clients, but see also generate_structs_h.
5322 and generate_xdr () =
5323 generate_header CStyle LGPLv2plus;
5325 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5326 pr "typedef string str<>;\n";
5329 (* Internal structures. *)
5333 pr "struct guestfs_int_%s {\n" typ;
5335 | name, FChar -> pr " char %s;\n" name
5336 | name, FString -> pr " string %s<>;\n" name
5337 | name, FBuffer -> pr " opaque %s<>;\n" name
5338 | name, FUUID -> pr " opaque %s[32];\n" name
5339 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5340 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5341 | name, FOptPercent -> pr " float %s;\n" name
5345 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5350 fun (shortname, style, _, _, _, _, _) ->
5351 let name = "guestfs_" ^ shortname in
5353 (match snd style with
5356 pr "struct %s_args {\n" name;
5359 | Pathname n | Device n | Dev_or_Path n | String n ->
5360 pr " string %s<>;\n" n
5361 | OptString n -> pr " str *%s;\n" n
5362 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5363 | Bool n -> pr " bool %s;\n" n
5364 | Int n -> pr " int %s;\n" n
5365 | Int64 n -> pr " hyper %s;\n" n
5366 | FileIn _ | FileOut _ -> ()
5370 (match fst style with
5373 pr "struct %s_ret {\n" name;
5377 pr "struct %s_ret {\n" name;
5378 pr " hyper %s;\n" n;
5381 pr "struct %s_ret {\n" name;
5384 | RConstString _ | RConstOptString _ ->
5385 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5387 pr "struct %s_ret {\n" name;
5388 pr " string %s<>;\n" n;
5391 pr "struct %s_ret {\n" name;
5392 pr " str %s<>;\n" n;
5394 | RStruct (n, typ) ->
5395 pr "struct %s_ret {\n" name;
5396 pr " guestfs_int_%s %s;\n" typ n;
5398 | RStructList (n, typ) ->
5399 pr "struct %s_ret {\n" name;
5400 pr " guestfs_int_%s_list %s;\n" typ n;
5403 pr "struct %s_ret {\n" name;
5404 pr " str %s<>;\n" n;
5407 pr "struct %s_ret {\n" name;
5408 pr " opaque %s<>;\n" n;
5413 (* Table of procedure numbers. *)
5414 pr "enum guestfs_procedure {\n";
5416 fun (shortname, _, proc_nr, _, _, _, _) ->
5417 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5419 pr " GUESTFS_PROC_NR_PROCS\n";
5423 (* Having to choose a maximum message size is annoying for several
5424 * reasons (it limits what we can do in the API), but it (a) makes
5425 * the protocol a lot simpler, and (b) provides a bound on the size
5426 * of the daemon which operates in limited memory space.
5428 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5431 (* Message header, etc. *)
5433 /* The communication protocol is now documented in the guestfs(3)
5437 const GUESTFS_PROGRAM = 0x2000F5F5;
5438 const GUESTFS_PROTOCOL_VERSION = 1;
5440 /* These constants must be larger than any possible message length. */
5441 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5442 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5444 enum guestfs_message_direction {
5445 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5446 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5449 enum guestfs_message_status {
5450 GUESTFS_STATUS_OK = 0,
5451 GUESTFS_STATUS_ERROR = 1
5454 const GUESTFS_ERROR_LEN = 256;
5456 struct guestfs_message_error {
5457 string error_message<GUESTFS_ERROR_LEN>;
5460 struct guestfs_message_header {
5461 unsigned prog; /* GUESTFS_PROGRAM */
5462 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5463 guestfs_procedure proc; /* GUESTFS_PROC_x */
5464 guestfs_message_direction direction;
5465 unsigned serial; /* message serial number */
5466 guestfs_message_status status;
5469 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5471 struct guestfs_chunk {
5472 int cancel; /* if non-zero, transfer is cancelled */
5473 /* data size is 0 bytes if the transfer has finished successfully */
5474 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5478 (* Generate the guestfs-structs.h file. *)
5479 and generate_structs_h () =
5480 generate_header CStyle LGPLv2plus;
5482 (* This is a public exported header file containing various
5483 * structures. The structures are carefully written to have
5484 * exactly the same in-memory format as the XDR structures that
5485 * we use on the wire to the daemon. The reason for creating
5486 * copies of these structures here is just so we don't have to
5487 * export the whole of guestfs_protocol.h (which includes much
5488 * unrelated and XDR-dependent stuff that we don't want to be
5489 * public, or required by clients).
5491 * To reiterate, we will pass these structures to and from the
5492 * client with a simple assignment or memcpy, so the format
5493 * must be identical to what rpcgen / the RFC defines.
5496 (* Public structures. *)
5499 pr "struct guestfs_%s {\n" typ;
5502 | name, FChar -> pr " char %s;\n" name
5503 | name, FString -> pr " char *%s;\n" name
5505 pr " uint32_t %s_len;\n" name;
5506 pr " char *%s;\n" name
5507 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5508 | name, FUInt32 -> pr " uint32_t %s;\n" name
5509 | name, FInt32 -> pr " int32_t %s;\n" name
5510 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5511 | name, FInt64 -> pr " int64_t %s;\n" name
5512 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5516 pr "struct guestfs_%s_list {\n" typ;
5517 pr " uint32_t len;\n";
5518 pr " struct guestfs_%s *val;\n" typ;
5521 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5522 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5526 (* Generate the guestfs-actions.h file. *)
5527 and generate_actions_h () =
5528 generate_header CStyle LGPLv2plus;
5530 fun (shortname, style, _, _, _, _, _) ->
5531 let name = "guestfs_" ^ shortname in
5532 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5536 (* Generate the guestfs-internal-actions.h file. *)
5537 and generate_internal_actions_h () =
5538 generate_header CStyle LGPLv2plus;
5540 fun (shortname, style, _, _, _, _, _) ->
5541 let name = "guestfs__" ^ shortname in
5542 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5544 ) non_daemon_functions
5546 (* Generate the client-side dispatch stubs. *)
5547 and generate_client_actions () =
5548 generate_header CStyle LGPLv2plus;
5555 #include <inttypes.h>
5557 #include \"guestfs.h\"
5558 #include \"guestfs-internal.h\"
5559 #include \"guestfs-internal-actions.h\"
5560 #include \"guestfs_protocol.h\"
5562 #define error guestfs_error
5563 //#define perrorf guestfs_perrorf
5564 #define safe_malloc guestfs_safe_malloc
5565 #define safe_realloc guestfs_safe_realloc
5566 //#define safe_strdup guestfs_safe_strdup
5567 #define safe_memdup guestfs_safe_memdup
5569 /* Check the return message from a call for validity. */
5571 check_reply_header (guestfs_h *g,
5572 const struct guestfs_message_header *hdr,
5573 unsigned int proc_nr, unsigned int serial)
5575 if (hdr->prog != GUESTFS_PROGRAM) {
5576 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5579 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5580 error (g, \"wrong protocol version (%%d/%%d)\",
5581 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5584 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5585 error (g, \"unexpected message direction (%%d/%%d)\",
5586 hdr->direction, GUESTFS_DIRECTION_REPLY);
5589 if (hdr->proc != proc_nr) {
5590 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5593 if (hdr->serial != serial) {
5594 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5601 /* Check we are in the right state to run a high-level action. */
5603 check_state (guestfs_h *g, const char *caller)
5605 if (!guestfs__is_ready (g)) {
5606 if (guestfs__is_config (g) || guestfs__is_launching (g))
5607 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5610 error (g, \"%%s called from the wrong state, %%d != READY\",
5611 caller, guestfs__get_state (g));
5619 (* Generate code to generate guestfish call traces. *)
5620 let trace_call shortname style =
5621 pr " if (guestfs__get_trace (g)) {\n";
5624 List.exists (function
5625 | StringList _ | DeviceList _ -> true
5626 | _ -> false) (snd style) in
5632 pr " printf (\"%s\");\n" shortname;
5635 | String n (* strings *)
5641 (* guestfish doesn't support string escaping, so neither do we *)
5642 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5643 | OptString n -> (* string option *)
5644 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5645 pr " else printf (\" null\");\n"
5647 | DeviceList n -> (* string list *)
5648 pr " putchar (' ');\n";
5649 pr " putchar ('\"');\n";
5650 pr " for (i = 0; %s[i]; ++i) {\n" n;
5651 pr " if (i > 0) putchar (' ');\n";
5652 pr " fputs (%s[i], stdout);\n" n;
5654 pr " putchar ('\"');\n";
5655 | Bool n -> (* boolean *)
5656 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5657 | Int n -> (* int *)
5658 pr " printf (\" %%d\", %s);\n" n
5660 pr " printf (\" %%\" PRIi64, %s);\n" n
5662 pr " putchar ('\\n');\n";
5667 (* For non-daemon functions, generate a wrapper around each function. *)
5669 fun (shortname, style, _, _, _, _, _) ->
5670 let name = "guestfs_" ^ shortname in
5672 generate_prototype ~extern:false ~semicolon:false ~newline:true
5673 ~handle:"g" name style;
5675 trace_call shortname style;
5676 pr " return guestfs__%s " shortname;
5677 generate_c_call_args ~handle:"g" style;
5681 ) non_daemon_functions;
5683 (* Client-side stubs for each function. *)
5685 fun (shortname, style, _, _, _, _, _) ->
5686 let name = "guestfs_" ^ shortname in
5688 (* Generate the action stub. *)
5689 generate_prototype ~extern:false ~semicolon:false ~newline:true
5690 ~handle:"g" name style;
5693 match fst style with
5694 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5695 | RConstString _ | RConstOptString _ ->
5696 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5697 | RString _ | RStringList _
5698 | RStruct _ | RStructList _
5699 | RHashtable _ | RBufferOut _ ->
5704 (match snd style with
5706 | _ -> pr " struct %s_args args;\n" name
5709 pr " guestfs_message_header hdr;\n";
5710 pr " guestfs_message_error err;\n";
5712 match fst style with
5714 | RConstString _ | RConstOptString _ ->
5715 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5717 | RBool _ | RString _ | RStringList _
5718 | RStruct _ | RStructList _
5719 | RHashtable _ | RBufferOut _ ->
5720 pr " struct %s_ret ret;\n" name;
5723 pr " int serial;\n";
5726 trace_call shortname style;
5727 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5728 pr " guestfs___set_busy (g);\n";
5731 (* Send the main header and arguments. *)
5732 (match snd style with
5734 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5735 (String.uppercase shortname)
5739 | Pathname n | Device n | Dev_or_Path n | String n ->
5740 pr " args.%s = (char *) %s;\n" n n
5742 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5743 | StringList n | DeviceList n ->
5744 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5745 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5747 pr " args.%s = %s;\n" n n
5749 pr " args.%s = %s;\n" n n
5751 pr " args.%s = %s;\n" n n
5752 | FileIn _ | FileOut _ -> ()
5754 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5755 (String.uppercase shortname);
5756 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5759 pr " if (serial == -1) {\n";
5760 pr " guestfs___end_busy (g);\n";
5761 pr " return %s;\n" error_code;
5765 (* Send any additional files (FileIn) requested. *)
5766 let need_read_reply_label = ref false in
5770 pr " r = guestfs___send_file (g, %s);\n" n;
5771 pr " if (r == -1) {\n";
5772 pr " guestfs___end_busy (g);\n";
5773 pr " return %s;\n" error_code;
5775 pr " if (r == -2) /* daemon cancelled */\n";
5776 pr " goto read_reply;\n";
5777 need_read_reply_label := true;
5782 (* Wait for the reply from the remote end. *)
5783 if !need_read_reply_label then pr " read_reply:\n";
5784 pr " memset (&hdr, 0, sizeof hdr);\n";
5785 pr " memset (&err, 0, sizeof err);\n";
5786 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5788 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5792 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5795 pr " if (r == -1) {\n";
5796 pr " guestfs___end_busy (g);\n";
5797 pr " return %s;\n" error_code;
5801 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5802 (String.uppercase shortname);
5803 pr " guestfs___end_busy (g);\n";
5804 pr " return %s;\n" error_code;
5808 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5809 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5810 pr " free (err.error_message);\n";
5811 pr " guestfs___end_busy (g);\n";
5812 pr " return %s;\n" error_code;
5816 (* Expecting to receive further files (FileOut)? *)
5820 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5821 pr " guestfs___end_busy (g);\n";
5822 pr " return %s;\n" error_code;
5828 pr " guestfs___end_busy (g);\n";
5830 (match fst style with
5831 | RErr -> pr " return 0;\n"
5832 | RInt n | RInt64 n | RBool n ->
5833 pr " return ret.%s;\n" n
5834 | RConstString _ | RConstOptString _ ->
5835 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5837 pr " return ret.%s; /* caller will free */\n" n
5838 | RStringList n | RHashtable n ->
5839 pr " /* caller will free this, but we need to add a NULL entry */\n";
5840 pr " ret.%s.%s_val =\n" n n;
5841 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5842 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5844 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5845 pr " return ret.%s.%s_val;\n" n n
5847 pr " /* caller will free this */\n";
5848 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5849 | RStructList (n, _) ->
5850 pr " /* caller will free this */\n";
5851 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5853 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5854 pr " * _val might be NULL here. To make the API saner for\n";
5855 pr " * callers, we turn this case into a unique pointer (using\n";
5856 pr " * malloc(1)).\n";
5858 pr " if (ret.%s.%s_len > 0) {\n" n n;
5859 pr " *size_r = ret.%s.%s_len;\n" n n;
5860 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5862 pr " free (ret.%s.%s_val);\n" n n;
5863 pr " char *p = safe_malloc (g, 1);\n";
5864 pr " *size_r = ret.%s.%s_len;\n" n n;
5872 (* Functions to free structures. *)
5873 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5874 pr " * structure format is identical to the XDR format. See note in\n";
5875 pr " * generator.ml.\n";
5882 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5884 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5890 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5892 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5899 (* Generate daemon/actions.h. *)
5900 and generate_daemon_actions_h () =
5901 generate_header CStyle GPLv2plus;
5903 pr "#include \"../src/guestfs_protocol.h\"\n";
5907 fun (name, style, _, _, _, _, _) ->
5909 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5913 (* Generate the linker script which controls the visibility of
5914 * symbols in the public ABI and ensures no other symbols get
5915 * exported accidentally.
5917 and generate_linker_script () =
5918 generate_header HashStyle GPLv2plus;
5923 "guestfs_get_error_handler";
5924 "guestfs_get_out_of_memory_handler";
5925 "guestfs_last_error";
5926 "guestfs_set_error_handler";
5927 "guestfs_set_launch_done_callback";
5928 "guestfs_set_log_message_callback";
5929 "guestfs_set_out_of_memory_handler";
5930 "guestfs_set_subprocess_quit_callback";
5932 (* Unofficial parts of the API: the bindings code use these
5933 * functions, so it is useful to export them.
5935 "guestfs_safe_calloc";
5936 "guestfs_safe_malloc";
5939 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5943 List.map (fun (typ, _) ->
5944 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5947 let globals = List.sort compare (globals @ functions @ structs) in
5951 List.iter (pr " %s;\n") globals;
5958 (* Generate the server-side stubs. *)
5959 and generate_daemon_actions () =
5960 generate_header CStyle GPLv2plus;
5962 pr "#include <config.h>\n";
5964 pr "#include <stdio.h>\n";
5965 pr "#include <stdlib.h>\n";
5966 pr "#include <string.h>\n";
5967 pr "#include <inttypes.h>\n";
5968 pr "#include <rpc/types.h>\n";
5969 pr "#include <rpc/xdr.h>\n";
5971 pr "#include \"daemon.h\"\n";
5972 pr "#include \"c-ctype.h\"\n";
5973 pr "#include \"../src/guestfs_protocol.h\"\n";
5974 pr "#include \"actions.h\"\n";
5978 fun (name, style, _, _, _, _, _) ->
5979 (* Generate server-side stubs. *)
5980 pr "static void %s_stub (XDR *xdr_in)\n" name;
5983 match fst style with
5984 | RErr | RInt _ -> pr " int r;\n"; "-1"
5985 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5986 | RBool _ -> pr " int r;\n"; "-1"
5987 | RConstString _ | RConstOptString _ ->
5988 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5989 | RString _ -> pr " char *r;\n"; "NULL"
5990 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5991 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5992 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5994 pr " size_t size = 1;\n";
5998 (match snd style with
6001 pr " struct guestfs_%s_args args;\n" name;
6004 | Device n | Dev_or_Path n
6007 | OptString n -> pr " char *%s;\n" n
6008 | StringList n | DeviceList n -> pr " char **%s;\n" n
6009 | Bool n -> pr " int %s;\n" n
6010 | Int n -> pr " int %s;\n" n
6011 | Int64 n -> pr " int64_t %s;\n" n
6012 | FileIn _ | FileOut _ -> ()
6017 (match snd style with
6020 pr " memset (&args, 0, sizeof args);\n";
6022 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6023 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6027 pr " char *%s = args.%s;\n" n n
6029 let pr_list_handling_code n =
6030 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6031 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6032 pr " if (%s == NULL) {\n" n;
6033 pr " reply_with_perror (\"realloc\");\n";
6036 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6037 pr " args.%s.%s_val = %s;\n" n n n;
6043 pr " ABS_PATH (%s, goto done);\n" n;
6046 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6049 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6050 | String n -> pr_args n
6051 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6053 pr_list_handling_code n;
6055 pr_list_handling_code n;
6056 pr " /* Ensure that each is a device,\n";
6057 pr " * and perform device name translation. */\n";
6058 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6059 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6061 | Bool n -> pr " %s = args.%s;\n" n n
6062 | Int n -> pr " %s = args.%s;\n" n n
6063 | Int64 n -> pr " %s = args.%s;\n" n n
6064 | FileIn _ | FileOut _ -> ()
6070 (* this is used at least for do_equal *)
6071 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6072 (* Emit NEED_ROOT just once, even when there are two or
6073 more Pathname args *)
6074 pr " NEED_ROOT (goto done);\n";
6077 (* Don't want to call the impl with any FileIn or FileOut
6078 * parameters, since these go "outside" the RPC protocol.
6081 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6083 pr " r = do_%s " name;
6084 generate_c_call_args (fst style, args');
6087 (match fst style with
6088 | RErr | RInt _ | RInt64 _ | RBool _
6089 | RConstString _ | RConstOptString _
6090 | RString _ | RStringList _ | RHashtable _
6091 | RStruct (_, _) | RStructList (_, _) ->
6092 pr " if (r == %s)\n" error_code;
6093 pr " /* do_%s has already called reply_with_error */\n" name;
6097 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6098 pr " * an ordinary zero-length buffer), so be careful ...\n";
6100 pr " if (size == 1 && r == %s)\n" error_code;
6101 pr " /* do_%s has already called reply_with_error */\n" name;
6106 (* If there are any FileOut parameters, then the impl must
6107 * send its own reply.
6110 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6112 pr " /* do_%s has already sent a reply */\n" name
6114 match fst style with
6115 | RErr -> pr " reply (NULL, NULL);\n"
6116 | RInt n | RInt64 n | RBool n ->
6117 pr " struct guestfs_%s_ret ret;\n" name;
6118 pr " ret.%s = r;\n" n;
6119 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6121 | RConstString _ | RConstOptString _ ->
6122 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6124 pr " struct guestfs_%s_ret ret;\n" name;
6125 pr " ret.%s = r;\n" n;
6126 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6129 | RStringList n | RHashtable n ->
6130 pr " struct guestfs_%s_ret ret;\n" name;
6131 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6132 pr " ret.%s.%s_val = r;\n" n n;
6133 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6135 pr " free_strings (r);\n"
6137 pr " struct guestfs_%s_ret ret;\n" name;
6138 pr " ret.%s = *r;\n" n;
6139 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6141 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6143 | RStructList (n, _) ->
6144 pr " struct guestfs_%s_ret ret;\n" name;
6145 pr " ret.%s = *r;\n" n;
6146 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6148 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6151 pr " struct guestfs_%s_ret ret;\n" name;
6152 pr " ret.%s.%s_val = r;\n" n n;
6153 pr " ret.%s.%s_len = size;\n" n n;
6154 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6159 (* Free the args. *)
6160 (match snd style with
6165 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6172 (* Dispatch function. *)
6173 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6175 pr " switch (proc_nr) {\n";
6178 fun (name, style, _, _, _, _, _) ->
6179 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6180 pr " %s_stub (xdr_in);\n" name;
6185 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";
6190 (* LVM columns and tokenization functions. *)
6191 (* XXX This generates crap code. We should rethink how we
6197 pr "static const char *lvm_%s_cols = \"%s\";\n"
6198 typ (String.concat "," (List.map fst cols));
6201 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6203 pr " char *tok, *p, *next;\n";
6207 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6210 pr " if (!str) {\n";
6211 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6214 pr " if (!*str || c_isspace (*str)) {\n";
6215 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6220 fun (name, coltype) ->
6221 pr " if (!tok) {\n";
6222 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6225 pr " p = strchrnul (tok, ',');\n";
6226 pr " if (*p) next = p+1; else next = NULL;\n";
6227 pr " *p = '\\0';\n";
6230 pr " r->%s = strdup (tok);\n" name;
6231 pr " if (r->%s == NULL) {\n" name;
6232 pr " perror (\"strdup\");\n";
6236 pr " for (i = j = 0; i < 32; ++j) {\n";
6237 pr " if (tok[j] == '\\0') {\n";
6238 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6240 pr " } else if (tok[j] != '-')\n";
6241 pr " r->%s[i++] = tok[j];\n" name;
6244 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6245 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6249 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6250 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6254 pr " if (tok[0] == '\\0')\n";
6255 pr " r->%s = -1;\n" name;
6256 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6257 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6260 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6261 assert false (* can never be an LVM column *)
6263 pr " tok = next;\n";
6266 pr " if (tok != NULL) {\n";
6267 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6274 pr "guestfs_int_lvm_%s_list *\n" typ;
6275 pr "parse_command_line_%ss (void)\n" typ;
6277 pr " char *out, *err;\n";
6278 pr " char *p, *pend;\n";
6280 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6281 pr " void *newp;\n";
6283 pr " ret = malloc (sizeof *ret);\n";
6284 pr " if (!ret) {\n";
6285 pr " reply_with_perror (\"malloc\");\n";
6286 pr " return NULL;\n";
6289 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6290 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6292 pr " r = command (&out, &err,\n";
6293 pr " \"lvm\", \"%ss\",\n" typ;
6294 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6295 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6296 pr " if (r == -1) {\n";
6297 pr " reply_with_error (\"%%s\", err);\n";
6298 pr " free (out);\n";
6299 pr " free (err);\n";
6300 pr " free (ret);\n";
6301 pr " return NULL;\n";
6304 pr " free (err);\n";
6306 pr " /* Tokenize each line of the output. */\n";
6309 pr " while (p) {\n";
6310 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6311 pr " if (pend) {\n";
6312 pr " *pend = '\\0';\n";
6316 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6319 pr " if (!*p) { /* Empty line? Skip it. */\n";
6324 pr " /* Allocate some space to store this next entry. */\n";
6325 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6326 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6327 pr " if (newp == NULL) {\n";
6328 pr " reply_with_perror (\"realloc\");\n";
6329 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6330 pr " free (ret);\n";
6331 pr " free (out);\n";
6332 pr " return NULL;\n";
6334 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6336 pr " /* Tokenize the next entry. */\n";
6337 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6338 pr " if (r == -1) {\n";
6339 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6340 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6341 pr " free (ret);\n";
6342 pr " free (out);\n";
6343 pr " return NULL;\n";
6350 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6352 pr " free (out);\n";
6353 pr " return ret;\n";
6356 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6358 (* Generate a list of function names, for debugging in the daemon.. *)
6359 and generate_daemon_names () =
6360 generate_header CStyle GPLv2plus;
6362 pr "#include <config.h>\n";
6364 pr "#include \"daemon.h\"\n";
6367 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6368 pr "const char *function_names[] = {\n";
6370 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6374 (* Generate the optional groups for the daemon to implement
6375 * guestfs_available.
6377 and generate_daemon_optgroups_c () =
6378 generate_header CStyle GPLv2plus;
6380 pr "#include <config.h>\n";
6382 pr "#include \"daemon.h\"\n";
6383 pr "#include \"optgroups.h\"\n";
6386 pr "struct optgroup optgroups[] = {\n";
6389 pr " { \"%s\", optgroup_%s_available },\n" group group
6391 pr " { NULL, NULL }\n";
6394 and generate_daemon_optgroups_h () =
6395 generate_header CStyle GPLv2plus;
6399 pr "extern int optgroup_%s_available (void);\n" group
6402 (* Generate the tests. *)
6403 and generate_tests () =
6404 generate_header CStyle GPLv2plus;
6411 #include <sys/types.h>
6414 #include \"guestfs.h\"
6415 #include \"guestfs-internal.h\"
6417 static guestfs_h *g;
6418 static int suppress_error = 0;
6420 static void print_error (guestfs_h *g, void *data, const char *msg)
6422 if (!suppress_error)
6423 fprintf (stderr, \"%%s\\n\", msg);
6426 /* FIXME: nearly identical code appears in fish.c */
6427 static void print_strings (char *const *argv)
6431 for (argc = 0; argv[argc] != NULL; ++argc)
6432 printf (\"\\t%%s\\n\", argv[argc]);
6436 static void print_table (char const *const *argv)
6440 for (i = 0; argv[i] != NULL; i += 2)
6441 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6447 (* Generate a list of commands which are not tested anywhere. *)
6448 pr "static void no_test_warnings (void)\n";
6451 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6453 fun (_, _, _, _, tests, _, _) ->
6454 let tests = filter_map (
6456 | (_, (Always|If _|Unless _), test) -> Some test
6457 | (_, Disabled, _) -> None
6459 let seq = List.concat (List.map seq_of_test tests) in
6460 let cmds_tested = List.map List.hd seq in
6461 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6465 fun (name, _, _, _, _, _, _) ->
6466 if not (Hashtbl.mem hash name) then
6467 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6473 (* Generate the actual tests. Note that we generate the tests
6474 * in reverse order, deliberately, so that (in general) the
6475 * newest tests run first. This makes it quicker and easier to
6480 fun (name, _, _, flags, tests, _, _) ->
6481 mapi (generate_one_test name flags) tests
6482 ) (List.rev all_functions) in
6483 let test_names = List.concat test_names in
6484 let nr_tests = List.length test_names in
6487 int main (int argc, char *argv[])
6490 unsigned long int n_failed = 0;
6491 const char *filename;
6493 int nr_tests, test_num = 0;
6495 setbuf (stdout, NULL);
6497 no_test_warnings ();
6499 g = guestfs_create ();
6501 printf (\"guestfs_create FAILED\\n\");
6502 exit (EXIT_FAILURE);
6505 guestfs_set_error_handler (g, print_error, NULL);
6507 guestfs_set_path (g, \"../appliance\");
6509 filename = \"test1.img\";
6510 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6513 exit (EXIT_FAILURE);
6515 if (lseek (fd, %d, SEEK_SET) == -1) {
6519 exit (EXIT_FAILURE);
6521 if (write (fd, &c, 1) == -1) {
6525 exit (EXIT_FAILURE);
6527 if (close (fd) == -1) {
6530 exit (EXIT_FAILURE);
6532 if (guestfs_add_drive (g, filename) == -1) {
6533 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6534 exit (EXIT_FAILURE);
6537 filename = \"test2.img\";
6538 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6541 exit (EXIT_FAILURE);
6543 if (lseek (fd, %d, SEEK_SET) == -1) {
6547 exit (EXIT_FAILURE);
6549 if (write (fd, &c, 1) == -1) {
6553 exit (EXIT_FAILURE);
6555 if (close (fd) == -1) {
6558 exit (EXIT_FAILURE);
6560 if (guestfs_add_drive (g, filename) == -1) {
6561 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6562 exit (EXIT_FAILURE);
6565 filename = \"test3.img\";
6566 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6569 exit (EXIT_FAILURE);
6571 if (lseek (fd, %d, SEEK_SET) == -1) {
6575 exit (EXIT_FAILURE);
6577 if (write (fd, &c, 1) == -1) {
6581 exit (EXIT_FAILURE);
6583 if (close (fd) == -1) {
6586 exit (EXIT_FAILURE);
6588 if (guestfs_add_drive (g, filename) == -1) {
6589 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6590 exit (EXIT_FAILURE);
6593 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6594 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6595 exit (EXIT_FAILURE);
6598 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6601 if (guestfs_launch (g) == -1) {
6602 printf (\"guestfs_launch FAILED\\n\");
6603 exit (EXIT_FAILURE);
6606 /* Cancel previous alarm. */
6611 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6615 pr " test_num++;\n";
6616 pr " if (guestfs_get_verbose (g))\n";
6617 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6618 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6619 pr " if (%s () == -1) {\n" test_name;
6620 pr " printf (\"%s FAILED\\n\");\n" test_name;
6621 pr " n_failed++;\n";
6626 pr " guestfs_close (g);\n";
6627 pr " unlink (\"test1.img\");\n";
6628 pr " unlink (\"test2.img\");\n";
6629 pr " unlink (\"test3.img\");\n";
6632 pr " if (n_failed > 0) {\n";
6633 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6634 pr " exit (EXIT_FAILURE);\n";
6638 pr " exit (EXIT_SUCCESS);\n";
6641 and generate_one_test name flags i (init, prereq, test) =
6642 let test_name = sprintf "test_%s_%d" name i in
6645 static int %s_skip (void)
6649 str = getenv (\"TEST_ONLY\");
6651 return strstr (str, \"%s\") == NULL;
6652 str = getenv (\"SKIP_%s\");
6653 if (str && STREQ (str, \"1\")) return 1;
6654 str = getenv (\"SKIP_TEST_%s\");
6655 if (str && STREQ (str, \"1\")) return 1;
6659 " test_name name (String.uppercase test_name) (String.uppercase name);
6662 | Disabled | Always -> ()
6663 | If code | Unless code ->
6664 pr "static int %s_prereq (void)\n" test_name;
6672 static int %s (void)
6675 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6679 " test_name test_name test_name;
6681 (* Optional functions should only be tested if the relevant
6682 * support is available in the daemon.
6688 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6690 pr " suppress_error = 1;\n";
6691 pr " r = guestfs_available (g, (char **) groups);\n";
6692 pr " suppress_error = 0;\n";
6693 pr " if (r == -1) {\n";
6694 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6703 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6705 pr " if (! %s_prereq ()) {\n" test_name;
6706 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6710 generate_one_test_body name i test_name init test;
6712 pr " if (%s_prereq ()) {\n" test_name;
6713 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6717 generate_one_test_body name i test_name init test;
6719 generate_one_test_body name i test_name init test
6727 and generate_one_test_body name i test_name init test =
6729 | InitNone (* XXX at some point, InitNone and InitEmpty became
6730 * folded together as the same thing. Really we should
6731 * make InitNone do nothing at all, but the tests may
6732 * need to be checked to make sure this is OK.
6735 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6736 List.iter (generate_test_command_call test_name)
6737 [["blockdev_setrw"; "/dev/sda"];
6741 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6742 List.iter (generate_test_command_call test_name)
6743 [["blockdev_setrw"; "/dev/sda"];
6746 ["part_disk"; "/dev/sda"; "mbr"]]
6748 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6749 List.iter (generate_test_command_call test_name)
6750 [["blockdev_setrw"; "/dev/sda"];
6753 ["part_disk"; "/dev/sda"; "mbr"];
6754 ["mkfs"; "ext2"; "/dev/sda1"];
6755 ["mount_options"; ""; "/dev/sda1"; "/"]]
6756 | InitBasicFSonLVM ->
6757 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6759 List.iter (generate_test_command_call test_name)
6760 [["blockdev_setrw"; "/dev/sda"];
6763 ["part_disk"; "/dev/sda"; "mbr"];
6764 ["pvcreate"; "/dev/sda1"];
6765 ["vgcreate"; "VG"; "/dev/sda1"];
6766 ["lvcreate"; "LV"; "VG"; "8"];
6767 ["mkfs"; "ext2"; "/dev/VG/LV"];
6768 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6770 pr " /* InitISOFS for %s */\n" test_name;
6771 List.iter (generate_test_command_call test_name)
6772 [["blockdev_setrw"; "/dev/sda"];
6775 ["mount_ro"; "/dev/sdd"; "/"]]
6778 let get_seq_last = function
6780 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6783 let seq = List.rev seq in
6784 List.rev (List.tl seq), List.hd seq
6789 pr " /* TestRun for %s (%d) */\n" name i;
6790 List.iter (generate_test_command_call test_name) seq
6791 | TestOutput (seq, expected) ->
6792 pr " /* TestOutput for %s (%d) */\n" name i;
6793 pr " const char *expected = \"%s\";\n" (c_quote expected);
6794 let seq, last = get_seq_last seq in
6796 pr " if (STRNEQ (r, expected)) {\n";
6797 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6801 List.iter (generate_test_command_call test_name) seq;
6802 generate_test_command_call ~test test_name last
6803 | TestOutputList (seq, expected) ->
6804 pr " /* TestOutputList for %s (%d) */\n" name i;
6805 let seq, last = get_seq_last seq in
6809 pr " if (!r[%d]) {\n" i;
6810 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6811 pr " print_strings (r);\n";
6815 pr " const char *expected = \"%s\";\n" (c_quote str);
6816 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6817 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6822 pr " if (r[%d] != NULL) {\n" (List.length expected);
6823 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6825 pr " print_strings (r);\n";
6829 List.iter (generate_test_command_call test_name) seq;
6830 generate_test_command_call ~test test_name last
6831 | TestOutputListOfDevices (seq, expected) ->
6832 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6833 let seq, last = get_seq_last seq in
6837 pr " if (!r[%d]) {\n" i;
6838 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6839 pr " print_strings (r);\n";
6843 pr " const char *expected = \"%s\";\n" (c_quote str);
6844 pr " r[%d][5] = 's';\n" i;
6845 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6846 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6851 pr " if (r[%d] != NULL) {\n" (List.length expected);
6852 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6854 pr " print_strings (r);\n";
6858 List.iter (generate_test_command_call test_name) seq;
6859 generate_test_command_call ~test test_name last
6860 | TestOutputInt (seq, expected) ->
6861 pr " /* TestOutputInt for %s (%d) */\n" name i;
6862 let seq, last = get_seq_last seq in
6864 pr " if (r != %d) {\n" expected;
6865 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6871 List.iter (generate_test_command_call test_name) seq;
6872 generate_test_command_call ~test test_name last
6873 | TestOutputIntOp (seq, op, expected) ->
6874 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6875 let seq, last = get_seq_last seq in
6877 pr " if (! (r %s %d)) {\n" op expected;
6878 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6879 test_name op expected;
6884 List.iter (generate_test_command_call test_name) seq;
6885 generate_test_command_call ~test test_name last
6886 | TestOutputTrue seq ->
6887 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6888 let seq, last = get_seq_last seq in
6891 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6896 List.iter (generate_test_command_call test_name) seq;
6897 generate_test_command_call ~test test_name last
6898 | TestOutputFalse seq ->
6899 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6900 let seq, last = get_seq_last seq in
6903 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6908 List.iter (generate_test_command_call test_name) seq;
6909 generate_test_command_call ~test test_name last
6910 | TestOutputLength (seq, expected) ->
6911 pr " /* TestOutputLength for %s (%d) */\n" name i;
6912 let seq, last = get_seq_last seq in
6915 pr " for (j = 0; j < %d; ++j)\n" expected;
6916 pr " if (r[j] == NULL) {\n";
6917 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6919 pr " print_strings (r);\n";
6922 pr " if (r[j] != NULL) {\n";
6923 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6925 pr " print_strings (r);\n";
6929 List.iter (generate_test_command_call test_name) seq;
6930 generate_test_command_call ~test test_name last
6931 | TestOutputBuffer (seq, expected) ->
6932 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6933 pr " const char *expected = \"%s\";\n" (c_quote expected);
6934 let seq, last = get_seq_last seq in
6935 let len = String.length expected in
6937 pr " if (size != %d) {\n" len;
6938 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6941 pr " if (STRNEQLEN (r, expected, size)) {\n";
6942 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6946 List.iter (generate_test_command_call test_name) seq;
6947 generate_test_command_call ~test test_name last
6948 | TestOutputStruct (seq, checks) ->
6949 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6950 let seq, last = get_seq_last seq in
6954 | CompareWithInt (field, expected) ->
6955 pr " if (r->%s != %d) {\n" field expected;
6956 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6957 test_name field expected;
6958 pr " (int) r->%s);\n" field;
6961 | CompareWithIntOp (field, op, expected) ->
6962 pr " if (!(r->%s %s %d)) {\n" field op expected;
6963 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6964 test_name field op expected;
6965 pr " (int) r->%s);\n" field;
6968 | CompareWithString (field, expected) ->
6969 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6970 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6971 test_name field expected;
6972 pr " r->%s);\n" field;
6975 | CompareFieldsIntEq (field1, field2) ->
6976 pr " if (r->%s != r->%s) {\n" field1 field2;
6977 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6978 test_name field1 field2;
6979 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6982 | CompareFieldsStrEq (field1, field2) ->
6983 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6984 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6985 test_name field1 field2;
6986 pr " r->%s, r->%s);\n" field1 field2;
6991 List.iter (generate_test_command_call test_name) seq;
6992 generate_test_command_call ~test test_name last
6993 | TestLastFail seq ->
6994 pr " /* TestLastFail for %s (%d) */\n" name i;
6995 let seq, last = get_seq_last seq in
6996 List.iter (generate_test_command_call test_name) seq;
6997 generate_test_command_call test_name ~expect_error:true last
6999 (* Generate the code to run a command, leaving the result in 'r'.
7000 * If you expect to get an error then you should set expect_error:true.
7002 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7004 | [] -> assert false
7006 (* Look up the command to find out what args/ret it has. *)
7009 let _, style, _, _, _, _, _ =
7010 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7013 failwithf "%s: in test, command %s was not found" test_name name in
7015 if List.length (snd style) <> List.length args then
7016 failwithf "%s: in test, wrong number of args given to %s"
7023 | OptString n, "NULL" -> ()
7026 | Dev_or_Path n, arg
7028 | OptString n, arg ->
7029 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7033 | FileIn _, _ | FileOut _, _ -> ()
7034 | StringList n, "" | DeviceList n, "" ->
7035 pr " const char *const %s[1] = { NULL };\n" n
7036 | StringList n, arg | DeviceList n, arg ->
7037 let strs = string_split " " arg in
7040 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7042 pr " const char *const %s[] = {\n" n;
7044 fun i _ -> pr " %s_%d,\n" n i
7048 ) (List.combine (snd style) args);
7051 match fst style with
7052 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7053 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7054 | RConstString _ | RConstOptString _ ->
7055 pr " const char *r;\n"; "NULL"
7056 | RString _ -> pr " char *r;\n"; "NULL"
7057 | RStringList _ | RHashtable _ ->
7061 | RStruct (_, typ) ->
7062 pr " struct guestfs_%s *r;\n" typ; "NULL"
7063 | RStructList (_, typ) ->
7064 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7067 pr " size_t size;\n";
7070 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7071 pr " r = guestfs_%s (g" name;
7073 (* Generate the parameters. *)
7076 | OptString _, "NULL" -> pr ", NULL"
7078 | Device n, _ | Dev_or_Path n, _
7082 | FileIn _, arg | FileOut _, arg ->
7083 pr ", \"%s\"" (c_quote arg)
7084 | StringList n, _ | DeviceList n, _ ->
7085 pr ", (char **) %s" n
7088 try int_of_string arg
7089 with Failure "int_of_string" ->
7090 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7094 try Int64.of_string arg
7095 with Failure "int_of_string" ->
7096 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7099 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7100 ) (List.combine (snd style) args);
7102 (match fst style with
7103 | RBufferOut _ -> pr ", &size"
7109 if not expect_error then
7110 pr " if (r == %s)\n" error_code
7112 pr " if (r != %s)\n" error_code;
7115 (* Insert the test code. *)
7121 (match fst style with
7122 | RErr | RInt _ | RInt64 _ | RBool _
7123 | RConstString _ | RConstOptString _ -> ()
7124 | RString _ | RBufferOut _ -> pr " free (r);\n"
7125 | RStringList _ | RHashtable _ ->
7126 pr " for (i = 0; r[i] != NULL; ++i)\n";
7127 pr " free (r[i]);\n";
7129 | RStruct (_, typ) ->
7130 pr " guestfs_free_%s (r);\n" typ
7131 | RStructList (_, typ) ->
7132 pr " guestfs_free_%s_list (r);\n" typ
7138 let str = replace_str str "\r" "\\r" in
7139 let str = replace_str str "\n" "\\n" in
7140 let str = replace_str str "\t" "\\t" in
7141 let str = replace_str str "\000" "\\0" in
7144 (* Generate a lot of different functions for guestfish. *)
7145 and generate_fish_cmds () =
7146 generate_header CStyle GPLv2plus;
7150 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7152 let all_functions_sorted =
7154 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7155 ) all_functions_sorted in
7157 pr "#include <config.h>\n";
7159 pr "#include <stdio.h>\n";
7160 pr "#include <stdlib.h>\n";
7161 pr "#include <string.h>\n";
7162 pr "#include <inttypes.h>\n";
7164 pr "#include <guestfs.h>\n";
7165 pr "#include \"c-ctype.h\"\n";
7166 pr "#include \"full-write.h\"\n";
7167 pr "#include \"xstrtol.h\"\n";
7168 pr "#include \"fish.h\"\n";
7171 (* list_commands function, which implements guestfish -h *)
7172 pr "void list_commands (void)\n";
7174 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7175 pr " list_builtin_commands ();\n";
7177 fun (name, _, _, flags, _, shortdesc, _) ->
7178 let name = replace_char name '_' '-' in
7179 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7181 ) all_functions_sorted;
7182 pr " printf (\" %%s\\n\",";
7183 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7187 (* display_command function, which implements guestfish -h cmd *)
7188 pr "void display_command (const char *cmd)\n";
7191 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7192 let name2 = replace_char name '_' '-' in
7194 try find_map (function FishAlias n -> Some n | _ -> None) flags
7195 with Not_found -> name in
7196 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7198 match snd style with
7202 name2 (String.concat " " (List.map name_of_argt args)) in
7205 if List.mem ProtocolLimitWarning flags then
7206 ("\n\n" ^ protocol_limit_warning)
7209 (* For DangerWillRobinson commands, we should probably have
7210 * guestfish prompt before allowing you to use them (especially
7211 * in interactive mode). XXX
7215 if List.mem DangerWillRobinson flags then
7216 ("\n\n" ^ danger_will_robinson)
7221 match deprecation_notice flags with
7223 | Some txt -> "\n\n" ^ txt in
7225 let describe_alias =
7226 if name <> alias then
7227 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7231 pr "STRCASEEQ (cmd, \"%s\")" name;
7232 if name <> name2 then
7233 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7234 if name <> alias then
7235 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7237 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7239 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7240 "=head1 DESCRIPTION\n\n" ^
7241 longdesc ^ warnings ^ describe_alias);
7244 pr " display_builtin_command (cmd);\n";
7248 let emit_print_list_function typ =
7249 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7252 pr " unsigned int i;\n";
7254 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7255 pr " printf (\"[%%d] = {\\n\", i);\n";
7256 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7257 pr " printf (\"}\\n\");\n";
7263 (* print_* functions *)
7267 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7269 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7272 pr " unsigned int i;\n";
7278 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7280 pr " printf (\"%%s%s: \", indent);\n" name;
7281 pr " for (i = 0; i < 32; ++i)\n";
7282 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7283 pr " printf (\"\\n\");\n"
7285 pr " printf (\"%%s%s: \", indent);\n" name;
7286 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7287 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7288 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7290 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7291 pr " printf (\"\\n\");\n"
7292 | name, (FUInt64|FBytes) ->
7293 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7296 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7299 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7302 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7305 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7307 | name, FOptPercent ->
7308 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7309 typ name name typ name;
7310 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7316 (* Emit a print_TYPE_list function definition only if that function is used. *)
7319 | typ, (RStructListOnly | RStructAndList) ->
7320 (* generate the function for typ *)
7321 emit_print_list_function typ
7322 | typ, _ -> () (* empty *)
7323 ) (rstructs_used_by all_functions);
7325 (* Emit a print_TYPE function definition only if that function is used. *)
7328 | typ, (RStructOnly | RStructAndList) ->
7329 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7331 pr " print_%s_indent (%s, \"\");\n" typ typ;
7334 | typ, _ -> () (* empty *)
7335 ) (rstructs_used_by all_functions);
7337 (* run_<action> actions *)
7339 fun (name, style, _, flags, _, _, _) ->
7340 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7342 (match fst style with
7345 | RBool _ -> pr " int r;\n"
7346 | RInt64 _ -> pr " int64_t r;\n"
7347 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7348 | RString _ -> pr " char *r;\n"
7349 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7350 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7351 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7354 pr " size_t size;\n";
7362 | FileOut n -> pr " const char *%s;\n" n
7364 | Dev_or_Path n -> pr " char *%s;\n" n
7365 | StringList n | DeviceList n -> pr " char **%s;\n" n
7366 | Bool n -> pr " int %s;\n" n
7367 | Int n -> pr " int %s;\n" n
7368 | Int64 n -> pr " int64_t %s;\n" n
7371 (* Check and convert parameters. *)
7372 let argc_expected = List.length (snd style) in
7373 pr " if (argc != %d) {\n" argc_expected;
7374 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7376 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7380 let parse_integer fn fntyp rtyp range name i =
7382 pr " strtol_error xerr;\n";
7383 pr " %s r;\n" fntyp;
7385 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7386 pr " if (xerr != LONGINT_OK) {\n";
7387 pr " fprintf (stderr,\n";
7388 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7389 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7394 | Some (min, max, comment) ->
7395 pr " /* %s */\n" comment;
7396 pr " if (r < %s || r > %s) {\n" min max;
7397 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7401 pr " /* The check above should ensure this assignment does not overflow. */\n";
7403 pr " %s = r;\n" name;
7412 pr " %s = argv[%d];\n" name i
7414 | Dev_or_Path name ->
7415 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7416 pr " if (%s == NULL) return -1;\n" name
7418 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7421 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7424 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7426 | StringList name | DeviceList name ->
7427 pr " %s = parse_string_list (argv[%d]);\n" name i;
7428 pr " if (%s == NULL) return -1;\n" name;
7430 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7433 let min = "(-(2LL<<30))"
7434 and max = "((2LL<<30)-1)"
7436 "The Int type in the generator is a signed 31 bit int." in
7437 Some (min, max, comment) in
7438 parse_integer "xstrtoll" "long long" "int" range name i
7440 parse_integer "xstrtoll" "long long" "int64_t" None name i
7443 (* Call C API function. *)
7445 try find_map (function FishAction n -> Some n | _ -> None) flags
7446 with Not_found -> sprintf "guestfs_%s" name in
7448 generate_c_call_args ~handle:"g" style;
7453 | Device name | String name
7454 | OptString name | FileIn name | FileOut name | Bool name
7455 | Int name | Int64 name -> ()
7456 | Pathname name | Dev_or_Path name ->
7457 pr " free (%s);\n" name
7458 | StringList name | DeviceList name ->
7459 pr " free_strings (%s);\n" name
7462 (* Check return value for errors and display command results. *)
7463 (match fst style with
7464 | RErr -> pr " return r;\n"
7466 pr " if (r == -1) return -1;\n";
7467 pr " printf (\"%%d\\n\", r);\n";
7470 pr " if (r == -1) return -1;\n";
7471 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7474 pr " if (r == -1) return -1;\n";
7475 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7478 pr " if (r == NULL) return -1;\n";
7479 pr " printf (\"%%s\\n\", r);\n";
7481 | RConstOptString _ ->
7482 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7485 pr " if (r == NULL) return -1;\n";
7486 pr " printf (\"%%s\\n\", r);\n";
7490 pr " if (r == NULL) return -1;\n";
7491 pr " print_strings (r);\n";
7492 pr " free_strings (r);\n";
7494 | RStruct (_, typ) ->
7495 pr " if (r == NULL) return -1;\n";
7496 pr " print_%s (r);\n" typ;
7497 pr " guestfs_free_%s (r);\n" typ;
7499 | RStructList (_, typ) ->
7500 pr " if (r == NULL) return -1;\n";
7501 pr " print_%s_list (r);\n" typ;
7502 pr " guestfs_free_%s_list (r);\n" typ;
7505 pr " if (r == NULL) return -1;\n";
7506 pr " print_table (r);\n";
7507 pr " free_strings (r);\n";
7510 pr " if (r == NULL) return -1;\n";
7511 pr " if (full_write (1, r, size) != size) {\n";
7512 pr " perror (\"write\");\n";
7523 (* run_action function *)
7524 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7527 fun (name, _, _, flags, _, _, _) ->
7528 let name2 = replace_char name '_' '-' in
7530 try find_map (function FishAlias n -> Some n | _ -> None) flags
7531 with Not_found -> name in
7533 pr "STRCASEEQ (cmd, \"%s\")" name;
7534 if name <> name2 then
7535 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7536 if name <> alias then
7537 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7539 pr " return run_%s (cmd, argc, argv);\n" name;
7543 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7544 pr " if (command_num == 1)\n";
7545 pr " extended_help_message ();\n";
7552 (* Readline completion for guestfish. *)
7553 and generate_fish_completion () =
7554 generate_header CStyle GPLv2plus;
7558 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7568 #ifdef HAVE_LIBREADLINE
7569 #include <readline/readline.h>
7574 #ifdef HAVE_LIBREADLINE
7576 static const char *const commands[] = {
7577 BUILTIN_COMMANDS_FOR_COMPLETION,
7580 (* Get the commands, including the aliases. They don't need to be
7581 * sorted - the generator() function just does a dumb linear search.
7585 fun (name, _, _, flags, _, _, _) ->
7586 let name2 = replace_char name '_' '-' in
7588 try find_map (function FishAlias n -> Some n | _ -> None) flags
7589 with Not_found -> name in
7591 if name <> alias then [name2; alias] else [name2]
7593 let commands = List.flatten commands in
7595 List.iter (pr " \"%s\",\n") commands;
7601 generator (const char *text, int state)
7603 static int index, len;
7608 len = strlen (text);
7611 rl_attempted_completion_over = 1;
7613 while ((name = commands[index]) != NULL) {
7615 if (STRCASEEQLEN (name, text, len))
7616 return strdup (name);
7622 #endif /* HAVE_LIBREADLINE */
7624 #ifdef HAVE_RL_COMPLETION_MATCHES
7625 #define RL_COMPLETION_MATCHES rl_completion_matches
7627 #ifdef HAVE_COMPLETION_MATCHES
7628 #define RL_COMPLETION_MATCHES completion_matches
7630 #endif /* else just fail if we don't have either symbol */
7633 do_completion (const char *text, int start, int end)
7635 char **matches = NULL;
7637 #ifdef HAVE_LIBREADLINE
7638 rl_completion_append_character = ' ';
7641 matches = RL_COMPLETION_MATCHES (text, generator);
7642 else if (complete_dest_paths)
7643 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7650 (* Generate the POD documentation for guestfish. *)
7651 and generate_fish_actions_pod () =
7652 let all_functions_sorted =
7654 fun (_, _, _, flags, _, _, _) ->
7655 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7656 ) all_functions_sorted in
7658 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7661 fun (name, style, _, flags, _, _, longdesc) ->
7663 Str.global_substitute rex (
7666 try Str.matched_group 1 s
7668 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7669 "C<" ^ replace_char sub '_' '-' ^ ">"
7671 let name = replace_char name '_' '-' in
7673 try find_map (function FishAlias n -> Some n | _ -> None) flags
7674 with Not_found -> name in
7676 pr "=head2 %s" name;
7677 if name <> alias then
7684 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7685 | OptString n -> pr " %s" n
7686 | StringList n | DeviceList n -> pr " '%s ...'" n
7687 | Bool _ -> pr " true|false"
7688 | Int n -> pr " %s" n
7689 | Int64 n -> pr " %s" n
7690 | FileIn n | FileOut n -> pr " (%s|-)" n
7694 pr "%s\n\n" longdesc;
7696 if List.exists (function FileIn _ | FileOut _ -> true
7697 | _ -> false) (snd style) then
7698 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7700 if List.mem ProtocolLimitWarning flags then
7701 pr "%s\n\n" protocol_limit_warning;
7703 if List.mem DangerWillRobinson flags then
7704 pr "%s\n\n" danger_will_robinson;
7706 match deprecation_notice flags with
7708 | Some txt -> pr "%s\n\n" txt
7709 ) all_functions_sorted
7711 (* Generate a C function prototype. *)
7712 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7713 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7715 ?handle name style =
7716 if extern then pr "extern ";
7717 if static then pr "static ";
7718 (match fst style with
7720 | RInt _ -> pr "int "
7721 | RInt64 _ -> pr "int64_t "
7722 | RBool _ -> pr "int "
7723 | RConstString _ | RConstOptString _ -> pr "const char *"
7724 | RString _ | RBufferOut _ -> pr "char *"
7725 | RStringList _ | RHashtable _ -> pr "char **"
7726 | RStruct (_, typ) ->
7727 if not in_daemon then pr "struct guestfs_%s *" typ
7728 else pr "guestfs_int_%s *" typ
7729 | RStructList (_, typ) ->
7730 if not in_daemon then pr "struct guestfs_%s_list *" typ
7731 else pr "guestfs_int_%s_list *" typ
7733 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7734 pr "%s%s (" prefix name;
7735 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7738 let comma = ref false in
7741 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7745 if single_line then pr ", " else pr ",\n\t\t"
7752 | Device n | Dev_or_Path n
7756 pr "const char *%s" n
7757 | StringList n | DeviceList n ->
7759 pr "char *const *%s" n
7760 | Bool n -> next (); pr "int %s" n
7761 | Int n -> next (); pr "int %s" n
7762 | Int64 n -> next (); pr "int64_t %s" n
7765 if not in_daemon then (next (); pr "const char *%s" n)
7767 if is_RBufferOut then (next (); pr "size_t *size_r");
7770 if semicolon then pr ";";
7771 if newline then pr "\n"
7773 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7774 and generate_c_call_args ?handle ?(decl = false) style =
7776 let comma = ref false in
7778 if !comma then pr ", ";
7783 | Some handle -> pr "%s" handle; comma := true
7788 pr "%s" (name_of_argt arg)
7790 (* For RBufferOut calls, add implicit &size parameter. *)
7792 match fst style with
7800 (* Generate the OCaml bindings interface. *)
7801 and generate_ocaml_mli () =
7802 generate_header OCamlStyle LGPLv2plus;
7805 (** For API documentation you should refer to the C API
7806 in the guestfs(3) manual page. The OCaml API uses almost
7807 exactly the same calls. *)
7810 (** A [guestfs_h] handle. *)
7812 exception Error of string
7813 (** This exception is raised when there is an error. *)
7815 exception Handle_closed of string
7816 (** This exception is raised if you use a {!Guestfs.t} handle
7817 after calling {!close} on it. The string is the name of
7820 val create : unit -> t
7821 (** Create a {!Guestfs.t} handle. *)
7823 val close : t -> unit
7824 (** Close the {!Guestfs.t} handle and free up all resources used
7827 Handles are closed by the garbage collector when they become
7828 unreferenced, but callers can call this in order to provide
7829 predictable cleanup. *)
7832 generate_ocaml_structure_decls ();
7836 fun (name, style, _, _, _, shortdesc, _) ->
7837 generate_ocaml_prototype name style;
7838 pr "(** %s *)\n" shortdesc;
7840 ) all_functions_sorted
7842 (* Generate the OCaml bindings implementation. *)
7843 and generate_ocaml_ml () =
7844 generate_header OCamlStyle LGPLv2plus;
7849 exception Error of string
7850 exception Handle_closed of string
7852 external create : unit -> t = \"ocaml_guestfs_create\"
7853 external close : t -> unit = \"ocaml_guestfs_close\"
7855 (* Give the exceptions names, so they can be raised from the C code. *)
7857 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7858 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7862 generate_ocaml_structure_decls ();
7866 fun (name, style, _, _, _, shortdesc, _) ->
7867 generate_ocaml_prototype ~is_external:true name style;
7868 ) all_functions_sorted
7870 (* Generate the OCaml bindings C implementation. *)
7871 and generate_ocaml_c () =
7872 generate_header CStyle LGPLv2plus;
7879 #include <caml/config.h>
7880 #include <caml/alloc.h>
7881 #include <caml/callback.h>
7882 #include <caml/fail.h>
7883 #include <caml/memory.h>
7884 #include <caml/mlvalues.h>
7885 #include <caml/signals.h>
7887 #include <guestfs.h>
7889 #include \"guestfs_c.h\"
7891 /* Copy a hashtable of string pairs into an assoc-list. We return
7892 * the list in reverse order, but hashtables aren't supposed to be
7895 static CAMLprim value
7896 copy_table (char * const * argv)
7899 CAMLlocal5 (rv, pairv, kv, vv, cons);
7903 for (i = 0; argv[i] != NULL; i += 2) {
7904 kv = caml_copy_string (argv[i]);
7905 vv = caml_copy_string (argv[i+1]);
7906 pairv = caml_alloc (2, 0);
7907 Store_field (pairv, 0, kv);
7908 Store_field (pairv, 1, vv);
7909 cons = caml_alloc (2, 0);
7910 Store_field (cons, 1, rv);
7912 Store_field (cons, 0, pairv);
7920 (* Struct copy functions. *)
7922 let emit_ocaml_copy_list_function typ =
7923 pr "static CAMLprim value\n";
7924 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7926 pr " CAMLparam0 ();\n";
7927 pr " CAMLlocal2 (rv, v);\n";
7928 pr " unsigned int i;\n";
7930 pr " if (%ss->len == 0)\n" typ;
7931 pr " CAMLreturn (Atom (0));\n";
7933 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7934 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7935 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7936 pr " caml_modify (&Field (rv, i), v);\n";
7938 pr " CAMLreturn (rv);\n";
7946 let has_optpercent_col =
7947 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7949 pr "static CAMLprim value\n";
7950 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7952 pr " CAMLparam0 ();\n";
7953 if has_optpercent_col then
7954 pr " CAMLlocal3 (rv, v, v2);\n"
7956 pr " CAMLlocal2 (rv, v);\n";
7958 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7963 pr " v = caml_copy_string (%s->%s);\n" typ name
7965 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7966 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7969 pr " v = caml_alloc_string (32);\n";
7970 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7971 | name, (FBytes|FInt64|FUInt64) ->
7972 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7973 | name, (FInt32|FUInt32) ->
7974 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7975 | name, FOptPercent ->
7976 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7977 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7978 pr " v = caml_alloc (1, 0);\n";
7979 pr " Store_field (v, 0, v2);\n";
7980 pr " } else /* None */\n";
7981 pr " v = Val_int (0);\n";
7983 pr " v = Val_int (%s->%s);\n" typ name
7985 pr " Store_field (rv, %d, v);\n" i
7987 pr " CAMLreturn (rv);\n";
7992 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7995 | typ, (RStructListOnly | RStructAndList) ->
7996 (* generate the function for typ *)
7997 emit_ocaml_copy_list_function typ
7998 | typ, _ -> () (* empty *)
7999 ) (rstructs_used_by all_functions);
8003 fun (name, style, _, _, _, _, _) ->
8004 pr "/* Automatically generated wrapper for function\n";
8006 generate_ocaml_prototype name style;
8011 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8013 let needs_extra_vs =
8014 match fst style with RConstOptString _ -> true | _ -> false in
8016 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8017 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8018 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8021 pr "CAMLprim value\n";
8022 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8023 List.iter (pr ", value %s") (List.tl params);
8028 | [p1; p2; p3; p4; p5] ->
8029 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8030 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8031 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8032 pr " CAMLxparam%d (%s);\n"
8033 (List.length rest) (String.concat ", " rest)
8035 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8037 if not needs_extra_vs then
8038 pr " CAMLlocal1 (rv);\n"
8040 pr " CAMLlocal3 (rv, v, v2);\n";
8043 pr " guestfs_h *g = Guestfs_val (gv);\n";
8044 pr " if (g == NULL)\n";
8045 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8051 | Device n | Dev_or_Path n
8055 pr " const char *%s = String_val (%sv);\n" n n
8057 pr " const char *%s =\n" n;
8058 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8060 | StringList n | DeviceList n ->
8061 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8063 pr " int %s = Bool_val (%sv);\n" n n
8065 pr " int %s = Int_val (%sv);\n" n n
8067 pr " int64_t %s = Int64_val (%sv);\n" n n
8070 match fst style with
8071 | RErr -> pr " int r;\n"; "-1"
8072 | RInt _ -> pr " int r;\n"; "-1"
8073 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8074 | RBool _ -> pr " int r;\n"; "-1"
8075 | RConstString _ | RConstOptString _ ->
8076 pr " const char *r;\n"; "NULL"
8077 | RString _ -> pr " char *r;\n"; "NULL"
8082 | RStruct (_, typ) ->
8083 pr " struct guestfs_%s *r;\n" typ; "NULL"
8084 | RStructList (_, typ) ->
8085 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8092 pr " size_t size;\n";
8096 pr " caml_enter_blocking_section ();\n";
8097 pr " r = guestfs_%s " name;
8098 generate_c_call_args ~handle:"g" style;
8100 pr " caml_leave_blocking_section ();\n";
8104 | StringList n | DeviceList n ->
8105 pr " ocaml_guestfs_free_strings (%s);\n" n;
8106 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8107 | Bool _ | Int _ | Int64 _
8108 | FileIn _ | FileOut _ -> ()
8111 pr " if (r == %s)\n" error_code;
8112 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8115 (match fst style with
8116 | RErr -> pr " rv = Val_unit;\n"
8117 | RInt _ -> pr " rv = Val_int (r);\n"
8119 pr " rv = caml_copy_int64 (r);\n"
8120 | RBool _ -> pr " rv = Val_bool (r);\n"
8122 pr " rv = caml_copy_string (r);\n"
8123 | RConstOptString _ ->
8124 pr " if (r) { /* Some string */\n";
8125 pr " v = caml_alloc (1, 0);\n";
8126 pr " v2 = caml_copy_string (r);\n";
8127 pr " Store_field (v, 0, v2);\n";
8128 pr " } else /* None */\n";
8129 pr " v = Val_int (0);\n";
8131 pr " rv = caml_copy_string (r);\n";
8134 pr " rv = caml_copy_string_array ((const char **) r);\n";
8135 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8137 | RStruct (_, typ) ->
8138 pr " rv = copy_%s (r);\n" typ;
8139 pr " guestfs_free_%s (r);\n" typ;
8140 | RStructList (_, typ) ->
8141 pr " rv = copy_%s_list (r);\n" typ;
8142 pr " guestfs_free_%s_list (r);\n" typ;
8144 pr " rv = copy_table (r);\n";
8145 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8148 pr " rv = caml_alloc_string (size);\n";
8149 pr " memcpy (String_val (rv), r, size);\n";
8152 pr " CAMLreturn (rv);\n";
8156 if List.length params > 5 then (
8157 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8158 pr "CAMLprim value ";
8159 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8160 pr "CAMLprim value\n";
8161 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8163 pr " return ocaml_guestfs_%s (argv[0]" name;
8164 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8169 ) all_functions_sorted
8171 and generate_ocaml_structure_decls () =
8174 pr "type %s = {\n" typ;
8177 | name, FString -> pr " %s : string;\n" name
8178 | name, FBuffer -> pr " %s : string;\n" name
8179 | name, FUUID -> pr " %s : string;\n" name
8180 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8181 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8182 | name, FChar -> pr " %s : char;\n" name
8183 | name, FOptPercent -> pr " %s : float option;\n" name
8189 and generate_ocaml_prototype ?(is_external = false) name style =
8190 if is_external then pr "external " else pr "val ";
8191 pr "%s : t -> " name;
8194 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8195 | OptString _ -> pr "string option -> "
8196 | StringList _ | DeviceList _ -> pr "string array -> "
8197 | Bool _ -> pr "bool -> "
8198 | Int _ -> pr "int -> "
8199 | Int64 _ -> pr "int64 -> "
8201 (match fst style with
8202 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8203 | RInt _ -> pr "int"
8204 | RInt64 _ -> pr "int64"
8205 | RBool _ -> pr "bool"
8206 | RConstString _ -> pr "string"
8207 | RConstOptString _ -> pr "string option"
8208 | RString _ | RBufferOut _ -> pr "string"
8209 | RStringList _ -> pr "string array"
8210 | RStruct (_, typ) -> pr "%s" typ
8211 | RStructList (_, typ) -> pr "%s array" typ
8212 | RHashtable _ -> pr "(string * string) list"
8214 if is_external then (
8216 if List.length (snd style) + 1 > 5 then
8217 pr "\"ocaml_guestfs_%s_byte\" " name;
8218 pr "\"ocaml_guestfs_%s\"" name
8222 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8223 and generate_perl_xs () =
8224 generate_header CStyle LGPLv2plus;
8227 #include \"EXTERN.h\"
8231 #include <guestfs.h>
8234 #define PRId64 \"lld\"
8238 my_newSVll(long long val) {
8239 #ifdef USE_64_BIT_ALL
8240 return newSViv(val);
8244 len = snprintf(buf, 100, \"%%\" PRId64, val);
8245 return newSVpv(buf, len);
8250 #define PRIu64 \"llu\"
8254 my_newSVull(unsigned long long val) {
8255 #ifdef USE_64_BIT_ALL
8256 return newSVuv(val);
8260 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8261 return newSVpv(buf, len);
8265 /* http://www.perlmonks.org/?node_id=680842 */
8267 XS_unpack_charPtrPtr (SV *arg) {
8272 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8273 croak (\"array reference expected\");
8275 av = (AV *)SvRV (arg);
8276 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8278 croak (\"malloc failed\");
8280 for (i = 0; i <= av_len (av); i++) {
8281 SV **elem = av_fetch (av, i, 0);
8283 if (!elem || !*elem)
8284 croak (\"missing element in list\");
8286 ret[i] = SvPV_nolen (*elem);
8294 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8301 RETVAL = guestfs_create ();
8303 croak (\"could not create guestfs handle\");
8304 guestfs_set_error_handler (RETVAL, NULL, NULL);
8317 fun (name, style, _, _, _, _, _) ->
8318 (match fst style with
8319 | RErr -> pr "void\n"
8320 | RInt _ -> pr "SV *\n"
8321 | RInt64 _ -> pr "SV *\n"
8322 | RBool _ -> pr "SV *\n"
8323 | RConstString _ -> pr "SV *\n"
8324 | RConstOptString _ -> pr "SV *\n"
8325 | RString _ -> pr "SV *\n"
8326 | RBufferOut _ -> pr "SV *\n"
8328 | RStruct _ | RStructList _
8330 pr "void\n" (* all lists returned implictly on the stack *)
8332 (* Call and arguments. *)
8334 generate_c_call_args ~handle:"g" ~decl:true style;
8336 pr " guestfs_h *g;\n";
8340 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8343 (* http://www.perlmonks.org/?node_id=554277
8344 * Note that the implicit handle argument means we have
8345 * to add 1 to the ST(x) operator.
8347 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8348 | StringList n | DeviceList n -> pr " char **%s;\n" n
8349 | Bool n -> pr " int %s;\n" n
8350 | Int n -> pr " int %s;\n" n
8351 | Int64 n -> pr " int64_t %s;\n" n
8354 let do_cleanups () =
8357 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8358 | Bool _ | Int _ | Int64 _
8359 | FileIn _ | FileOut _ -> ()
8360 | StringList n | DeviceList n -> pr " free (%s);\n" n
8365 (match fst style with
8370 pr " r = guestfs_%s " name;
8371 generate_c_call_args ~handle:"g" style;
8374 pr " if (r == -1)\n";
8375 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8381 pr " %s = guestfs_%s " n name;
8382 generate_c_call_args ~handle:"g" style;
8385 pr " if (%s == -1)\n" n;
8386 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8387 pr " RETVAL = newSViv (%s);\n" n;
8392 pr " int64_t %s;\n" n;
8394 pr " %s = guestfs_%s " n name;
8395 generate_c_call_args ~handle:"g" style;
8398 pr " if (%s == -1)\n" n;
8399 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8400 pr " RETVAL = my_newSVll (%s);\n" n;
8405 pr " const char *%s;\n" n;
8407 pr " %s = guestfs_%s " n name;
8408 generate_c_call_args ~handle:"g" style;
8411 pr " if (%s == NULL)\n" n;
8412 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8413 pr " RETVAL = newSVpv (%s, 0);\n" n;
8416 | RConstOptString n ->
8418 pr " const char *%s;\n" n;
8420 pr " %s = guestfs_%s " n name;
8421 generate_c_call_args ~handle:"g" style;
8424 pr " if (%s == NULL)\n" n;
8425 pr " RETVAL = &PL_sv_undef;\n";
8427 pr " RETVAL = newSVpv (%s, 0);\n" n;
8432 pr " char *%s;\n" n;
8434 pr " %s = guestfs_%s " n name;
8435 generate_c_call_args ~handle:"g" style;
8438 pr " if (%s == NULL)\n" n;
8439 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8440 pr " RETVAL = newSVpv (%s, 0);\n" n;
8441 pr " free (%s);\n" n;
8444 | RStringList n | RHashtable n ->
8446 pr " char **%s;\n" n;
8449 pr " %s = guestfs_%s " n name;
8450 generate_c_call_args ~handle:"g" style;
8453 pr " if (%s == NULL)\n" n;
8454 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8455 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8456 pr " EXTEND (SP, n);\n";
8457 pr " for (i = 0; i < n; ++i) {\n";
8458 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8459 pr " free (%s[i]);\n" n;
8461 pr " free (%s);\n" n;
8462 | RStruct (n, typ) ->
8463 let cols = cols_of_struct typ in
8464 generate_perl_struct_code typ cols name style n do_cleanups
8465 | RStructList (n, typ) ->
8466 let cols = cols_of_struct typ in
8467 generate_perl_struct_list_code typ cols name style n do_cleanups
8470 pr " char *%s;\n" n;
8471 pr " size_t size;\n";
8473 pr " %s = guestfs_%s " n name;
8474 generate_c_call_args ~handle:"g" style;
8477 pr " if (%s == NULL)\n" n;
8478 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8479 pr " RETVAL = newSVpvn (%s, size);\n" n;
8480 pr " free (%s);\n" n;
8488 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8490 pr " struct guestfs_%s_list *%s;\n" typ n;
8494 pr " %s = guestfs_%s " n name;
8495 generate_c_call_args ~handle:"g" style;
8498 pr " if (%s == NULL)\n" n;
8499 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8500 pr " EXTEND (SP, %s->len);\n" n;
8501 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8502 pr " hv = newHV ();\n";
8506 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8507 name (String.length name) n name
8509 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8510 name (String.length name) n name
8512 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8513 name (String.length name) n name n name
8514 | name, (FBytes|FUInt64) ->
8515 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8516 name (String.length name) n name
8518 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8519 name (String.length name) n name
8520 | name, (FInt32|FUInt32) ->
8521 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8522 name (String.length name) n name
8524 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8525 name (String.length name) n name
8526 | name, FOptPercent ->
8527 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8528 name (String.length name) n name
8530 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8532 pr " guestfs_free_%s_list (%s);\n" typ n
8534 and generate_perl_struct_code typ cols name style n do_cleanups =
8536 pr " struct guestfs_%s *%s;\n" typ n;
8538 pr " %s = guestfs_%s " n name;
8539 generate_c_call_args ~handle:"g" style;
8542 pr " if (%s == NULL)\n" n;
8543 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8544 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8546 fun ((name, _) as col) ->
8547 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8551 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8554 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8557 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8559 | name, (FBytes|FUInt64) ->
8560 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8563 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8565 | name, (FInt32|FUInt32) ->
8566 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8569 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8571 | name, FOptPercent ->
8572 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8575 pr " free (%s);\n" n
8577 (* Generate Sys/Guestfs.pm. *)
8578 and generate_perl_pm () =
8579 generate_header HashStyle LGPLv2plus;
8586 Sys::Guestfs - Perl bindings for libguestfs
8592 my $h = Sys::Guestfs->new ();
8593 $h->add_drive ('guest.img');
8595 $h->mount ('/dev/sda1', '/');
8596 $h->touch ('/hello');
8601 The C<Sys::Guestfs> module provides a Perl XS binding to the
8602 libguestfs API for examining and modifying virtual machine
8605 Amongst the things this is good for: making batch configuration
8606 changes to guests, getting disk used/free statistics (see also:
8607 virt-df), migrating between virtualization systems (see also:
8608 virt-p2v), performing partial backups, performing partial guest
8609 clones, cloning guests and changing registry/UUID/hostname info, and
8612 Libguestfs uses Linux kernel and qemu code, and can access any type of
8613 guest filesystem that Linux and qemu can, including but not limited
8614 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8615 schemes, qcow, qcow2, vmdk.
8617 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8618 LVs, what filesystem is in each LV, etc.). It can also run commands
8619 in the context of the guest. Also you can access filesystems over
8622 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8623 functions for using libguestfs from Perl, including integration
8628 All errors turn into calls to C<croak> (see L<Carp(3)>).
8636 package Sys::Guestfs;
8642 XSLoader::load ('Sys::Guestfs');
8644 =item $h = Sys::Guestfs->new ();
8646 Create a new guestfs handle.
8652 my $class = ref ($proto) || $proto;
8654 my $self = Sys::Guestfs::_create ();
8655 bless $self, $class;
8661 (* Actions. We only need to print documentation for these as
8662 * they are pulled in from the XS code automatically.
8665 fun (name, style, _, flags, _, _, longdesc) ->
8666 if not (List.mem NotInDocs flags) then (
8667 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8669 generate_perl_prototype name style;
8671 pr "%s\n\n" longdesc;
8672 if List.mem ProtocolLimitWarning flags then
8673 pr "%s\n\n" protocol_limit_warning;
8674 if List.mem DangerWillRobinson flags then
8675 pr "%s\n\n" danger_will_robinson;
8676 match deprecation_notice flags with
8678 | Some txt -> pr "%s\n\n" txt
8680 ) all_functions_sorted;
8692 Copyright (C) %s Red Hat Inc.
8696 Please see the file COPYING.LIB for the full license.
8702 L<http://libguestfs.org>,
8703 L<Sys::Guestfs::Lib(3)>.
8708 and generate_perl_prototype name style =
8709 (match fst style with
8717 | RBufferOut n -> pr "$%s = " n
8719 | RHashtable n -> pr "%%%s = " n
8721 | RStructList (n,_) -> pr "@%s = " n
8724 let comma = ref false in
8727 if !comma then pr ", ";
8730 | Pathname n | Device n | Dev_or_Path n | String n
8731 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8733 | StringList n | DeviceList n ->
8738 (* Generate Python C module. *)
8739 and generate_python_c () =
8740 generate_header CStyle LGPLv2plus;
8749 #include \"guestfs.h\"
8757 get_handle (PyObject *obj)
8760 assert (obj != Py_None);
8761 return ((Pyguestfs_Object *) obj)->g;
8765 put_handle (guestfs_h *g)
8769 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8772 /* This list should be freed (but not the strings) after use. */
8774 get_string_list (PyObject *obj)
8781 if (!PyList_Check (obj)) {
8782 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8786 len = PyList_Size (obj);
8787 r = malloc (sizeof (char *) * (len+1));
8789 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8793 for (i = 0; i < len; ++i)
8794 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8801 put_string_list (char * const * const argv)
8806 for (argc = 0; argv[argc] != NULL; ++argc)
8809 list = PyList_New (argc);
8810 for (i = 0; i < argc; ++i)
8811 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8817 put_table (char * const * const argv)
8819 PyObject *list, *item;
8822 for (argc = 0; argv[argc] != NULL; ++argc)
8825 list = PyList_New (argc >> 1);
8826 for (i = 0; i < argc; i += 2) {
8827 item = PyTuple_New (2);
8828 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8829 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8830 PyList_SetItem (list, i >> 1, item);
8837 free_strings (char **argv)
8841 for (argc = 0; argv[argc] != NULL; ++argc)
8847 py_guestfs_create (PyObject *self, PyObject *args)
8851 g = guestfs_create ();
8853 PyErr_SetString (PyExc_RuntimeError,
8854 \"guestfs.create: failed to allocate handle\");
8857 guestfs_set_error_handler (g, NULL, NULL);
8858 return put_handle (g);
8862 py_guestfs_close (PyObject *self, PyObject *args)
8867 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8869 g = get_handle (py_g);
8873 Py_INCREF (Py_None);
8879 let emit_put_list_function typ =
8880 pr "static PyObject *\n";
8881 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8883 pr " PyObject *list;\n";
8886 pr " list = PyList_New (%ss->len);\n" typ;
8887 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8888 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8889 pr " return list;\n";
8894 (* Structures, turned into Python dictionaries. *)
8897 pr "static PyObject *\n";
8898 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8900 pr " PyObject *dict;\n";
8902 pr " dict = PyDict_New ();\n";
8906 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8907 pr " PyString_FromString (%s->%s));\n"
8910 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8911 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8914 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8915 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8917 | name, (FBytes|FUInt64) ->
8918 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8919 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8922 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8923 pr " PyLong_FromLongLong (%s->%s));\n"
8926 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8927 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8930 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8931 pr " PyLong_FromLong (%s->%s));\n"
8933 | name, FOptPercent ->
8934 pr " if (%s->%s >= 0)\n" typ name;
8935 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8936 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8939 pr " Py_INCREF (Py_None);\n";
8940 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8943 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8944 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8946 pr " return dict;\n";
8952 (* Emit a put_TYPE_list function definition only if that function is used. *)
8955 | typ, (RStructListOnly | RStructAndList) ->
8956 (* generate the function for typ *)
8957 emit_put_list_function typ
8958 | typ, _ -> () (* empty *)
8959 ) (rstructs_used_by all_functions);
8961 (* Python wrapper functions. *)
8963 fun (name, style, _, _, _, _, _) ->
8964 pr "static PyObject *\n";
8965 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8968 pr " PyObject *py_g;\n";
8969 pr " guestfs_h *g;\n";
8970 pr " PyObject *py_r;\n";
8973 match fst style with
8974 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8975 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8976 | RConstString _ | RConstOptString _ ->
8977 pr " const char *r;\n"; "NULL"
8978 | RString _ -> pr " char *r;\n"; "NULL"
8979 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8980 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8981 | RStructList (_, typ) ->
8982 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8985 pr " size_t size;\n";
8990 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8991 pr " const char *%s;\n" n
8992 | OptString n -> pr " const char *%s;\n" n
8993 | StringList n | DeviceList n ->
8994 pr " PyObject *py_%s;\n" n;
8995 pr " char **%s;\n" n
8996 | Bool n -> pr " int %s;\n" n
8997 | Int n -> pr " int %s;\n" n
8998 | Int64 n -> pr " long long %s;\n" n
9003 (* Convert the parameters. *)
9004 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9007 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9008 | OptString _ -> pr "z"
9009 | StringList _ | DeviceList _ -> pr "O"
9010 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9012 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9013 * emulate C's int/long/long long in Python?
9016 pr ":guestfs_%s\",\n" name;
9020 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9021 | OptString n -> pr ", &%s" n
9022 | StringList n | DeviceList n -> pr ", &py_%s" n
9023 | Bool n -> pr ", &%s" n
9024 | Int n -> pr ", &%s" n
9025 | Int64 n -> pr ", &%s" n
9029 pr " return NULL;\n";
9031 pr " g = get_handle (py_g);\n";
9034 | Pathname _ | Device _ | Dev_or_Path _ | String _
9035 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9036 | StringList n | DeviceList n ->
9037 pr " %s = get_string_list (py_%s);\n" n n;
9038 pr " if (!%s) return NULL;\n" n
9043 pr " r = guestfs_%s " name;
9044 generate_c_call_args ~handle:"g" style;
9049 | Pathname _ | Device _ | Dev_or_Path _ | String _
9050 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9051 | StringList n | DeviceList n ->
9052 pr " free (%s);\n" n
9055 pr " if (r == %s) {\n" error_code;
9056 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9057 pr " return NULL;\n";
9061 (match fst style with
9063 pr " Py_INCREF (Py_None);\n";
9064 pr " py_r = Py_None;\n"
9066 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9067 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9068 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9069 | RConstOptString _ ->
9071 pr " py_r = PyString_FromString (r);\n";
9073 pr " Py_INCREF (Py_None);\n";
9074 pr " py_r = Py_None;\n";
9077 pr " py_r = PyString_FromString (r);\n";
9080 pr " py_r = put_string_list (r);\n";
9081 pr " free_strings (r);\n"
9082 | RStruct (_, typ) ->
9083 pr " py_r = put_%s (r);\n" typ;
9084 pr " guestfs_free_%s (r);\n" typ
9085 | RStructList (_, typ) ->
9086 pr " py_r = put_%s_list (r);\n" typ;
9087 pr " guestfs_free_%s_list (r);\n" typ
9089 pr " py_r = put_table (r);\n";
9090 pr " free_strings (r);\n"
9092 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9096 pr " return py_r;\n";
9101 (* Table of functions. *)
9102 pr "static PyMethodDef methods[] = {\n";
9103 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9104 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9106 fun (name, _, _, _, _, _, _) ->
9107 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9110 pr " { NULL, NULL, 0, NULL }\n";
9114 (* Init function. *)
9117 initlibguestfsmod (void)
9119 static int initialized = 0;
9121 if (initialized) return;
9122 Py_InitModule ((char *) \"libguestfsmod\", methods);
9127 (* Generate Python module. *)
9128 and generate_python_py () =
9129 generate_header HashStyle LGPLv2plus;
9132 u\"\"\"Python bindings for libguestfs
9135 g = guestfs.GuestFS ()
9136 g.add_drive (\"guest.img\")
9138 parts = g.list_partitions ()
9140 The guestfs module provides a Python binding to the libguestfs API
9141 for examining and modifying virtual machine disk images.
9143 Amongst the things this is good for: making batch configuration
9144 changes to guests, getting disk used/free statistics (see also:
9145 virt-df), migrating between virtualization systems (see also:
9146 virt-p2v), performing partial backups, performing partial guest
9147 clones, cloning guests and changing registry/UUID/hostname info, and
9150 Libguestfs uses Linux kernel and qemu code, and can access any type of
9151 guest filesystem that Linux and qemu can, including but not limited
9152 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9153 schemes, qcow, qcow2, vmdk.
9155 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9156 LVs, what filesystem is in each LV, etc.). It can also run commands
9157 in the context of the guest. Also you can access filesystems over
9160 Errors which happen while using the API are turned into Python
9161 RuntimeError exceptions.
9163 To create a guestfs handle you usually have to perform the following
9166 # Create the handle, call add_drive at least once, and possibly
9167 # several times if the guest has multiple block devices:
9168 g = guestfs.GuestFS ()
9169 g.add_drive (\"guest.img\")
9171 # Launch the qemu subprocess and wait for it to become ready:
9174 # Now you can issue commands, for example:
9179 import libguestfsmod
9182 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9184 def __init__ (self):
9185 \"\"\"Create a new libguestfs handle.\"\"\"
9186 self._o = libguestfsmod.create ()
9189 libguestfsmod.close (self._o)
9194 fun (name, style, _, flags, _, _, longdesc) ->
9196 generate_py_call_args ~handle:"self" (snd style);
9199 if not (List.mem NotInDocs flags) then (
9200 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9202 match fst style with
9203 | RErr | RInt _ | RInt64 _ | RBool _
9204 | RConstOptString _ | RConstString _
9205 | RString _ | RBufferOut _ -> doc
9207 doc ^ "\n\nThis function returns a list of strings."
9208 | RStruct (_, typ) ->
9209 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9210 | RStructList (_, typ) ->
9211 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9213 doc ^ "\n\nThis function returns a dictionary." in
9215 if List.mem ProtocolLimitWarning flags then
9216 doc ^ "\n\n" ^ protocol_limit_warning
9219 if List.mem DangerWillRobinson flags then
9220 doc ^ "\n\n" ^ danger_will_robinson
9223 match deprecation_notice flags with
9225 | Some txt -> doc ^ "\n\n" ^ txt in
9226 let doc = pod2text ~width:60 name doc in
9227 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9228 let doc = String.concat "\n " doc in
9229 pr " u\"\"\"%s\"\"\"\n" doc;
9231 pr " return libguestfsmod.%s " name;
9232 generate_py_call_args ~handle:"self._o" (snd style);
9237 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9238 and generate_py_call_args ~handle args =
9240 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9243 (* Useful if you need the longdesc POD text as plain text. Returns a
9246 * Because this is very slow (the slowest part of autogeneration),
9247 * we memoize the results.
9249 and pod2text ~width name longdesc =
9250 let key = width, name, longdesc in
9251 try Hashtbl.find pod2text_memo key
9253 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9254 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9256 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9257 let chan = open_process_in cmd in
9258 let lines = ref [] in
9260 let line = input_line chan in
9261 if i = 1 then (* discard the first line of output *)
9264 let line = triml line in
9265 lines := line :: !lines;
9268 let lines = try loop 1 with End_of_file -> List.rev !lines in
9270 (match close_process_in chan with
9273 failwithf "pod2text: process exited with non-zero status (%d)" i
9274 | WSIGNALED i | WSTOPPED i ->
9275 failwithf "pod2text: process signalled or stopped by signal %d" i
9277 Hashtbl.add pod2text_memo key lines;
9278 pod2text_memo_updated ();
9281 (* Generate ruby bindings. *)
9282 and generate_ruby_c () =
9283 generate_header CStyle LGPLv2plus;
9291 #include \"guestfs.h\"
9293 #include \"extconf.h\"
9295 /* For Ruby < 1.9 */
9297 #define RARRAY_LEN(r) (RARRAY((r))->len)
9300 static VALUE m_guestfs; /* guestfs module */
9301 static VALUE c_guestfs; /* guestfs_h handle */
9302 static VALUE e_Error; /* used for all errors */
9304 static void ruby_guestfs_free (void *p)
9307 guestfs_close ((guestfs_h *) p);
9310 static VALUE ruby_guestfs_create (VALUE m)
9314 g = guestfs_create ();
9316 rb_raise (e_Error, \"failed to create guestfs handle\");
9318 /* Don't print error messages to stderr by default. */
9319 guestfs_set_error_handler (g, NULL, NULL);
9321 /* Wrap it, and make sure the close function is called when the
9324 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9327 static VALUE ruby_guestfs_close (VALUE gv)
9330 Data_Get_Struct (gv, guestfs_h, g);
9332 ruby_guestfs_free (g);
9333 DATA_PTR (gv) = NULL;
9341 fun (name, style, _, _, _, _, _) ->
9342 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9343 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9346 pr " guestfs_h *g;\n";
9347 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9349 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9355 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9356 pr " Check_Type (%sv, T_STRING);\n" n;
9357 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9359 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9360 pr " \"%s\", \"%s\");\n" n name
9362 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9363 | StringList n | DeviceList n ->
9364 pr " char **%s;\n" n;
9365 pr " Check_Type (%sv, T_ARRAY);\n" n;
9367 pr " int i, len;\n";
9368 pr " len = RARRAY_LEN (%sv);\n" n;
9369 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9371 pr " for (i = 0; i < len; ++i) {\n";
9372 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9373 pr " %s[i] = StringValueCStr (v);\n" n;
9375 pr " %s[len] = NULL;\n" n;
9378 pr " int %s = RTEST (%sv);\n" n n
9380 pr " int %s = NUM2INT (%sv);\n" n n
9382 pr " long long %s = NUM2LL (%sv);\n" n n
9387 match fst style with
9388 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9389 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9390 | RConstString _ | RConstOptString _ ->
9391 pr " const char *r;\n"; "NULL"
9392 | RString _ -> pr " char *r;\n"; "NULL"
9393 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9394 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9395 | RStructList (_, typ) ->
9396 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9399 pr " size_t size;\n";
9403 pr " r = guestfs_%s " name;
9404 generate_c_call_args ~handle:"g" style;
9409 | Pathname _ | Device _ | Dev_or_Path _ | String _
9410 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9411 | StringList n | DeviceList n ->
9412 pr " free (%s);\n" n
9415 pr " if (r == %s)\n" error_code;
9416 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9419 (match fst style with
9421 pr " return Qnil;\n"
9422 | RInt _ | RBool _ ->
9423 pr " return INT2NUM (r);\n"
9425 pr " return ULL2NUM (r);\n"
9427 pr " return rb_str_new2 (r);\n";
9428 | RConstOptString _ ->
9430 pr " return rb_str_new2 (r);\n";
9432 pr " return Qnil;\n";
9434 pr " VALUE rv = rb_str_new2 (r);\n";
9438 pr " int i, len = 0;\n";
9439 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9440 pr " VALUE rv = rb_ary_new2 (len);\n";
9441 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9442 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9443 pr " free (r[i]);\n";
9447 | RStruct (_, typ) ->
9448 let cols = cols_of_struct typ in
9449 generate_ruby_struct_code typ cols
9450 | RStructList (_, typ) ->
9451 let cols = cols_of_struct typ in
9452 generate_ruby_struct_list_code typ cols
9454 pr " VALUE rv = rb_hash_new ();\n";
9456 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9457 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9458 pr " free (r[i]);\n";
9459 pr " free (r[i+1]);\n";
9464 pr " VALUE rv = rb_str_new (r, size);\n";
9474 /* Initialize the module. */
9475 void Init__guestfs ()
9477 m_guestfs = rb_define_module (\"Guestfs\");
9478 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9479 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9481 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9482 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9485 (* Define the rest of the methods. *)
9487 fun (name, style, _, _, _, _, _) ->
9488 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9489 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9494 (* Ruby code to return a struct. *)
9495 and generate_ruby_struct_code typ cols =
9496 pr " VALUE rv = rb_hash_new ();\n";
9500 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9502 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9504 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9505 | name, (FBytes|FUInt64) ->
9506 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9508 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9510 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9512 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9513 | name, FOptPercent ->
9514 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9515 | name, FChar -> (* XXX wrong? *)
9516 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9518 pr " guestfs_free_%s (r);\n" typ;
9521 (* Ruby code to return a struct list. *)
9522 and generate_ruby_struct_list_code typ cols =
9523 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9525 pr " for (i = 0; i < r->len; ++i) {\n";
9526 pr " VALUE hv = rb_hash_new ();\n";
9530 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9532 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
9534 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9535 | name, (FBytes|FUInt64) ->
9536 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9538 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9540 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9542 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9543 | name, FOptPercent ->
9544 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9545 | name, FChar -> (* XXX wrong? *)
9546 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9548 pr " rb_ary_push (rv, hv);\n";
9550 pr " guestfs_free_%s_list (r);\n" typ;
9553 (* Generate Java bindings GuestFS.java file. *)
9554 and generate_java_java () =
9555 generate_header CStyle LGPLv2plus;
9558 package com.redhat.et.libguestfs;
9560 import java.util.HashMap;
9561 import com.redhat.et.libguestfs.LibGuestFSException;
9562 import com.redhat.et.libguestfs.PV;
9563 import com.redhat.et.libguestfs.VG;
9564 import com.redhat.et.libguestfs.LV;
9565 import com.redhat.et.libguestfs.Stat;
9566 import com.redhat.et.libguestfs.StatVFS;
9567 import com.redhat.et.libguestfs.IntBool;
9568 import com.redhat.et.libguestfs.Dirent;
9571 * The GuestFS object is a libguestfs handle.
9575 public class GuestFS {
9576 // Load the native code.
9578 System.loadLibrary (\"guestfs_jni\");
9582 * The native guestfs_h pointer.
9587 * Create a libguestfs handle.
9589 * @throws LibGuestFSException
9591 public GuestFS () throws LibGuestFSException
9595 private native long _create () throws LibGuestFSException;
9598 * Close a libguestfs handle.
9600 * You can also leave handles to be collected by the garbage
9601 * collector, but this method ensures that the resources used
9602 * by the handle are freed up immediately. If you call any
9603 * other methods after closing the handle, you will get an
9606 * @throws LibGuestFSException
9608 public void close () throws LibGuestFSException
9614 private native void _close (long g) throws LibGuestFSException;
9616 public void finalize () throws LibGuestFSException
9624 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9625 if not (List.mem NotInDocs flags); then (
9626 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9628 if List.mem ProtocolLimitWarning flags then
9629 doc ^ "\n\n" ^ protocol_limit_warning
9632 if List.mem DangerWillRobinson flags then
9633 doc ^ "\n\n" ^ danger_will_robinson
9636 match deprecation_notice flags with
9638 | Some txt -> doc ^ "\n\n" ^ txt in
9639 let doc = pod2text ~width:60 name doc in
9640 let doc = List.map ( (* RHBZ#501883 *)
9643 | nonempty -> nonempty
9645 let doc = String.concat "\n * " doc in
9648 pr " * %s\n" shortdesc;
9651 pr " * @throws LibGuestFSException\n";
9655 generate_java_prototype ~public:true ~semicolon:false name style;
9658 pr " if (g == 0)\n";
9659 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9662 if fst style <> RErr then pr "return ";
9664 generate_java_call_args ~handle:"g" (snd style);
9668 generate_java_prototype ~privat:true ~native:true name style;
9675 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9676 and generate_java_call_args ~handle args =
9678 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9681 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9682 ?(semicolon=true) name style =
9683 if privat then pr "private ";
9684 if public then pr "public ";
9685 if native then pr "native ";
9688 (match fst style with
9689 | RErr -> pr "void ";
9690 | RInt _ -> pr "int ";
9691 | RInt64 _ -> pr "long ";
9692 | RBool _ -> pr "boolean ";
9693 | RConstString _ | RConstOptString _ | RString _
9694 | RBufferOut _ -> pr "String ";
9695 | RStringList _ -> pr "String[] ";
9696 | RStruct (_, typ) ->
9697 let name = java_name_of_struct typ in
9699 | RStructList (_, typ) ->
9700 let name = java_name_of_struct typ in
9702 | RHashtable _ -> pr "HashMap<String,String> ";
9705 if native then pr "_%s " name else pr "%s " name;
9707 let needs_comma = ref false in
9716 if !needs_comma then pr ", ";
9717 needs_comma := true;
9721 | Device n | Dev_or_Path n
9727 | StringList n | DeviceList n ->
9738 pr " throws LibGuestFSException";
9739 if semicolon then pr ";"
9741 and generate_java_struct jtyp cols () =
9742 generate_header CStyle LGPLv2plus;
9745 package com.redhat.et.libguestfs;
9748 * Libguestfs %s structure.
9760 | name, FBuffer -> pr " public String %s;\n" name
9761 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9762 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9763 | name, FChar -> pr " public char %s;\n" name
9764 | name, FOptPercent ->
9765 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9766 pr " public float %s;\n" name
9771 and generate_java_c () =
9772 generate_header CStyle LGPLv2plus;
9779 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9780 #include \"guestfs.h\"
9782 /* Note that this function returns. The exception is not thrown
9783 * until after the wrapper function returns.
9786 throw_exception (JNIEnv *env, const char *msg)
9789 cl = (*env)->FindClass (env,
9790 \"com/redhat/et/libguestfs/LibGuestFSException\");
9791 (*env)->ThrowNew (env, cl, msg);
9794 JNIEXPORT jlong JNICALL
9795 Java_com_redhat_et_libguestfs_GuestFS__1create
9796 (JNIEnv *env, jobject obj)
9800 g = guestfs_create ();
9802 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9805 guestfs_set_error_handler (g, NULL, NULL);
9806 return (jlong) (long) g;
9809 JNIEXPORT void JNICALL
9810 Java_com_redhat_et_libguestfs_GuestFS__1close
9811 (JNIEnv *env, jobject obj, jlong jg)
9813 guestfs_h *g = (guestfs_h *) (long) jg;
9820 fun (name, style, _, _, _, _, _) ->
9822 (match fst style with
9823 | RErr -> pr "void ";
9824 | RInt _ -> pr "jint ";
9825 | RInt64 _ -> pr "jlong ";
9826 | RBool _ -> pr "jboolean ";
9827 | RConstString _ | RConstOptString _ | RString _
9828 | RBufferOut _ -> pr "jstring ";
9829 | RStruct _ | RHashtable _ ->
9831 | RStringList _ | RStructList _ ->
9835 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9836 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9838 pr " (JNIEnv *env, jobject obj, jlong jg";
9842 | Device n | Dev_or_Path n
9847 pr ", jstring j%s" n
9848 | StringList n | DeviceList n ->
9849 pr ", jobjectArray j%s" n
9851 pr ", jboolean j%s" n
9859 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9860 let error_code, no_ret =
9861 match fst style with
9862 | RErr -> pr " int r;\n"; "-1", ""
9864 | RInt _ -> pr " int r;\n"; "-1", "0"
9865 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9866 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9867 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9869 pr " jstring jr;\n";
9870 pr " char *r;\n"; "NULL", "NULL"
9872 pr " jobjectArray jr;\n";
9875 pr " jstring jstr;\n";
9876 pr " char **r;\n"; "NULL", "NULL"
9877 | RStruct (_, typ) ->
9878 pr " jobject jr;\n";
9880 pr " jfieldID fl;\n";
9881 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9882 | RStructList (_, typ) ->
9883 pr " jobjectArray jr;\n";
9885 pr " jfieldID fl;\n";
9886 pr " jobject jfl;\n";
9887 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9888 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9890 pr " jstring jr;\n";
9892 pr " size_t size;\n";
9897 | Device n | Dev_or_Path n
9902 pr " const char *%s;\n" n
9903 | StringList n | DeviceList n ->
9904 pr " int %s_len;\n" n;
9905 pr " const char **%s;\n" n
9910 pr " int64_t %s;\n" n
9914 (match fst style with
9915 | RStringList _ | RStructList _ -> true
9916 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9918 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9919 List.exists (function
9920 | StringList _ -> true
9921 | DeviceList _ -> true
9922 | _ -> false) (snd style) in
9928 (* Get the parameters. *)
9932 | Device n | Dev_or_Path n
9936 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9938 (* This is completely undocumented, but Java null becomes
9941 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9942 | StringList n | DeviceList n ->
9943 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9944 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9945 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9946 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9948 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9950 pr " %s[%s_len] = NULL;\n" n n;
9954 pr " %s = j%s;\n" n n
9957 (* Make the call. *)
9958 pr " r = guestfs_%s " name;
9959 generate_c_call_args ~handle:"g" style;
9962 (* Release the parameters. *)
9966 | Device n | Dev_or_Path n
9970 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9973 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9974 | StringList n | DeviceList n ->
9975 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9976 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9978 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9980 pr " free (%s);\n" n
9986 (* Check for errors. *)
9987 pr " if (r == %s) {\n" error_code;
9988 pr " throw_exception (env, guestfs_last_error (g));\n";
9989 pr " return %s;\n" no_ret;
9993 (match fst style with
9995 | RInt _ -> pr " return (jint) r;\n"
9996 | RBool _ -> pr " return (jboolean) r;\n"
9997 | RInt64 _ -> pr " return (jlong) r;\n"
9998 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9999 | RConstOptString _ ->
10000 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10002 pr " jr = (*env)->NewStringUTF (env, r);\n";
10006 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10007 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10008 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10009 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10010 pr " for (i = 0; i < r_len; ++i) {\n";
10011 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10012 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10013 pr " free (r[i]);\n";
10017 | RStruct (_, typ) ->
10018 let jtyp = java_name_of_struct typ in
10019 let cols = cols_of_struct typ in
10020 generate_java_struct_return typ jtyp cols
10021 | RStructList (_, typ) ->
10022 let jtyp = java_name_of_struct typ in
10023 let cols = cols_of_struct typ in
10024 generate_java_struct_list_return typ jtyp cols
10027 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10028 pr " return NULL;\n"
10030 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10039 and generate_java_struct_return typ jtyp cols =
10040 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10041 pr " jr = (*env)->AllocObject (env, cl);\n";
10045 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10046 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10049 pr " char s[33];\n";
10050 pr " memcpy (s, r->%s, 32);\n" name;
10051 pr " s[32] = 0;\n";
10052 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10053 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10057 pr " int len = r->%s_len;\n" name;
10058 pr " char s[len+1];\n";
10059 pr " memcpy (s, r->%s, len);\n" name;
10060 pr " s[len] = 0;\n";
10061 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10062 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10064 | name, (FBytes|FUInt64|FInt64) ->
10065 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10066 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10067 | name, (FUInt32|FInt32) ->
10068 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10069 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10070 | name, FOptPercent ->
10071 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10072 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10074 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10075 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10080 and generate_java_struct_list_return typ jtyp cols =
10081 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10082 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10083 pr " for (i = 0; i < r->len; ++i) {\n";
10084 pr " jfl = (*env)->AllocObject (env, cl);\n";
10088 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10089 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10092 pr " char s[33];\n";
10093 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10094 pr " s[32] = 0;\n";
10095 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10096 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10100 pr " int len = r->val[i].%s_len;\n" name;
10101 pr " char s[len+1];\n";
10102 pr " memcpy (s, r->val[i].%s, len);\n" name;
10103 pr " s[len] = 0;\n";
10104 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10105 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10107 | name, (FBytes|FUInt64|FInt64) ->
10108 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10109 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10110 | name, (FUInt32|FInt32) ->
10111 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10112 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10113 | name, FOptPercent ->
10114 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10115 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10117 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10118 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10120 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10122 pr " guestfs_free_%s_list (r);\n" typ;
10125 and generate_java_makefile_inc () =
10126 generate_header HashStyle GPLv2plus;
10128 pr "java_built_sources = \\\n";
10131 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10133 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10135 and generate_haskell_hs () =
10136 generate_header HaskellStyle LGPLv2plus;
10138 (* XXX We only know how to generate partial FFI for Haskell
10139 * at the moment. Please help out!
10141 let can_generate style =
10145 | RInt64 _, _ -> true
10147 | RConstString _, _
10148 | RConstOptString _, _
10154 | RBufferOut _, _ -> false in
10157 {-# INCLUDE <guestfs.h> #-}
10158 {-# LANGUAGE ForeignFunctionInterface #-}
10163 (* List out the names of the actions we want to export. *)
10165 fun (name, style, _, _, _, _, _) ->
10166 if can_generate style then pr ",\n %s" name
10172 -- Unfortunately some symbols duplicate ones already present
10173 -- in Prelude. We don't know which, so we hard-code a list
10175 import Prelude hiding (truncate)
10179 import Foreign.C.Types
10181 import Control.Exception
10182 import Data.Typeable
10184 data GuestfsS = GuestfsS -- represents the opaque C struct
10185 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10186 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10188 -- XXX define properly later XXX
10192 data IntBool = IntBool
10194 data StatVFS = StatVFS
10195 data Hashtable = Hashtable
10197 foreign import ccall unsafe \"guestfs_create\" c_create
10199 foreign import ccall unsafe \"&guestfs_close\" c_close
10200 :: FunPtr (GuestfsP -> IO ())
10201 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10202 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10204 create :: IO GuestfsH
10207 c_set_error_handler p nullPtr nullPtr
10208 h <- newForeignPtr c_close p
10211 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10212 :: GuestfsP -> IO CString
10214 -- last_error :: GuestfsH -> IO (Maybe String)
10215 -- last_error h = do
10216 -- str <- withForeignPtr h (\\p -> c_last_error p)
10217 -- maybePeek peekCString str
10219 last_error :: GuestfsH -> IO (String)
10221 str <- withForeignPtr h (\\p -> c_last_error p)
10222 if (str == nullPtr)
10223 then return \"no error\"
10224 else peekCString str
10228 (* Generate wrappers for each foreign function. *)
10230 fun (name, style, _, _, _, _, _) ->
10231 if can_generate style then (
10232 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10234 generate_haskell_prototype ~handle:"GuestfsP" style;
10238 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10240 pr "%s %s = do\n" name
10241 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10243 (* Convert pointer arguments using with* functions. *)
10248 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10249 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10250 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10251 | Bool _ | Int _ | Int64 _ -> ()
10253 (* Convert integer arguments. *)
10257 | Bool n -> sprintf "(fromBool %s)" n
10258 | Int n -> sprintf "(fromIntegral %s)" n
10259 | Int64 n -> sprintf "(fromIntegral %s)" n
10260 | FileIn n | FileOut n
10261 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10263 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10264 (String.concat " " ("p" :: args));
10265 (match fst style with
10266 | RErr | RInt _ | RInt64 _ | RBool _ ->
10267 pr " if (r == -1)\n";
10269 pr " err <- last_error h\n";
10271 | RConstString _ | RConstOptString _ | RString _
10272 | RStringList _ | RStruct _
10273 | RStructList _ | RHashtable _ | RBufferOut _ ->
10274 pr " if (r == nullPtr)\n";
10276 pr " err <- last_error h\n";
10279 (match fst style with
10281 pr " else return ()\n"
10283 pr " else return (fromIntegral r)\n"
10285 pr " else return (fromIntegral r)\n"
10287 pr " else return (toBool r)\n"
10289 | RConstOptString _
10296 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10302 and generate_haskell_prototype ~handle ?(hs = false) style =
10303 pr "%s -> " handle;
10304 let string = if hs then "String" else "CString" in
10305 let int = if hs then "Int" else "CInt" in
10306 let bool = if hs then "Bool" else "CInt" in
10307 let int64 = if hs then "Integer" else "Int64" in
10311 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10312 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10313 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10314 | Bool _ -> pr "%s" bool
10315 | Int _ -> pr "%s" int
10316 | Int64 _ -> pr "%s" int
10317 | FileIn _ -> pr "%s" string
10318 | FileOut _ -> pr "%s" string
10323 (match fst style with
10324 | RErr -> if not hs then pr "CInt"
10325 | RInt _ -> pr "%s" int
10326 | RInt64 _ -> pr "%s" int64
10327 | RBool _ -> pr "%s" bool
10328 | RConstString _ -> pr "%s" string
10329 | RConstOptString _ -> pr "Maybe %s" string
10330 | RString _ -> pr "%s" string
10331 | RStringList _ -> pr "[%s]" string
10332 | RStruct (_, typ) ->
10333 let name = java_name_of_struct typ in
10335 | RStructList (_, typ) ->
10336 let name = java_name_of_struct typ in
10338 | RHashtable _ -> pr "Hashtable"
10339 | RBufferOut _ -> pr "%s" string
10343 and generate_csharp () =
10344 generate_header CPlusPlusStyle LGPLv2plus;
10346 (* XXX Make this configurable by the C# assembly users. *)
10347 let library = "libguestfs.so.0" in
10350 // These C# bindings are highly experimental at present.
10352 // Firstly they only work on Linux (ie. Mono). In order to get them
10353 // to work on Windows (ie. .Net) you would need to port the library
10354 // itself to Windows first.
10356 // The second issue is that some calls are known to be incorrect and
10357 // can cause Mono to segfault. Particularly: calls which pass or
10358 // return string[], or return any structure value. This is because
10359 // we haven't worked out the correct way to do this from C#.
10361 // The third issue is that when compiling you get a lot of warnings.
10362 // We are not sure whether the warnings are important or not.
10364 // Fourthly we do not routinely build or test these bindings as part
10365 // of the make && make check cycle, which means that regressions might
10368 // Suggestions and patches are welcome.
10372 // gmcs Libguestfs.cs
10373 // mono Libguestfs.exe
10375 // (You'll probably want to add a Test class / static main function
10376 // otherwise this won't do anything useful).
10380 using System.Runtime.InteropServices;
10381 using System.Runtime.Serialization;
10382 using System.Collections;
10386 class Error : System.ApplicationException
10388 public Error (string message) : base (message) {}
10389 protected Error (SerializationInfo info, StreamingContext context) {}
10396 [DllImport (\"%s\")]
10397 static extern IntPtr guestfs_create ();
10401 _handle = guestfs_create ();
10402 if (_handle == IntPtr.Zero)
10403 throw new Error (\"could not create guestfs handle\");
10406 [DllImport (\"%s\")]
10407 static extern void guestfs_close (IntPtr h);
10411 guestfs_close (_handle);
10414 [DllImport (\"%s\")]
10415 static extern string guestfs_last_error (IntPtr h);
10417 " library library library;
10419 (* Generate C# structure bindings. We prefix struct names with
10420 * underscore because C# cannot have conflicting struct names and
10421 * method names (eg. "class stat" and "stat").
10425 pr " [StructLayout (LayoutKind.Sequential)]\n";
10426 pr " public class _%s {\n" typ;
10429 | name, FChar -> pr " char %s;\n" name
10430 | name, FString -> pr " string %s;\n" name
10432 pr " uint %s_len;\n" name;
10433 pr " string %s;\n" name
10435 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10436 pr " string %s;\n" name
10437 | name, FUInt32 -> pr " uint %s;\n" name
10438 | name, FInt32 -> pr " int %s;\n" name
10439 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10440 | name, FInt64 -> pr " long %s;\n" name
10441 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10447 (* Generate C# function bindings. *)
10449 fun (name, style, _, _, _, shortdesc, _) ->
10450 let rec csharp_return_type () =
10451 match fst style with
10453 | RBool n -> "bool"
10455 | RInt64 n -> "long"
10457 | RConstOptString n
10459 | RBufferOut n -> "string"
10460 | RStruct (_,n) -> "_" ^ n
10461 | RHashtable n -> "Hashtable"
10462 | RStringList n -> "string[]"
10463 | RStructList (_,n) -> sprintf "_%s[]" n
10465 and c_return_type () =
10466 match fst style with
10470 | RInt64 _ -> "long"
10472 | RConstOptString _
10474 | RBufferOut _ -> "string"
10475 | RStruct (_,n) -> "_" ^ n
10477 | RStringList _ -> "string[]"
10478 | RStructList (_,n) -> sprintf "_%s[]" n
10480 and c_error_comparison () =
10481 match fst style with
10485 | RInt64 _ -> "== -1"
10487 | RConstOptString _
10493 | RStructList (_,_) -> "== null"
10495 and generate_extern_prototype () =
10496 pr " static extern %s guestfs_%s (IntPtr h"
10497 (c_return_type ()) name;
10500 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10501 | FileIn n | FileOut n ->
10502 pr ", [In] string %s" n
10503 | StringList n | DeviceList n ->
10504 pr ", [In] string[] %s" n
10514 and generate_public_prototype () =
10515 pr " public %s %s (" (csharp_return_type ()) name;
10516 let comma = ref false in
10518 if !comma then pr ", ";
10523 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10524 | FileIn n | FileOut n ->
10525 next (); pr "string %s" n
10526 | StringList n | DeviceList n ->
10527 next (); pr "string[] %s" n
10529 next (); pr "bool %s" n
10531 next (); pr "int %s" n
10533 next (); pr "long %s" n
10537 and generate_call () =
10538 pr "guestfs_%s (_handle" name;
10539 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10543 pr " [DllImport (\"%s\")]\n" library;
10544 generate_extern_prototype ();
10546 pr " /// <summary>\n";
10547 pr " /// %s\n" shortdesc;
10548 pr " /// </summary>\n";
10549 generate_public_prototype ();
10551 pr " %s r;\n" (c_return_type ());
10554 pr " if (r %s)\n" (c_error_comparison ());
10555 pr " throw new Error (guestfs_last_error (_handle));\n";
10556 (match fst style with
10559 pr " return r != 0 ? true : false;\n"
10561 pr " Hashtable rr = new Hashtable ();\n";
10562 pr " for (int i = 0; i < r.Length; i += 2)\n";
10563 pr " rr.Add (r[i], r[i+1]);\n";
10565 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10566 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10572 ) all_functions_sorted;
10578 and generate_bindtests () =
10579 generate_header CStyle LGPLv2plus;
10583 #include <stdlib.h>
10584 #include <inttypes.h>
10585 #include <string.h>
10587 #include \"guestfs.h\"
10588 #include \"guestfs-internal.h\"
10589 #include \"guestfs-internal-actions.h\"
10590 #include \"guestfs_protocol.h\"
10592 #define error guestfs_error
10593 #define safe_calloc guestfs_safe_calloc
10594 #define safe_malloc guestfs_safe_malloc
10597 print_strings (char *const *argv)
10602 for (argc = 0; argv[argc] != NULL; ++argc) {
10603 if (argc > 0) printf (\", \");
10604 printf (\"\\\"%%s\\\"\", argv[argc]);
10609 /* The test0 function prints its parameters to stdout. */
10613 match test_functions with
10614 | [] -> assert false
10615 | test0 :: tests -> test0, tests in
10618 let (name, style, _, _, _, _, _) = test0 in
10619 generate_prototype ~extern:false ~semicolon:false ~newline:true
10620 ~handle:"g" ~prefix:"guestfs__" name style;
10625 | Device n | Dev_or_Path n
10628 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10629 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10630 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10631 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10632 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10633 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10635 pr " /* Java changes stdout line buffering so we need this: */\n";
10636 pr " fflush (stdout);\n";
10642 fun (name, style, _, _, _, _, _) ->
10643 if String.sub name (String.length name - 3) 3 <> "err" then (
10644 pr "/* Test normal return. */\n";
10645 generate_prototype ~extern:false ~semicolon:false ~newline:true
10646 ~handle:"g" ~prefix:"guestfs__" name style;
10648 (match fst style with
10653 pr " sscanf (val, \"%%d\", &r);\n";
10656 pr " int64_t r;\n";
10657 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10660 pr " return STREQ (val, \"true\");\n"
10662 | RConstOptString _ ->
10663 (* Can't return the input string here. Return a static
10664 * string so we ensure we get a segfault if the caller
10665 * tries to free it.
10667 pr " return \"static string\";\n"
10669 pr " return strdup (val);\n"
10671 pr " char **strs;\n";
10673 pr " sscanf (val, \"%%d\", &n);\n";
10674 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10675 pr " for (i = 0; i < n; ++i) {\n";
10676 pr " strs[i] = safe_malloc (g, 16);\n";
10677 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10679 pr " strs[n] = NULL;\n";
10680 pr " return strs;\n"
10681 | RStruct (_, typ) ->
10682 pr " struct guestfs_%s *r;\n" typ;
10683 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10685 | RStructList (_, typ) ->
10686 pr " struct guestfs_%s_list *r;\n" typ;
10687 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10688 pr " sscanf (val, \"%%d\", &r->len);\n";
10689 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10692 pr " char **strs;\n";
10694 pr " sscanf (val, \"%%d\", &n);\n";
10695 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10696 pr " for (i = 0; i < n; ++i) {\n";
10697 pr " strs[i*2] = safe_malloc (g, 16);\n";
10698 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10699 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10700 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10702 pr " strs[n*2] = NULL;\n";
10703 pr " return strs;\n"
10705 pr " return strdup (val);\n"
10710 pr "/* Test error return. */\n";
10711 generate_prototype ~extern:false ~semicolon:false ~newline:true
10712 ~handle:"g" ~prefix:"guestfs__" name style;
10714 pr " error (g, \"error\");\n";
10715 (match fst style with
10716 | RErr | RInt _ | RInt64 _ | RBool _ ->
10718 | RConstString _ | RConstOptString _
10719 | RString _ | RStringList _ | RStruct _
10723 pr " return NULL;\n"
10730 and generate_ocaml_bindtests () =
10731 generate_header OCamlStyle GPLv2plus;
10735 let g = Guestfs.create () in
10739 String.concat " " (
10742 | CallString s -> "\"" ^ s ^ "\""
10743 | CallOptString None -> "None"
10744 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10745 | CallStringList xs ->
10746 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10747 | CallInt i when i >= 0 -> string_of_int i
10748 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10749 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10750 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10751 | CallBool b -> string_of_bool b
10756 generate_lang_bindtests (
10757 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10760 pr "print_endline \"EOF\"\n"
10762 and generate_perl_bindtests () =
10763 pr "#!/usr/bin/perl -w\n";
10764 generate_header HashStyle GPLv2plus;
10771 my $g = Sys::Guestfs->new ();
10775 String.concat ", " (
10778 | CallString s -> "\"" ^ s ^ "\""
10779 | CallOptString None -> "undef"
10780 | CallOptString (Some s) -> sprintf "\"%s\"" s
10781 | CallStringList xs ->
10782 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10783 | CallInt i -> string_of_int i
10784 | CallInt64 i -> Int64.to_string i
10785 | CallBool b -> if b then "1" else "0"
10790 generate_lang_bindtests (
10791 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10794 pr "print \"EOF\\n\"\n"
10796 and generate_python_bindtests () =
10797 generate_header HashStyle GPLv2plus;
10802 g = guestfs.GuestFS ()
10806 String.concat ", " (
10809 | CallString s -> "\"" ^ s ^ "\""
10810 | CallOptString None -> "None"
10811 | CallOptString (Some s) -> sprintf "\"%s\"" s
10812 | CallStringList xs ->
10813 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10814 | CallInt i -> string_of_int i
10815 | CallInt64 i -> Int64.to_string i
10816 | CallBool b -> if b then "1" else "0"
10821 generate_lang_bindtests (
10822 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10825 pr "print \"EOF\"\n"
10827 and generate_ruby_bindtests () =
10828 generate_header HashStyle GPLv2plus;
10833 g = Guestfs::create()
10837 String.concat ", " (
10840 | CallString s -> "\"" ^ s ^ "\""
10841 | CallOptString None -> "nil"
10842 | CallOptString (Some s) -> sprintf "\"%s\"" s
10843 | CallStringList xs ->
10844 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10845 | CallInt i -> string_of_int i
10846 | CallInt64 i -> Int64.to_string i
10847 | CallBool b -> string_of_bool b
10852 generate_lang_bindtests (
10853 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10856 pr "print \"EOF\\n\"\n"
10858 and generate_java_bindtests () =
10859 generate_header CStyle GPLv2plus;
10862 import com.redhat.et.libguestfs.*;
10864 public class Bindtests {
10865 public static void main (String[] argv)
10868 GuestFS g = new GuestFS ();
10872 String.concat ", " (
10875 | CallString s -> "\"" ^ s ^ "\""
10876 | CallOptString None -> "null"
10877 | CallOptString (Some s) -> sprintf "\"%s\"" s
10878 | CallStringList xs ->
10880 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10881 | CallInt i -> string_of_int i
10882 | CallInt64 i -> Int64.to_string i
10883 | CallBool b -> string_of_bool b
10888 generate_lang_bindtests (
10889 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10893 System.out.println (\"EOF\");
10895 catch (Exception exn) {
10896 System.err.println (exn);
10903 and generate_haskell_bindtests () =
10904 generate_header HaskellStyle GPLv2plus;
10907 module Bindtests where
10908 import qualified Guestfs
10911 g <- Guestfs.create
10915 String.concat " " (
10918 | CallString s -> "\"" ^ s ^ "\""
10919 | CallOptString None -> "Nothing"
10920 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10921 | CallStringList xs ->
10922 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10923 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10924 | CallInt i -> string_of_int i
10925 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10926 | CallInt64 i -> Int64.to_string i
10927 | CallBool true -> "True"
10928 | CallBool false -> "False"
10933 generate_lang_bindtests (
10934 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10937 pr " putStrLn \"EOF\"\n"
10939 (* Language-independent bindings tests - we do it this way to
10940 * ensure there is parity in testing bindings across all languages.
10942 and generate_lang_bindtests call =
10943 call "test0" [CallString "abc"; CallOptString (Some "def");
10944 CallStringList []; CallBool false;
10945 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10946 call "test0" [CallString "abc"; CallOptString None;
10947 CallStringList []; CallBool false;
10948 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10949 call "test0" [CallString ""; CallOptString (Some "def");
10950 CallStringList []; CallBool false;
10951 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10952 call "test0" [CallString ""; CallOptString (Some "");
10953 CallStringList []; CallBool false;
10954 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10955 call "test0" [CallString "abc"; CallOptString (Some "def");
10956 CallStringList ["1"]; CallBool false;
10957 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10958 call "test0" [CallString "abc"; CallOptString (Some "def");
10959 CallStringList ["1"; "2"]; CallBool false;
10960 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10961 call "test0" [CallString "abc"; CallOptString (Some "def");
10962 CallStringList ["1"]; CallBool true;
10963 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10964 call "test0" [CallString "abc"; CallOptString (Some "def");
10965 CallStringList ["1"]; CallBool false;
10966 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10967 call "test0" [CallString "abc"; CallOptString (Some "def");
10968 CallStringList ["1"]; CallBool false;
10969 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10970 call "test0" [CallString "abc"; CallOptString (Some "def");
10971 CallStringList ["1"]; CallBool false;
10972 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10973 call "test0" [CallString "abc"; CallOptString (Some "def");
10974 CallStringList ["1"]; CallBool false;
10975 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10976 call "test0" [CallString "abc"; CallOptString (Some "def");
10977 CallStringList ["1"]; CallBool false;
10978 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10979 call "test0" [CallString "abc"; CallOptString (Some "def");
10980 CallStringList ["1"]; CallBool false;
10981 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10983 (* XXX Add here tests of the return and error functions. *)
10985 (* Code to generator bindings for virt-inspector. Currently only
10986 * implemented for OCaml code (for virt-p2v 2.0).
10988 let rng_input = "inspector/virt-inspector.rng"
10990 (* Read the input file and parse it into internal structures. This is
10991 * by no means a complete RELAX NG parser, but is just enough to be
10992 * able to parse the specific input file.
10995 | Element of string * rng list (* <element name=name/> *)
10996 | Attribute of string * rng list (* <attribute name=name/> *)
10997 | Interleave of rng list (* <interleave/> *)
10998 | ZeroOrMore of rng (* <zeroOrMore/> *)
10999 | OneOrMore of rng (* <oneOrMore/> *)
11000 | Optional of rng (* <optional/> *)
11001 | Choice of string list (* <choice><value/>*</choice> *)
11002 | Value of string (* <value>str</value> *)
11003 | Text (* <text/> *)
11005 let rec string_of_rng = function
11006 | Element (name, xs) ->
11007 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11008 | Attribute (name, xs) ->
11009 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11010 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11011 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11012 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11013 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11014 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11015 | Value value -> "Value \"" ^ value ^ "\""
11018 and string_of_rng_list xs =
11019 String.concat ", " (List.map string_of_rng xs)
11021 let rec parse_rng ?defines context = function
11023 | Xml.Element ("element", ["name", name], children) :: rest ->
11024 Element (name, parse_rng ?defines context children)
11025 :: parse_rng ?defines context rest
11026 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11027 Attribute (name, parse_rng ?defines context children)
11028 :: parse_rng ?defines context rest
11029 | Xml.Element ("interleave", [], children) :: rest ->
11030 Interleave (parse_rng ?defines context children)
11031 :: parse_rng ?defines context rest
11032 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11033 let rng = parse_rng ?defines context [child] in
11035 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11037 failwithf "%s: <zeroOrMore> contains more than one child element"
11040 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11041 let rng = parse_rng ?defines context [child] in
11043 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11045 failwithf "%s: <oneOrMore> contains more than one child element"
11048 | Xml.Element ("optional", [], [child]) :: rest ->
11049 let rng = parse_rng ?defines context [child] in
11051 | [child] -> Optional child :: parse_rng ?defines context rest
11053 failwithf "%s: <optional> contains more than one child element"
11056 | Xml.Element ("choice", [], children) :: rest ->
11057 let values = List.map (
11058 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11060 failwithf "%s: can't handle anything except <value> in <choice>"
11064 :: parse_rng ?defines context rest
11065 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11066 Value value :: parse_rng ?defines context rest
11067 | Xml.Element ("text", [], []) :: rest ->
11068 Text :: parse_rng ?defines context rest
11069 | Xml.Element ("ref", ["name", name], []) :: rest ->
11070 (* Look up the reference. Because of limitations in this parser,
11071 * we can't handle arbitrarily nested <ref> yet. You can only
11072 * use <ref> from inside <start>.
11074 (match defines with
11076 failwithf "%s: contains <ref>, but no refs are defined yet" context
11078 let rng = StringMap.find name map in
11079 rng @ parse_rng ?defines context rest
11082 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11085 let xml = Xml.parse_file rng_input in
11087 | Xml.Element ("grammar", _,
11088 Xml.Element ("start", _, gram) :: defines) ->
11089 (* The <define/> elements are referenced in the <start> section,
11090 * so build a map of those first.
11092 let defines = List.fold_left (
11094 function Xml.Element ("define", ["name", name], defn) ->
11095 StringMap.add name defn map
11097 failwithf "%s: expected <define name=name/>" rng_input
11098 ) StringMap.empty defines in
11099 let defines = StringMap.mapi parse_rng defines in
11101 (* Parse the <start> clause, passing the defines. *)
11102 parse_rng ~defines "<start>" gram
11104 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11107 let name_of_field = function
11108 | Element (name, _) | Attribute (name, _)
11109 | ZeroOrMore (Element (name, _))
11110 | OneOrMore (Element (name, _))
11111 | Optional (Element (name, _)) -> name
11112 | Optional (Attribute (name, _)) -> name
11113 | Text -> (* an unnamed field in an element *)
11116 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11118 (* At the moment this function only generates OCaml types. However we
11119 * should parameterize it later so it can generate types/structs in a
11120 * variety of languages.
11122 let generate_types xs =
11123 (* A simple type is one that can be printed out directly, eg.
11124 * "string option". A complex type is one which has a name and has
11125 * to be defined via another toplevel definition, eg. a struct.
11127 * generate_type generates code for either simple or complex types.
11128 * In the simple case, it returns the string ("string option"). In
11129 * the complex case, it returns the name ("mountpoint"). In the
11130 * complex case it has to print out the definition before returning,
11131 * so it should only be called when we are at the beginning of a
11132 * new line (BOL context).
11134 let rec generate_type = function
11135 | Text -> (* string *)
11137 | Choice values -> (* [`val1|`val2|...] *)
11138 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11139 | ZeroOrMore rng -> (* <rng> list *)
11140 let t, is_simple = generate_type rng in
11141 t ^ " list (* 0 or more *)", is_simple
11142 | OneOrMore rng -> (* <rng> list *)
11143 let t, is_simple = generate_type rng in
11144 t ^ " list (* 1 or more *)", is_simple
11145 (* virt-inspector hack: bool *)
11146 | Optional (Attribute (name, [Value "1"])) ->
11148 | Optional rng -> (* <rng> list *)
11149 let t, is_simple = generate_type rng in
11150 t ^ " option", is_simple
11151 (* type name = { fields ... } *)
11152 | Element (name, fields) when is_attrs_interleave fields ->
11153 generate_type_struct name (get_attrs_interleave fields)
11154 | Element (name, [field]) (* type name = field *)
11155 | Attribute (name, [field]) ->
11156 let t, is_simple = generate_type field in
11157 if is_simple then (t, true)
11159 pr "type %s = %s\n" name t;
11162 | Element (name, fields) -> (* type name = { fields ... } *)
11163 generate_type_struct name fields
11165 failwithf "generate_type failed at: %s" (string_of_rng rng)
11167 and is_attrs_interleave = function
11168 | [Interleave _] -> true
11169 | Attribute _ :: fields -> is_attrs_interleave fields
11170 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11173 and get_attrs_interleave = function
11174 | [Interleave fields] -> fields
11175 | ((Attribute _) as field) :: fields
11176 | ((Optional (Attribute _)) as field) :: fields ->
11177 field :: get_attrs_interleave fields
11178 | _ -> assert false
11180 and generate_types xs =
11181 List.iter (fun x -> ignore (generate_type x)) xs
11183 and generate_type_struct name fields =
11184 (* Calculate the types of the fields first. We have to do this
11185 * before printing anything so we are still in BOL context.
11187 let types = List.map fst (List.map generate_type fields) in
11189 (* Special case of a struct containing just a string and another
11190 * field. Turn it into an assoc list.
11193 | ["string"; other] ->
11194 let fname1, fname2 =
11196 | [f1; f2] -> name_of_field f1, name_of_field f2
11197 | _ -> assert false in
11198 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11202 pr "type %s = {\n" name;
11204 fun (field, ftype) ->
11205 let fname = name_of_field field in
11206 pr " %s_%s : %s;\n" name fname ftype
11207 ) (List.combine fields types);
11209 (* Return the name of this type, and
11210 * false because it's not a simple type.
11217 let generate_parsers xs =
11218 (* As for generate_type above, generate_parser makes a parser for
11219 * some type, and returns the name of the parser it has generated.
11220 * Because it (may) need to print something, it should always be
11221 * called in BOL context.
11223 let rec generate_parser = function
11224 | Text -> (* string *)
11225 "string_child_or_empty"
11226 | Choice values -> (* [`val1|`val2|...] *)
11227 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11229 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11230 | ZeroOrMore rng -> (* <rng> list *)
11231 let pa = generate_parser rng in
11232 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11233 | OneOrMore rng -> (* <rng> list *)
11234 let pa = generate_parser rng in
11235 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11236 (* virt-inspector hack: bool *)
11237 | Optional (Attribute (name, [Value "1"])) ->
11238 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11239 | Optional rng -> (* <rng> list *)
11240 let pa = generate_parser rng in
11241 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11242 (* type name = { fields ... } *)
11243 | Element (name, fields) when is_attrs_interleave fields ->
11244 generate_parser_struct name (get_attrs_interleave fields)
11245 | Element (name, [field]) -> (* type name = field *)
11246 let pa = generate_parser field in
11247 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11248 pr "let %s =\n" parser_name;
11250 pr "let parse_%s = %s\n" name parser_name;
11252 | Attribute (name, [field]) ->
11253 let pa = generate_parser field in
11254 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11255 pr "let %s =\n" parser_name;
11257 pr "let parse_%s = %s\n" name parser_name;
11259 | Element (name, fields) -> (* type name = { fields ... } *)
11260 generate_parser_struct name ([], fields)
11262 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11264 and is_attrs_interleave = function
11265 | [Interleave _] -> true
11266 | Attribute _ :: fields -> is_attrs_interleave fields
11267 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11270 and get_attrs_interleave = function
11271 | [Interleave fields] -> [], fields
11272 | ((Attribute _) as field) :: fields
11273 | ((Optional (Attribute _)) as field) :: fields ->
11274 let attrs, interleaves = get_attrs_interleave fields in
11275 (field :: attrs), interleaves
11276 | _ -> assert false
11278 and generate_parsers xs =
11279 List.iter (fun x -> ignore (generate_parser x)) xs
11281 and generate_parser_struct name (attrs, interleaves) =
11282 (* Generate parsers for the fields first. We have to do this
11283 * before printing anything so we are still in BOL context.
11285 let fields = attrs @ interleaves in
11286 let pas = List.map generate_parser fields in
11288 (* Generate an intermediate tuple from all the fields first.
11289 * If the type is just a string + another field, then we will
11290 * return this directly, otherwise it is turned into a record.
11292 * RELAX NG note: This code treats <interleave> and plain lists of
11293 * fields the same. In other words, it doesn't bother enforcing
11294 * any ordering of fields in the XML.
11296 pr "let parse_%s x =\n" name;
11297 pr " let t = (\n ";
11298 let comma = ref false in
11301 if !comma then pr ",\n ";
11304 | Optional (Attribute (fname, [field])), pa ->
11306 | Optional (Element (fname, [field])), pa ->
11307 pr "%s (optional_child %S x)" pa fname
11308 | Attribute (fname, [Text]), _ ->
11309 pr "attribute %S x" fname
11310 | (ZeroOrMore _ | OneOrMore _), pa ->
11315 let fname = name_of_field field in
11316 pr "%s (child %S x)" pa fname
11317 ) (List.combine fields pas);
11321 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11325 pr " (Obj.magic t : %s)\n" name
11329 | (Optional (Attribute (fname, [field])), pa) ->
11330 pr " %s_%s =\n" name fname;
11332 | (Optional (Element (fname, [field])), pa) ->
11333 pr " %s_%s =\n" name fname;
11334 pr " (let x = optional_child %S x in\n" fname;
11337 let fname = name_of_field field in
11338 pr " %s_%s =\n" name fname;
11339 pr " (let x = child %S x in\n" fname;
11341 ) (List.combine fields pas);
11345 sprintf "parse_%s" name
11348 generate_parsers xs
11350 (* Generate ocaml/guestfs_inspector.mli. *)
11351 let generate_ocaml_inspector_mli () =
11352 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11355 (** This is an OCaml language binding to the external [virt-inspector]
11358 For more information, please read the man page [virt-inspector(1)].
11363 generate_types grammar;
11364 pr "(** The nested information returned from the {!inspect} function. *)\n";
11368 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11369 (** To inspect a libvirt domain called [name], pass a singleton
11370 list: [inspect [name]]. When using libvirt only, you may
11371 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11373 To inspect a disk image or images, pass a list of the filenames
11374 of the disk images: [inspect filenames]
11376 This function inspects the given guest or disk images and
11377 returns a list of operating system(s) found and a large amount
11378 of information about them. In the vast majority of cases,
11379 a virtual machine only contains a single operating system.
11381 If the optional [~xml] parameter is given, then this function
11382 skips running the external virt-inspector program and just
11383 parses the given XML directly (which is expected to be XML
11384 produced from a previous run of virt-inspector). The list of
11385 names and connect URI are ignored in this case.
11387 This function can throw a wide variety of exceptions, for example
11388 if the external virt-inspector program cannot be found, or if
11389 it doesn't generate valid XML.
11393 (* Generate ocaml/guestfs_inspector.ml. *)
11394 let generate_ocaml_inspector_ml () =
11395 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11400 generate_types grammar;
11404 (* Misc functions which are used by the parser code below. *)
11405 let first_child = function
11406 | Xml.Element (_, _, c::_) -> c
11407 | Xml.Element (name, _, []) ->
11408 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11409 | Xml.PCData str ->
11410 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11412 let string_child_or_empty = function
11413 | Xml.Element (_, _, [Xml.PCData s]) -> s
11414 | Xml.Element (_, _, []) -> \"\"
11415 | Xml.Element (x, _, _) ->
11416 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11418 | Xml.PCData str ->
11419 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11421 let optional_child name xml =
11422 let children = Xml.children xml in
11424 Some (List.find (function
11425 | Xml.Element (n, _, _) when n = name -> true
11426 | _ -> false) children)
11430 let child name xml =
11431 match optional_child name xml with
11434 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11436 let attribute name xml =
11437 try Xml.attrib xml name
11438 with Xml.No_attribute _ ->
11439 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11443 generate_parsers grammar;
11447 (* Run external virt-inspector, then use parser to parse the XML. *)
11448 let inspect ?connect ?xml names =
11452 if names = [] then invalid_arg \"inspect: no names given\";
11453 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11454 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11456 let cmd = List.map Filename.quote cmd in
11457 let cmd = String.concat \" \" cmd in
11458 let chan = open_process_in cmd in
11459 let xml = Xml.parse_in chan in
11460 (match close_process_in chan with
11462 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11463 | WSIGNALED i | WSTOPPED i ->
11464 failwith (\"external virt-inspector command died or stopped on sig \" ^
11469 Xml.parse_string doc in
11470 parse_operatingsystems xml
11473 (* This is used to generate the src/MAX_PROC_NR file which
11474 * contains the maximum procedure number, a surrogate for the
11475 * ABI version number. See src/Makefile.am for the details.
11477 and generate_max_proc_nr () =
11478 let proc_nrs = List.map (
11479 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11480 ) daemon_functions in
11482 let max_proc_nr = List.fold_left max 0 proc_nrs in
11484 pr "%d\n" max_proc_nr
11486 let output_to filename k =
11487 let filename_new = filename ^ ".new" in
11488 chan := open_out filename_new;
11491 chan := Pervasives.stdout;
11493 (* Is the new file different from the current file? *)
11494 if Sys.file_exists filename && files_equal filename filename_new then
11495 unlink filename_new (* same, so skip it *)
11497 (* different, overwrite old one *)
11498 (try chmod filename 0o644 with Unix_error _ -> ());
11499 rename filename_new filename;
11500 chmod filename 0o444;
11501 printf "written %s\n%!" filename;
11504 let perror msg = function
11505 | Unix_error (err, _, _) ->
11506 eprintf "%s: %s\n" msg (error_message err)
11508 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11510 (* Main program. *)
11513 try openfile "HACKING" [O_RDWR] 0
11515 | Unix_error (ENOENT, _, _) ->
11517 You are probably running this from the wrong directory.
11518 Run it from the top source directory using the command
11523 perror "open: HACKING" exn;
11526 (* Acquire a lock so parallel builds won't try to run the generator
11527 * twice at the same time. Subsequent builds will wait for the first
11528 * one to finish. Note the lock is released implicitly when the
11531 (try lockf lock_fd F_LOCK 1
11533 perror "lock: HACKING" exn;
11536 check_functions ();
11538 output_to "src/guestfs_protocol.x" generate_xdr;
11539 output_to "src/guestfs-structs.h" generate_structs_h;
11540 output_to "src/guestfs-actions.h" generate_actions_h;
11541 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11542 output_to "src/guestfs-actions.c" generate_client_actions;
11543 output_to "src/guestfs-bindtests.c" generate_bindtests;
11544 output_to "src/guestfs-structs.pod" generate_structs_pod;
11545 output_to "src/guestfs-actions.pod" generate_actions_pod;
11546 output_to "src/guestfs-availability.pod" generate_availability_pod;
11547 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11548 output_to "src/libguestfs.syms" generate_linker_script;
11549 output_to "daemon/actions.h" generate_daemon_actions_h;
11550 output_to "daemon/stubs.c" generate_daemon_actions;
11551 output_to "daemon/names.c" generate_daemon_names;
11552 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11553 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11554 output_to "capitests/tests.c" generate_tests;
11555 output_to "fish/cmds.c" generate_fish_cmds;
11556 output_to "fish/completion.c" generate_fish_completion;
11557 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11558 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11559 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11560 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11561 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11562 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11563 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11564 output_to "perl/Guestfs.xs" generate_perl_xs;
11565 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11566 output_to "perl/bindtests.pl" generate_perl_bindtests;
11567 output_to "python/guestfs-py.c" generate_python_c;
11568 output_to "python/guestfs.py" generate_python_py;
11569 output_to "python/bindtests.py" generate_python_bindtests;
11570 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11571 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11572 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11576 let cols = cols_of_struct typ in
11577 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11578 output_to filename (generate_java_struct jtyp cols);
11581 output_to "java/Makefile.inc" generate_java_makefile_inc;
11582 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11583 output_to "java/Bindtests.java" generate_java_bindtests;
11584 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11585 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11586 output_to "csharp/Libguestfs.cs" generate_csharp;
11588 (* Always generate this file last, and unconditionally. It's used
11589 * by the Makefile to know when we must re-run the generator.
11591 let chan = open_out "src/stamp-generator" in
11592 fprintf chan "1\n";
11595 printf "generated %d lines of code\n" !lines