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, [String "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, [String "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 ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
797 The call returns a structure with four elements. The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet. The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
806 I<Note:> Don't use this call to test for availability
807 of features. Distro backports makes this unreliable. Use
808 C<guestfs_available> instead.");
810 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811 [InitNone, Always, TestOutputTrue (
812 [["set_selinux"; "true"];
814 "set SELinux enabled or disabled at appliance boot",
816 This sets the selinux flag that is passed to the appliance
817 at boot time. The default is C<selinux=0> (disabled).
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
825 ("get_selinux", (RBool "selinux", []), -1, [],
827 "get SELinux enabled flag",
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
835 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836 [InitNone, Always, TestOutputFalse (
837 [["set_trace"; "false"];
839 "enable or disable command traces",
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish. In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
855 ("get_trace", (RBool "trace", []), -1, [],
857 "get command trace enabled flag",
859 Return the command trace flag.");
861 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862 [InitNone, Always, TestOutputFalse (
863 [["set_direct"; "false"];
865 "enable or disable direct appliance mode",
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
875 You probably don't want to use this unless you know what you
878 The default is disabled.");
880 ("get_direct", (RBool "direct", []), -1, [],
882 "get direct appliance mode flag",
884 Return the direct appliance mode flag.");
886 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887 [InitNone, Always, TestOutputTrue (
888 [["set_recovery_proc"; "true"];
889 ["get_recovery_proc"]])],
890 "enable or disable the recovery process",
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process. The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself). In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
906 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
908 "get recovery process enabled flag",
910 Return the recovery process enabled flag.");
912 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
914 "add a drive specifying the QEMU block emulation to use",
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
919 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921 "add a drive read-only specifying the QEMU block emulation to use",
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
928 (* daemon_functions are any functions which cause some action
929 * to take place in the daemon.
932 let daemon_functions = [
933 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934 [InitEmpty, Always, TestOutput (
935 [["part_disk"; "/dev/sda"; "mbr"];
936 ["mkfs"; "ext2"; "/dev/sda1"];
937 ["mount"; "/dev/sda1"; "/"];
938 ["write_file"; "/new"; "new file contents"; "0"];
939 ["cat"; "/new"]], "new file contents")],
940 "mount a guest disk at a position in the filesystem",
942 Mount a guest disk at a position in the filesystem. Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest. If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
948 The rules are the same as for L<mount(2)>: A filesystem must
949 first be mounted on C</> before others can be mounted. Other
950 filesystems can only be mounted on directories which already
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
959 ("sync", (RErr, []), 2, [],
960 [ InitEmpty, Always, TestRun [["sync"]]],
961 "sync disks, writes are flushed through to the disk image",
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
969 ("touch", (RErr, [Pathname "path"]), 3, [],
970 [InitBasicFS, Always, TestOutputTrue (
972 ["exists"; "/new"]])],
973 "update file timestamps or create a new file",
975 Touch acts like the L<touch(1)> command. It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
979 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980 [InitISOFS, Always, TestOutput (
981 [["cat"; "/known-2"]], "abcdef\n")],
982 "list the contents of a file",
984 Return the contents of the file named C<path>.
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string). For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
991 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992 [], (* XXX Tricky to test because it depends on the exact format
993 * of the 'ls -l' command, which changes between F10 and F11.
995 "list the files in a directory (long format)",
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
1000 This command is mostly useful for interactive sessions. It
1001 is I<not> intended that you try to parse the output string.");
1003 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004 [InitBasicFS, Always, TestOutputList (
1006 ["touch"; "/newer"];
1007 ["touch"; "/newest"];
1008 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009 "list the files in a directory",
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd). The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1015 This command is mostly useful for interactive sessions. Programs
1016 should probably use C<guestfs_readdir> instead.");
1018 ("list_devices", (RStringList "devices", []), 7, [],
1019 [InitEmpty, Always, TestOutputListOfDevices (
1020 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021 "list the block devices",
1023 List all the block devices.
1025 The full block device names are returned, eg. C</dev/sda>");
1027 ("list_partitions", (RStringList "partitions", []), 8, [],
1028 [InitBasicFS, Always, TestOutputListOfDevices (
1029 [["list_partitions"]], ["/dev/sda1"]);
1030 InitEmpty, Always, TestOutputListOfDevices (
1031 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033 "list the partitions",
1035 List all the partitions detected on all block devices.
1037 The full partition device names are returned, eg. C</dev/sda1>
1039 This does not return logical volumes. For that you will need to
1040 call C<guestfs_lvs>.");
1042 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044 [["pvs"]], ["/dev/sda1"]);
1045 InitEmpty, Always, TestOutputListOfDevices (
1046 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047 ["pvcreate"; "/dev/sda1"];
1048 ["pvcreate"; "/dev/sda2"];
1049 ["pvcreate"; "/dev/sda3"];
1050 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051 "list the LVM physical volumes (PVs)",
1053 List all the physical volumes detected. This is the equivalent
1054 of the L<pvs(8)> command.
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1059 See also C<guestfs_pvs_full>.");
1061 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062 [InitBasicFSonLVM, Always, TestOutputList (
1064 InitEmpty, Always, TestOutputList (
1065 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066 ["pvcreate"; "/dev/sda1"];
1067 ["pvcreate"; "/dev/sda2"];
1068 ["pvcreate"; "/dev/sda3"];
1069 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070 ["vgcreate"; "VG2"; "/dev/sda3"];
1071 ["vgs"]], ["VG1"; "VG2"])],
1072 "list the LVM volume groups (VGs)",
1074 List all the volumes groups detected. This is the equivalent
1075 of the L<vgs(8)> command.
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1080 See also C<guestfs_vgs_full>.");
1082 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083 [InitBasicFSonLVM, Always, TestOutputList (
1084 [["lvs"]], ["/dev/VG/LV"]);
1085 InitEmpty, Always, TestOutputList (
1086 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087 ["pvcreate"; "/dev/sda1"];
1088 ["pvcreate"; "/dev/sda2"];
1089 ["pvcreate"; "/dev/sda3"];
1090 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091 ["vgcreate"; "VG2"; "/dev/sda3"];
1092 ["lvcreate"; "LV1"; "VG1"; "50"];
1093 ["lvcreate"; "LV2"; "VG1"; "50"];
1094 ["lvcreate"; "LV3"; "VG2"; "50"];
1095 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096 "list the LVM logical volumes (LVs)",
1098 List all the logical volumes detected. This is the equivalent
1099 of the L<lvs(8)> command.
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1104 See also C<guestfs_lvs_full>.");
1106 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107 [], (* XXX how to test? *)
1108 "list the LVM physical volumes (PVs)",
1110 List all the physical volumes detected. This is the equivalent
1111 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1113 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114 [], (* XXX how to test? *)
1115 "list the LVM volume groups (VGs)",
1117 List all the volumes groups detected. This is the equivalent
1118 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1120 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121 [], (* XXX how to test? *)
1122 "list the LVM logical volumes (LVs)",
1124 List all the logical volumes detected. This is the equivalent
1125 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1127 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128 [InitISOFS, Always, TestOutputList (
1129 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130 InitISOFS, Always, TestOutputList (
1131 [["read_lines"; "/empty"]], [])],
1132 "read file as lines",
1134 Return the contents of the file named C<path>.
1136 The file contents are returned as a list of lines. Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line). For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1144 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145 [], (* XXX Augeas code needs tests. *)
1146 "create a new Augeas handle",
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1152 You must call this before using any other C<guestfs_aug_*>
1155 C<root> is the filesystem root. C<root> must not be NULL,
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1164 =item C<AUG_SAVE_BACKUP> = 1
1166 Keep the original file with a C<.augsave> extension.
1168 =item C<AUG_SAVE_NEWFILE> = 2
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1173 =item C<AUG_TYPE_CHECK> = 4
1175 Typecheck lenses (can be expensive).
1177 =item C<AUG_NO_STDINC> = 8
1179 Do not use standard load path for modules.
1181 =item C<AUG_SAVE_NOOP> = 16
1183 Make save a no-op, just record what would have been changed.
1185 =item C<AUG_NO_LOAD> = 32
1187 Do not load the tree in C<guestfs_aug_init>.
1191 To close the handle, you can call C<guestfs_aug_close>.
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1195 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196 [], (* XXX Augeas code needs tests. *)
1197 "close the current Augeas handle",
1199 Close the current Augeas handle and free up any resources
1200 used by it. After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1204 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205 [], (* XXX Augeas code needs tests. *)
1206 "define an Augeas variable",
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1215 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216 [], (* XXX Augeas code needs tests. *)
1217 "define an Augeas node",
1219 Defines a variable C<name> whose value is the result of
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1230 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231 [], (* XXX Augeas code needs tests. *)
1232 "look up the value of an Augeas path",
1234 Look up the value associated with C<path>. If C<path>
1235 matches exactly one node, the C<value> is returned.");
1237 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238 [], (* XXX Augeas code needs tests. *)
1239 "set Augeas path to value",
1241 Set the value associated with C<path> to C<value>.");
1243 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244 [], (* XXX Augeas code needs tests. *)
1245 "insert a sibling Augeas node",
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1255 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256 [], (* XXX Augeas code needs tests. *)
1257 "remove an Augeas path",
1259 Remove C<path> and all of its children.
1261 On success this returns the number of entries which were removed.");
1263 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264 [], (* XXX Augeas code needs tests. *)
1267 Move the node C<src> to C<dest>. C<src> must match exactly
1268 one node. C<dest> is overwritten if it exists.");
1270 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271 [], (* XXX Augeas code needs tests. *)
1272 "return Augeas nodes which match augpath",
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1278 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279 [], (* XXX Augeas code needs tests. *)
1280 "write all pending Augeas changes to disk",
1282 This writes all pending changes to disk.
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1287 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1289 "load files into the tree",
1291 Load files into the tree.
1293 See C<aug_load> in the Augeas documentation for the full gory
1296 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297 [], (* XXX Augeas code needs tests. *)
1298 "list Augeas nodes under augpath",
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1303 ("rm", (RErr, [Pathname "path"]), 29, [],
1304 [InitBasicFS, Always, TestRun
1307 InitBasicFS, Always, TestLastFail
1309 InitBasicFS, Always, TestLastFail
1314 Remove the single file C<path>.");
1316 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317 [InitBasicFS, Always, TestRun
1320 InitBasicFS, Always, TestLastFail
1321 [["rmdir"; "/new"]];
1322 InitBasicFS, Always, TestLastFail
1324 ["rmdir"; "/new"]]],
1325 "remove a directory",
1327 Remove the single directory C<path>.");
1329 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330 [InitBasicFS, Always, TestOutputFalse
1332 ["mkdir"; "/new/foo"];
1333 ["touch"; "/new/foo/bar"];
1335 ["exists"; "/new"]]],
1336 "remove a file or directory recursively",
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory. This is like the C<rm -rf> shell
1342 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343 [InitBasicFS, Always, TestOutputTrue
1345 ["is_dir"; "/new"]];
1346 InitBasicFS, Always, TestLastFail
1347 [["mkdir"; "/new/foo/bar"]]],
1348 "create a directory",
1350 Create a directory named C<path>.");
1352 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353 [InitBasicFS, Always, TestOutputTrue
1354 [["mkdir_p"; "/new/foo/bar"];
1355 ["is_dir"; "/new/foo/bar"]];
1356 InitBasicFS, Always, TestOutputTrue
1357 [["mkdir_p"; "/new/foo/bar"];
1358 ["is_dir"; "/new/foo"]];
1359 InitBasicFS, Always, TestOutputTrue
1360 [["mkdir_p"; "/new/foo/bar"];
1361 ["is_dir"; "/new"]];
1362 (* Regression tests for RHBZ#503133: *)
1363 InitBasicFS, Always, TestRun
1365 ["mkdir_p"; "/new"]];
1366 InitBasicFS, Always, TestLastFail
1368 ["mkdir_p"; "/new"]]],
1369 "create a directory and parents",
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary. This is like the C<mkdir -p> shell command.");
1374 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375 [], (* XXX Need stat command to test *)
1378 Change the mode (permissions) of C<path> to C<mode>. Only
1379 numeric modes are supported.
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1385 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386 [], (* XXX Need stat command to test *)
1387 "change file owner and group",
1389 Change the file owner to C<owner> and group to C<group>.
1391 Only numeric uid and gid are supported. If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1395 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396 [InitISOFS, Always, TestOutputTrue (
1397 [["exists"; "/empty"]]);
1398 InitISOFS, Always, TestOutputTrue (
1399 [["exists"; "/directory"]])],
1400 "test if file or directory exists",
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1407 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408 [InitISOFS, Always, TestOutputTrue (
1409 [["is_file"; "/known-1"]]);
1410 InitISOFS, Always, TestOutputFalse (
1411 [["is_file"; "/directory"]])],
1412 "test if file exists",
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name. Note that it returns false for
1416 other objects like directories.
1418 See also C<guestfs_stat>.");
1420 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421 [InitISOFS, Always, TestOutputFalse (
1422 [["is_dir"; "/known-3"]]);
1423 InitISOFS, Always, TestOutputTrue (
1424 [["is_dir"; "/directory"]])],
1425 "test if file exists",
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name. Note that it returns false for
1429 other objects like files.
1431 See also C<guestfs_stat>.");
1433 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434 [InitEmpty, Always, TestOutputListOfDevices (
1435 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436 ["pvcreate"; "/dev/sda1"];
1437 ["pvcreate"; "/dev/sda2"];
1438 ["pvcreate"; "/dev/sda3"];
1439 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440 "create an LVM physical volume",
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1446 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447 [InitEmpty, Always, TestOutputList (
1448 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449 ["pvcreate"; "/dev/sda1"];
1450 ["pvcreate"; "/dev/sda2"];
1451 ["pvcreate"; "/dev/sda3"];
1452 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453 ["vgcreate"; "VG2"; "/dev/sda3"];
1454 ["vgs"]], ["VG1"; "VG2"])],
1455 "create an LVM volume group",
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1460 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461 [InitEmpty, Always, TestOutputList (
1462 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463 ["pvcreate"; "/dev/sda1"];
1464 ["pvcreate"; "/dev/sda2"];
1465 ["pvcreate"; "/dev/sda3"];
1466 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467 ["vgcreate"; "VG2"; "/dev/sda3"];
1468 ["lvcreate"; "LV1"; "VG1"; "50"];
1469 ["lvcreate"; "LV2"; "VG1"; "50"];
1470 ["lvcreate"; "LV3"; "VG2"; "50"];
1471 ["lvcreate"; "LV4"; "VG2"; "50"];
1472 ["lvcreate"; "LV5"; "VG2"; "50"];
1474 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476 "create an LVM volume group",
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1481 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482 [InitEmpty, Always, TestOutput (
1483 [["part_disk"; "/dev/sda"; "mbr"];
1484 ["mkfs"; "ext2"; "/dev/sda1"];
1485 ["mount_options"; ""; "/dev/sda1"; "/"];
1486 ["write_file"; "/new"; "new file contents"; "0"];
1487 ["cat"; "/new"]], "new file contents")],
1488 "make a filesystem",
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume). The filesystem type is C<fstype>, for
1494 ("sfdisk", (RErr, [Device "device";
1495 Int "cyls"; Int "heads"; Int "sectors";
1496 StringList "lines"]), 43, [DangerWillRobinson],
1498 "create partitions on a block device",
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1503 C<device> should be a block device, for example C</dev/sda>.
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted. Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1513 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1514 information refer to the L<sfdisk(8)> manpage.
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1523 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524 [InitBasicFS, Always, TestOutput (
1525 [["write_file"; "/new"; "new file contents"; "0"];
1526 ["cat"; "/new"]], "new file contents");
1527 InitBasicFS, Always, TestOutput (
1528 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529 ["cat"; "/new"]], "\nnew file contents\n");
1530 InitBasicFS, Always, TestOutput (
1531 [["write_file"; "/new"; "\n\n"; "0"];
1532 ["cat"; "/new"]], "\n\n");
1533 InitBasicFS, Always, TestOutput (
1534 [["write_file"; "/new"; ""; "0"];
1535 ["cat"; "/new"]], "");
1536 InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "\n\n\n"; "0"];
1538 ["cat"; "/new"]], "\n\n\n");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\n"; "0"];
1541 ["cat"; "/new"]], "\n")],
1544 This call creates a file called C<path>. The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version. In the meantime
1555 use C<guestfs_upload>.");
1557 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558 [InitEmpty, Always, TestOutputListOfDevices (
1559 [["part_disk"; "/dev/sda"; "mbr"];
1560 ["mkfs"; "ext2"; "/dev/sda1"];
1561 ["mount_options"; ""; "/dev/sda1"; "/"];
1562 ["mounts"]], ["/dev/sda1"]);
1563 InitEmpty, Always, TestOutputList (
1564 [["part_disk"; "/dev/sda"; "mbr"];
1565 ["mkfs"; "ext2"; "/dev/sda1"];
1566 ["mount_options"; ""; "/dev/sda1"; "/"];
1569 "unmount a filesystem",
1571 This unmounts the given filesystem. The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1575 ("mounts", (RStringList "devices", []), 46, [],
1576 [InitBasicFS, Always, TestOutputListOfDevices (
1577 [["mounts"]], ["/dev/sda1"])],
1578 "show mounted filesystems",
1580 This returns the list of currently mounted filesystems. It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1583 Some internal mounts are not shown.
1585 See also: C<guestfs_mountpoints>");
1587 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588 [InitBasicFS, Always, TestOutputList (
1591 (* check that umount_all can unmount nested mounts correctly: *)
1592 InitEmpty, Always, TestOutputList (
1593 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594 ["mkfs"; "ext2"; "/dev/sda1"];
1595 ["mkfs"; "ext2"; "/dev/sda2"];
1596 ["mkfs"; "ext2"; "/dev/sda3"];
1597 ["mount_options"; ""; "/dev/sda1"; "/"];
1599 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600 ["mkdir"; "/mp1/mp2"];
1601 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602 ["mkdir"; "/mp1/mp2/mp3"];
1605 "unmount all filesystems",
1607 This unmounts all mounted filesystems.
1609 Some internal mounts are not unmounted by this call.");
1611 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1613 "remove all LVM LVs, VGs and PVs",
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1618 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619 [InitISOFS, Always, TestOutput (
1620 [["file"; "/empty"]], "empty");
1621 InitISOFS, Always, TestOutput (
1622 [["file"; "/known-1"]], "ASCII text");
1623 InitISOFS, Always, TestLastFail (
1624 [["file"; "/notexists"]])],
1625 "determine file type",
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file. This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1631 This call will also transparently look inside various types
1634 The exact command which runs is C<file -zbsL path>. Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1638 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639 [InitBasicFS, Always, TestOutput (
1640 [["upload"; "test-command"; "/test-command"];
1641 ["chmod"; "0o755"; "/test-command"];
1642 ["command"; "/test-command 1"]], "Result1");
1643 InitBasicFS, Always, TestOutput (
1644 [["upload"; "test-command"; "/test-command"];
1645 ["chmod"; "0o755"; "/test-command"];
1646 ["command"; "/test-command 2"]], "Result2\n");
1647 InitBasicFS, Always, TestOutput (
1648 [["upload"; "test-command"; "/test-command"];
1649 ["chmod"; "0o755"; "/test-command"];
1650 ["command"; "/test-command 3"]], "\nResult3");
1651 InitBasicFS, Always, TestOutput (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command"; "/test-command 4"]], "\nResult4\n");
1655 InitBasicFS, Always, TestOutput (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command"; "/test-command 5"]], "\nResult5\n\n");
1659 InitBasicFS, Always, TestOutput (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663 InitBasicFS, Always, TestOutput (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command"; "/test-command 7"]], "");
1667 InitBasicFS, Always, TestOutput (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command"; "/test-command 8"]], "\n");
1671 InitBasicFS, Always, TestOutput (
1672 [["upload"; "test-command"; "/test-command"];
1673 ["chmod"; "0o755"; "/test-command"];
1674 ["command"; "/test-command 9"]], "\n\n");
1675 InitBasicFS, Always, TestOutput (
1676 [["upload"; "test-command"; "/test-command"];
1677 ["chmod"; "0o755"; "/test-command"];
1678 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679 InitBasicFS, Always, TestOutput (
1680 [["upload"; "test-command"; "/test-command"];
1681 ["chmod"; "0o755"; "/test-command"];
1682 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683 InitBasicFS, Always, TestLastFail (
1684 [["upload"; "test-command"; "/test-command"];
1685 ["chmod"; "0o755"; "/test-command"];
1686 ["command"; "/test-command"]])],
1687 "run a command from the guest filesystem",
1689 This call runs a command from the guest filesystem. The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters. The list must be
1697 non-empty (ie. must contain a program name). Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1701 The return value is anything printed to I<stdout> by
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message. The error message
1706 string is the content of I<stderr> from the command.
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>. If you require a program from
1710 another location, you should provide the full path in the
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places. It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1719 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720 [InitBasicFS, Always, TestOutputList (
1721 [["upload"; "test-command"; "/test-command"];
1722 ["chmod"; "0o755"; "/test-command"];
1723 ["command_lines"; "/test-command 1"]], ["Result1"]);
1724 InitBasicFS, Always, TestOutputList (
1725 [["upload"; "test-command"; "/test-command"];
1726 ["chmod"; "0o755"; "/test-command"];
1727 ["command_lines"; "/test-command 2"]], ["Result2"]);
1728 InitBasicFS, Always, TestOutputList (
1729 [["upload"; "test-command"; "/test-command"];
1730 ["chmod"; "0o755"; "/test-command"];
1731 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732 InitBasicFS, Always, TestOutputList (
1733 [["upload"; "test-command"; "/test-command"];
1734 ["chmod"; "0o755"; "/test-command"];
1735 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736 InitBasicFS, Always, TestOutputList (
1737 [["upload"; "test-command"; "/test-command"];
1738 ["chmod"; "0o755"; "/test-command"];
1739 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740 InitBasicFS, Always, TestOutputList (
1741 [["upload"; "test-command"; "/test-command"];
1742 ["chmod"; "0o755"; "/test-command"];
1743 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744 InitBasicFS, Always, TestOutputList (
1745 [["upload"; "test-command"; "/test-command"];
1746 ["chmod"; "0o755"; "/test-command"];
1747 ["command_lines"; "/test-command 7"]], []);
1748 InitBasicFS, Always, TestOutputList (
1749 [["upload"; "test-command"; "/test-command"];
1750 ["chmod"; "0o755"; "/test-command"];
1751 ["command_lines"; "/test-command 8"]], [""]);
1752 InitBasicFS, Always, TestOutputList (
1753 [["upload"; "test-command"; "/test-command"];
1754 ["chmod"; "0o755"; "/test-command"];
1755 ["command_lines"; "/test-command 9"]], ["";""]);
1756 InitBasicFS, Always, TestOutputList (
1757 [["upload"; "test-command"; "/test-command"];
1758 ["chmod"; "0o755"; "/test-command"];
1759 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760 InitBasicFS, Always, TestOutputList (
1761 [["upload"; "test-command"; "/test-command"];
1762 ["chmod"; "0o755"; "/test-command"];
1763 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764 "run a command, returning lines",
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1769 See also: C<guestfs_sh_lines>");
1771 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772 [InitISOFS, Always, TestOutputStruct (
1773 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774 "get file information",
1776 Returns file information for the given C<path>.
1778 This is the same as the C<stat(2)> system call.");
1780 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781 [InitISOFS, Always, TestOutputStruct (
1782 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783 "get file information for a symbolic link",
1785 Returns file information for the given C<path>.
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1791 This is the same as the C<lstat(2)> system call.");
1793 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794 [InitISOFS, Always, TestOutputStruct (
1795 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796 "get file system statistics",
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1802 This is the same as the C<statvfs(2)> system call.");
1804 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1806 "get ext2/ext3/ext4 superblock details",
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1811 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1812 manpage for more details. The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1816 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817 [InitEmpty, Always, TestOutputTrue (
1818 [["blockdev_setro"; "/dev/sda"];
1819 ["blockdev_getro"; "/dev/sda"]])],
1820 "set block device to read-only",
1822 Sets the block device named C<device> to read-only.
1824 This uses the L<blockdev(8)> command.");
1826 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827 [InitEmpty, Always, TestOutputFalse (
1828 [["blockdev_setrw"; "/dev/sda"];
1829 ["blockdev_getro"; "/dev/sda"]])],
1830 "set block device to read-write",
1832 Sets the block device named C<device> to read-write.
1834 This uses the L<blockdev(8)> command.");
1836 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837 [InitEmpty, Always, TestOutputTrue (
1838 [["blockdev_setro"; "/dev/sda"];
1839 ["blockdev_getro"; "/dev/sda"]])],
1840 "is block device set to read-only",
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1845 This uses the L<blockdev(8)> command.");
1847 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848 [InitEmpty, Always, TestOutputInt (
1849 [["blockdev_getss"; "/dev/sda"]], 512)],
1850 "get sectorsize of block device",
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1858 This uses the L<blockdev(8)> command.");
1860 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861 [InitEmpty, Always, TestOutputInt (
1862 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863 "get blocksize of block device",
1865 This returns the block size of a device.
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1870 This uses the L<blockdev(8)> command.");
1872 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1874 "set blocksize of block device",
1876 This sets the block size of a device.
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1881 This uses the L<blockdev(8)> command.");
1883 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884 [InitEmpty, Always, TestOutputInt (
1885 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886 "get total size of device in 512-byte sectors",
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1895 This uses the L<blockdev(8)> command.");
1897 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898 [InitEmpty, Always, TestOutputInt (
1899 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900 "get total size of device in bytes",
1902 This returns the size of the device in bytes.
1904 See also C<guestfs_blockdev_getsz>.
1906 This uses the L<blockdev(8)> command.");
1908 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909 [InitEmpty, Always, TestRun
1910 [["blockdev_flushbufs"; "/dev/sda"]]],
1911 "flush device buffers",
1913 This tells the kernel to flush internal buffers associated
1916 This uses the L<blockdev(8)> command.");
1918 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919 [InitEmpty, Always, TestRun
1920 [["blockdev_rereadpt"; "/dev/sda"]]],
1921 "reread partition table",
1923 Reread the partition table on C<device>.
1925 This uses the L<blockdev(8)> command.");
1927 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928 [InitBasicFS, Always, TestOutput (
1929 (* Pick a file from cwd which isn't likely to change. *)
1930 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931 ["checksum"; "md5"; "/COPYING.LIB"]],
1932 Digest.to_hex (Digest.file "COPYING.LIB"))],
1933 "upload a file from the local machine",
1935 Upload local file C<filename> to C<remotefilename> on the
1938 C<filename> can also be a named pipe.
1940 See also C<guestfs_download>.");
1942 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943 [InitBasicFS, Always, TestOutput (
1944 (* Pick a file from cwd which isn't likely to change. *)
1945 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947 ["upload"; "testdownload.tmp"; "/upload"];
1948 ["checksum"; "md5"; "/upload"]],
1949 Digest.to_hex (Digest.file "COPYING.LIB"))],
1950 "download a file to the local machine",
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1955 C<filename> can also be a named pipe.
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1959 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960 [InitISOFS, Always, TestOutput (
1961 [["checksum"; "crc"; "/known-3"]], "2891671662");
1962 InitISOFS, Always, TestLastFail (
1963 [["checksum"; "crc"; "/notexists"]]);
1964 InitISOFS, Always, TestOutput (
1965 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966 InitISOFS, Always, TestOutput (
1967 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968 InitISOFS, Always, TestOutput (
1969 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970 InitISOFS, Always, TestOutput (
1971 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972 InitISOFS, Always, TestOutput (
1973 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974 InitISOFS, Always, TestOutput (
1975 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976 "compute MD5, SHAx or CRC checksum of file",
1978 This call computes the MD5, SHAx or CRC checksum of the
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1993 Compute the MD5 hash (using the C<md5sum> program).
1997 Compute the SHA1 hash (using the C<sha1sum> program).
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2017 The checksum is returned as a printable string.");
2019 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020 [InitBasicFS, Always, TestOutput (
2021 [["tar_in"; "../images/helloworld.tar"; "/"];
2022 ["cat"; "/hello"]], "hello\n")],
2023 "unpack tarfile to directory",
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2031 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2033 "pack directory into tarfile",
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_out>.");
2041 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042 [InitBasicFS, Always, TestOutput (
2043 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044 ["cat"; "/hello"]], "hello\n")],
2045 "unpack compressed tarball to directory",
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2052 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2054 "pack directory into compressed tarball",
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2061 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062 [InitBasicFS, Always, TestLastFail (
2064 ["mount_ro"; "/dev/sda1"; "/"];
2065 ["touch"; "/new"]]);
2066 InitBasicFS, Always, TestOutput (
2067 [["write_file"; "/new"; "data"; "0"];
2069 ["mount_ro"; "/dev/sda1"; "/"];
2070 ["cat"; "/new"]], "data")],
2071 "mount a guest disk, read-only",
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2076 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2078 "mount a guest disk with mount options",
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2084 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2086 "mount a guest disk with mount options and vfstype",
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2092 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2094 "debugging and internals",
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2100 There is no comprehensive help for this command. You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2104 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105 [InitEmpty, Always, TestOutputList (
2106 [["part_disk"; "/dev/sda"; "mbr"];
2107 ["pvcreate"; "/dev/sda1"];
2108 ["vgcreate"; "VG"; "/dev/sda1"];
2109 ["lvcreate"; "LV1"; "VG"; "50"];
2110 ["lvcreate"; "LV2"; "VG"; "50"];
2111 ["lvremove"; "/dev/VG/LV1"];
2112 ["lvs"]], ["/dev/VG/LV2"]);
2113 InitEmpty, Always, TestOutputList (
2114 [["part_disk"; "/dev/sda"; "mbr"];
2115 ["pvcreate"; "/dev/sda1"];
2116 ["vgcreate"; "VG"; "/dev/sda1"];
2117 ["lvcreate"; "LV1"; "VG"; "50"];
2118 ["lvcreate"; "LV2"; "VG"; "50"];
2119 ["lvremove"; "/dev/VG"];
2121 InitEmpty, Always, TestOutputList (
2122 [["part_disk"; "/dev/sda"; "mbr"];
2123 ["pvcreate"; "/dev/sda1"];
2124 ["vgcreate"; "VG"; "/dev/sda1"];
2125 ["lvcreate"; "LV1"; "VG"; "50"];
2126 ["lvcreate"; "LV2"; "VG"; "50"];
2127 ["lvremove"; "/dev/VG"];
2129 "remove an LVM logical volume",
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2137 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138 [InitEmpty, Always, TestOutputList (
2139 [["part_disk"; "/dev/sda"; "mbr"];
2140 ["pvcreate"; "/dev/sda1"];
2141 ["vgcreate"; "VG"; "/dev/sda1"];
2142 ["lvcreate"; "LV1"; "VG"; "50"];
2143 ["lvcreate"; "LV2"; "VG"; "50"];
2146 InitEmpty, Always, TestOutputList (
2147 [["part_disk"; "/dev/sda"; "mbr"];
2148 ["pvcreate"; "/dev/sda1"];
2149 ["vgcreate"; "VG"; "/dev/sda1"];
2150 ["lvcreate"; "LV1"; "VG"; "50"];
2151 ["lvcreate"; "LV2"; "VG"; "50"];
2154 "remove an LVM volume group",
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2158 This also forcibly removes all logical volumes in the volume
2161 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162 [InitEmpty, Always, TestOutputListOfDevices (
2163 [["part_disk"; "/dev/sda"; "mbr"];
2164 ["pvcreate"; "/dev/sda1"];
2165 ["vgcreate"; "VG"; "/dev/sda1"];
2166 ["lvcreate"; "LV1"; "VG"; "50"];
2167 ["lvcreate"; "LV2"; "VG"; "50"];
2169 ["pvremove"; "/dev/sda1"];
2171 InitEmpty, Always, TestOutputListOfDevices (
2172 [["part_disk"; "/dev/sda"; "mbr"];
2173 ["pvcreate"; "/dev/sda1"];
2174 ["vgcreate"; "VG"; "/dev/sda1"];
2175 ["lvcreate"; "LV1"; "VG"; "50"];
2176 ["lvcreate"; "LV2"; "VG"; "50"];
2178 ["pvremove"; "/dev/sda1"];
2180 InitEmpty, Always, TestOutputListOfDevices (
2181 [["part_disk"; "/dev/sda"; "mbr"];
2182 ["pvcreate"; "/dev/sda1"];
2183 ["vgcreate"; "VG"; "/dev/sda1"];
2184 ["lvcreate"; "LV1"; "VG"; "50"];
2185 ["lvcreate"; "LV2"; "VG"; "50"];
2187 ["pvremove"; "/dev/sda1"];
2189 "remove an LVM physical volume",
2191 This wipes a physical volume C<device> so that LVM will no longer
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2198 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199 [InitBasicFS, Always, TestOutput (
2200 [["set_e2label"; "/dev/sda1"; "testlabel"];
2201 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202 "set the ext2/3/4 filesystem label",
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>. Filesystem labels are limited to
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2211 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2213 "get the ext2/3/4 filesystem label",
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2218 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219 (let uuid = uuidgen () in
2220 [InitBasicFS, Always, TestOutput (
2221 [["set_e2uuid"; "/dev/sda1"; uuid];
2222 ["get_e2uuid"; "/dev/sda1"]], uuid);
2223 InitBasicFS, Always, TestOutput (
2224 [["set_e2uuid"; "/dev/sda1"; "clear"];
2225 ["get_e2uuid"; "/dev/sda1"]], "");
2226 (* We can't predict what UUIDs will be, so just check the commands run. *)
2227 InitBasicFS, Always, TestRun (
2228 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229 InitBasicFS, Always, TestRun (
2230 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231 "set the ext2/3/4 filesystem UUID",
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>. The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2241 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2243 "get the ext2/3/4 filesystem UUID",
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2248 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249 [InitBasicFS, Always, TestOutputInt (
2250 [["umount"; "/dev/sda1"];
2251 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252 InitBasicFS, Always, TestOutputInt (
2253 [["umount"; "/dev/sda1"];
2254 ["zero"; "/dev/sda1"];
2255 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256 "run the filesystem checker",
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2261 The returned integer is the status. See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2270 Multiple status codes can be summed together.
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2279 Checking or repairing NTFS volumes is not supported
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2286 ("zero", (RErr, [Device "device"]), 85, [],
2287 [InitBasicFS, Always, TestOutput (
2288 [["umount"; "/dev/sda1"];
2289 ["zero"; "/dev/sda1"];
2290 ["file"; "/dev/sda1"]], "data")],
2291 "write zeroes to the device",
2293 This command writes zeroes over the first few blocks of C<device>.
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device). It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2299 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2301 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302 (* Test disabled because grub-install incompatible with virtio-blk driver.
2303 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2305 [InitBasicFS, Disabled, TestOutputTrue (
2306 [["grub_install"; "/"; "/dev/sda1"];
2307 ["is_dir"; "/boot"]])],
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2313 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314 [InitBasicFS, Always, TestOutput (
2315 [["write_file"; "/old"; "file content"; "0"];
2316 ["cp"; "/old"; "/new"];
2317 ["cat"; "/new"]], "file content");
2318 InitBasicFS, Always, TestOutputTrue (
2319 [["write_file"; "/old"; "file content"; "0"];
2320 ["cp"; "/old"; "/new"];
2321 ["is_file"; "/old"]]);
2322 InitBasicFS, Always, TestOutput (
2323 [["write_file"; "/old"; "file content"; "0"];
2325 ["cp"; "/old"; "/dir/new"];
2326 ["cat"; "/dir/new"]], "file content")],
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2332 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333 [InitBasicFS, Always, TestOutput (
2334 [["mkdir"; "/olddir"];
2335 ["mkdir"; "/newdir"];
2336 ["write_file"; "/olddir/file"; "file content"; "0"];
2337 ["cp_a"; "/olddir"; "/newdir"];
2338 ["cat"; "/newdir/olddir/file"]], "file content")],
2339 "copy a file or directory recursively",
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2344 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345 [InitBasicFS, Always, TestOutput (
2346 [["write_file"; "/old"; "file content"; "0"];
2347 ["mv"; "/old"; "/new"];
2348 ["cat"; "/new"]], "file content");
2349 InitBasicFS, Always, TestOutputFalse (
2350 [["write_file"; "/old"; "file content"; "0"];
2351 ["mv"; "/old"; "/new"];
2352 ["is_file"; "/old"]])],
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2358 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359 [InitEmpty, Always, TestRun (
2360 [["drop_caches"; "3"]])],
2361 "drop kernel page cache, dentries and inodes",
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches. The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2368 Setting C<whattodrop> to 3 should drop everything.
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2373 ("dmesg", (RString "kmsgs", []), 91, [],
2374 [InitEmpty, Always, TestRun (
2376 "return kernel messages",
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel. This is sometimes useful for extended
2380 debugging of problems.
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2387 ("ping_daemon", (RErr, []), 92, [],
2388 [InitEmpty, Always, TestRun (
2389 [["ping_daemon"]])],
2390 "ping the guest daemon",
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess. Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2397 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398 [InitBasicFS, Always, TestOutputTrue (
2399 [["write_file"; "/file1"; "contents of a file"; "0"];
2400 ["cp"; "/file1"; "/file2"];
2401 ["equal"; "/file1"; "/file2"]]);
2402 InitBasicFS, Always, TestOutputFalse (
2403 [["write_file"; "/file1"; "contents of a file"; "0"];
2404 ["write_file"; "/file2"; "contents of another file"; "0"];
2405 ["equal"; "/file1"; "/file2"]]);
2406 InitBasicFS, Always, TestLastFail (
2407 [["equal"; "/file1"; "/file2"]])],
2408 "test if two files have equal contents",
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2413 The external L<cmp(1)> program is used for the comparison.");
2415 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416 [InitISOFS, Always, TestOutputList (
2417 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418 InitISOFS, Always, TestOutputList (
2419 [["strings"; "/empty"]], [])],
2420 "print the printable strings in a file",
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2425 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426 [InitISOFS, Always, TestOutputList (
2427 [["strings_e"; "b"; "/known-5"]], []);
2428 InitBasicFS, Disabled, TestOutputList (
2429 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431 "print the printable strings in a file",
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2436 See the L<strings(1)> manpage for the full list of encodings.
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2441 The returned strings are transcoded to UTF-8.");
2443 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444 [InitISOFS, Always, TestOutput (
2445 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2446 (* Test for RHBZ#501888c2 regression which caused large hexdump
2447 * commands to segfault.
2449 InitISOFS, Always, TestRun (
2450 [["hexdump"; "/100krandom"]])],
2451 "dump a file in hexadecimal",
2453 This runs C<hexdump -C> on the given C<path>. The result is
2454 the human-readable, canonical hex dump of the file.");
2456 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457 [InitNone, Always, TestOutput (
2458 [["part_disk"; "/dev/sda"; "mbr"];
2459 ["mkfs"; "ext3"; "/dev/sda1"];
2460 ["mount_options"; ""; "/dev/sda1"; "/"];
2461 ["write_file"; "/new"; "test file"; "0"];
2462 ["umount"; "/dev/sda1"];
2463 ["zerofree"; "/dev/sda1"];
2464 ["mount_options"; ""; "/dev/sda1"; "/"];
2465 ["cat"; "/new"]], "test file")],
2466 "zero unused inodes and disk blocks on ext2/3 filesystem",
2468 This runs the I<zerofree> program on C<device>. This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2473 You should B<not> run this program if the filesystem is
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2479 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2481 "resize an LVM physical volume",
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2486 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487 Int "cyls"; Int "heads"; Int "sectors";
2488 String "line"]), 99, [DangerWillRobinson],
2490 "modify a single partition on a block device",
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2495 For other parameters, see C<guestfs_sfdisk>. You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2498 See also: C<guestfs_part_add>");
2500 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2502 "display the partition table",
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command. It is
2506 not intended to be parsed.
2508 See also: C<guestfs_part_list>");
2510 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2512 "display the kernel geometry",
2514 This displays the kernel's idea of the geometry of C<device>.
2516 The result is in human-readable format, and not designed to
2519 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2521 "display the disk geometry from the partition table",
2523 This displays the disk geometry of C<device> read from the
2524 partition table. Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2528 The result is in human-readable format, and not designed to
2531 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2533 "activate or deactivate all volume groups",
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2539 then those devices disappear.
2541 This command is the same as running C<vgchange -a y|n>");
2543 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2545 "activate or deactivate some volume groups",
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2551 then those devices disappear.
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2558 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559 [InitNone, Always, TestOutput (
2560 [["part_disk"; "/dev/sda"; "mbr"];
2561 ["pvcreate"; "/dev/sda1"];
2562 ["vgcreate"; "VG"; "/dev/sda1"];
2563 ["lvcreate"; "LV"; "VG"; "10"];
2564 ["mkfs"; "ext2"; "/dev/VG/LV"];
2565 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566 ["write_file"; "/new"; "test content"; "0"];
2568 ["lvresize"; "/dev/VG/LV"; "20"];
2569 ["e2fsck_f"; "/dev/VG/LV"];
2570 ["resize2fs"; "/dev/VG/LV"];
2571 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572 ["cat"; "/new"]], "test content")],
2573 "resize an LVM logical volume",
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>. When reducing, data in the reduced part
2579 ("resize2fs", (RErr, [Device "device"]), 106, [],
2580 [], (* lvresize tests this *)
2581 "resize an ext2/ext3 filesystem",
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command. For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2592 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593 [InitBasicFS, Always, TestOutputList (
2594 [["find"; "/"]], ["lost+found"]);
2595 InitBasicFS, Always, TestOutputList (
2599 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600 InitBasicFS, Always, TestOutputList (
2601 [["mkdir_p"; "/a/b/c"];
2602 ["touch"; "/a/b/c/d"];
2603 ["find"; "/a/b/"]], ["c"; "c/d"])],
2604 "find all files and directories",
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>. It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2611 This returns a list of strings I<without any prefix>. Thus
2612 if the directory structure was:
2618 then the returned list from C<guestfs_find> C</tmp> would be
2626 If C<directory> is not a directory, then this command returns
2629 The returned list is sorted.
2631 See also C<guestfs_find0>.");
2633 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634 [], (* lvresize tests this *)
2635 "check an ext2/ext3 filesystem",
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.). Normally you should use C<guestfs_fsck>.");
2644 ("sleep", (RErr, [Int "secs"]), 109, [],
2645 [InitNone, Always, TestRun (
2647 "sleep for some seconds",
2649 Sleep for C<secs> seconds.");
2651 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652 [InitNone, Always, TestOutputInt (
2653 [["part_disk"; "/dev/sda"; "mbr"];
2654 ["mkfs"; "ntfs"; "/dev/sda1"];
2655 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656 InitNone, Always, TestOutputInt (
2657 [["part_disk"; "/dev/sda"; "mbr"];
2658 ["mkfs"; "ext2"; "/dev/sda1"];
2659 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660 "probe NTFS volume",
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability. (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2666 C<rw> is a boolean flag. Set it to true if you want to test
2667 if the volume can be mounted read-write. Set it to false if
2668 you want to test if the volume can be mounted read-only.
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2674 ("sh", (RString "output", [String "command"]), 111, [],
2675 [], (* XXX needs tests *)
2676 "run a command via the shell",
2678 This call runs a command from the guest filesystem via the
2681 This is like C<guestfs_command>, but passes the command to:
2683 /bin/sh -c \"command\"
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2689 All the provisos about C<guestfs_command> apply to this call.");
2691 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692 [], (* XXX needs tests *)
2693 "run a command via the shell returning lines",
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2698 See also: C<guestfs_command_lines>");
2700 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702 * code in stubs.c, since all valid glob patterns must start with "/".
2703 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2705 [InitBasicFS, Always, TestOutputList (
2706 [["mkdir_p"; "/a/b/c"];
2707 ["touch"; "/a/b/c/d"];
2708 ["touch"; "/a/b/c/e"];
2709 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710 InitBasicFS, Always, TestOutputList (
2711 [["mkdir_p"; "/a/b/c"];
2712 ["touch"; "/a/b/c/d"];
2713 ["touch"; "/a/b/c/e"];
2714 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715 InitBasicFS, Always, TestOutputList (
2716 [["mkdir_p"; "/a/b/c"];
2717 ["touch"; "/a/b/c/d"];
2718 ["touch"; "/a/b/c/e"];
2719 ["glob_expand"; "/a/*/x/*"]], [])],
2720 "expand a wildcard path",
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2733 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735 [["scrub_device"; "/dev/sdc"]])],
2736 "scrub (securely wipe) a device",
2738 This command writes patterns over C<device> to make data retrieval
2741 It is an interface to the L<scrub(1)> program. See that
2742 manual page for more details.");
2744 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745 [InitBasicFS, Always, TestRun (
2746 [["write_file"; "/file"; "content"; "0"];
2747 ["scrub_file"; "/file"]])],
2748 "scrub (securely wipe) a file",
2750 This command writes patterns over a file to make data retrieval
2753 The file is I<removed> after scrubbing.
2755 It is an interface to the L<scrub(1)> program. See that
2756 manual page for more details.");
2758 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759 [], (* XXX needs testing *)
2760 "scrub (securely wipe) free space",
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2768 It is an interface to the L<scrub(1)> program. See that
2769 manual page for more details.");
2771 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772 [InitBasicFS, Always, TestRun (
2774 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775 "create a temporary directory",
2777 This command creates a temporary directory. The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2785 The name of the temporary directory that was created
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2794 See also: L<mkdtemp(3)>");
2796 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797 [InitISOFS, Always, TestOutputInt (
2798 [["wc_l"; "/10klines"]], 10000)],
2799 "count lines in a file",
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2804 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805 [InitISOFS, Always, TestOutputInt (
2806 [["wc_w"; "/10klines"]], 10000)],
2807 "count words in a file",
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2812 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813 [InitISOFS, Always, TestOutputInt (
2814 [["wc_c"; "/100kallspaces"]], 102400)],
2815 "count characters in a file",
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2820 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821 [InitISOFS, Always, TestOutputList (
2822 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823 "return first 10 lines of a file",
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2828 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829 [InitISOFS, Always, TestOutputList (
2830 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831 InitISOFS, Always, TestOutputList (
2832 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833 InitISOFS, Always, TestOutputList (
2834 [["head_n"; "0"; "/10klines"]], [])],
2835 "return first N lines of a file",
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2845 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846 [InitISOFS, Always, TestOutputList (
2847 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848 "return last 10 lines of a file",
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2853 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854 [InitISOFS, Always, TestOutputList (
2855 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856 InitISOFS, Always, TestOutputList (
2857 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858 InitISOFS, Always, TestOutputList (
2859 [["tail_n"; "0"; "/10klines"]], [])],
2860 "return last N lines of a file",
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2870 ("df", (RString "output", []), 125, [],
2871 [], (* XXX Tricky to test because it depends on the exact format
2872 * of the 'df' command and other imponderables.
2874 "report file system disk space usage",
2876 This command runs the C<df> command to report disk space used.
2878 This command is mostly useful for interactive sessions. It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2882 ("df_h", (RString "output", []), 126, [],
2883 [], (* XXX Tricky to test because it depends on the exact format
2884 * of the 'df' command and other imponderables.
2886 "report file system disk space usage (human readable)",
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2891 This command is mostly useful for interactive sessions. It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2895 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896 [InitISOFS, Always, TestOutputInt (
2897 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898 "estimate file space usage",
2900 This command runs the C<du -s> command to estimate file space
2903 C<path> can be a file or a directory. If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2910 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911 [InitISOFS, Always, TestOutputList (
2912 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913 "list files in an initrd",
2915 This command lists out files contained in an initrd.
2917 The files are listed without any initial C</> character. The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical). Directory names are listed as separate items.
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd. We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2925 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2927 "mount a file using the loop device",
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point. It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2933 ("mkswap", (RErr, [Device "device"]), 130, [],
2934 [InitEmpty, Always, TestRun (
2935 [["part_disk"; "/dev/sda"; "mbr"];
2936 ["mkswap"; "/dev/sda1"]])],
2937 "create a swap partition",
2939 Create a swap partition on C<device>.");
2941 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942 [InitEmpty, Always, TestRun (
2943 [["part_disk"; "/dev/sda"; "mbr"];
2944 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945 "create a swap partition with a label",
2947 Create a swap partition on C<device> with label C<label>.
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition. This appears to be
2951 a limitation of the kernel or swap tools.");
2953 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954 (let uuid = uuidgen () in
2955 [InitEmpty, Always, TestRun (
2956 [["part_disk"; "/dev/sda"; "mbr"];
2957 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958 "create a swap partition with an explicit UUID",
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2962 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963 [InitBasicFS, Always, TestOutputStruct (
2964 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967 InitBasicFS, Always, TestOutputStruct (
2968 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970 "make block, character or FIFO devices",
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2975 The C<mode> parameter should be the mode, using the standard
2976 constants. C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.");
2980 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981 [InitBasicFS, Always, TestOutputStruct (
2982 [["mkfifo"; "0o777"; "/node"];
2983 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984 "make FIFO (named pipe)",
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>. It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2990 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991 [InitBasicFS, Always, TestOutputStruct (
2992 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994 "make block device node",
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
3000 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001 [InitBasicFS, Always, TestOutputStruct (
3002 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004 "make char device node",
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3010 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011 [], (* XXX umask is one of those stateful things that we should
3012 * reset between each test.
3014 "set file mode creation mask (umask)",
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3024 The default umask is C<022>. This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3030 This call returns the previous umask.");
3032 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3034 "read directories entries",
3036 This returns the list of directory entries in directory C<dir>.
3038 All entries in the directory are returned, including C<.> and
3039 C<..>. The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3042 Also this call returns basic file type information about each
3043 file. The C<ftyp> field will contain one of the following characters:
3081 The L<readdir(3)> returned a C<d_type> field with an
3086 This function is primarily intended for use by programs. To
3087 get a simple list of names, use C<guestfs_ls>. To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3090 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3092 "create partitions on a block device",
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3103 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3105 "determine file type inside a compressed file",
3107 This command runs C<file> after first decompressing C<path>
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3115 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3117 "list extended attributes of a file or directory",
3119 This call lists the extended attributes of the file or directory
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3127 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3129 "list extended attributes of a file or directory",
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3135 ("setxattr", (RErr, [String "xattr";
3136 String "val"; Int "vallen"; (* will be BufferIn *)
3137 Pathname "path"]), 143, [Optional "linuxxattrs"],
3139 "set extended attribute of a file or directory",
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3147 ("lsetxattr", (RErr, [String "xattr";
3148 String "val"; Int "vallen"; (* will be BufferIn *)
3149 Pathname "path"]), 144, [Optional "linuxxattrs"],
3151 "set extended attribute of a file or directory",
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3157 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3159 "remove extended attribute of a file or directory",
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3166 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3168 "remove extended attribute of a file or directory",
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3174 ("mountpoints", (RHashtable "mps", []), 147, [],
3178 This call is similar to C<guestfs_mounts>. That call returns
3179 a list of devices. This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3182 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183 (* This is a special case: while you would expect a parameter
3184 * of type "Pathname", that doesn't work, because it implies
3185 * NEED_ROOT in the generated calling code in stubs.c, and
3186 * this function cannot use NEED_ROOT.
3189 "create a mountpoint",
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that. You can unpack this as follows
3204 add-ro Fedora-11-i686-Live.iso
3207 mkmountpoint /squash
3210 mount-loop /cd/LiveOS/squashfs.img /squash
3211 mount-loop /squash/LiveOS/ext3fs.img /ext3
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3215 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3217 "remove a mountpoint",
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3221 for full details.");
3223 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224 [InitISOFS, Always, TestOutputBuffer (
3225 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3228 This calls returns the contents of the file C<path> as a
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3236 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237 [InitISOFS, Always, TestOutputList (
3238 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239 InitISOFS, Always, TestOutputList (
3240 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241 "return lines matching a pattern",
3243 This calls the external C<grep> program and returns the
3246 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247 [InitISOFS, Always, TestOutputList (
3248 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249 "return lines matching a pattern",
3251 This calls the external C<egrep> program and returns the
3254 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255 [InitISOFS, Always, TestOutputList (
3256 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257 "return lines matching a pattern",
3259 This calls the external C<fgrep> program and returns the
3262 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263 [InitISOFS, Always, TestOutputList (
3264 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265 "return lines matching a pattern",
3267 This calls the external C<grep -i> program and returns the
3270 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271 [InitISOFS, Always, TestOutputList (
3272 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273 "return lines matching a pattern",
3275 This calls the external C<egrep -i> program and returns the
3278 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279 [InitISOFS, Always, TestOutputList (
3280 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281 "return lines matching a pattern",
3283 This calls the external C<fgrep -i> program and returns the
3286 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287 [InitISOFS, Always, TestOutputList (
3288 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289 "return lines matching a pattern",
3291 This calls the external C<zgrep> program and returns the
3294 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295 [InitISOFS, Always, TestOutputList (
3296 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297 "return lines matching a pattern",
3299 This calls the external C<zegrep> program and returns the
3302 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303 [InitISOFS, Always, TestOutputList (
3304 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305 "return lines matching a pattern",
3307 This calls the external C<zfgrep> program and returns the
3310 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311 [InitISOFS, Always, TestOutputList (
3312 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313 "return lines matching a pattern",
3315 This calls the external C<zgrep -i> program and returns the
3318 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319 [InitISOFS, Always, TestOutputList (
3320 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321 "return lines matching a pattern",
3323 This calls the external C<zegrep -i> program and returns the
3326 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327 [InitISOFS, Always, TestOutputList (
3328 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329 "return lines matching a pattern",
3331 This calls the external C<zfgrep -i> program and returns the
3334 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335 [InitISOFS, Always, TestOutput (
3336 [["realpath"; "/../directory"]], "/directory")],
3337 "canonicalized absolute pathname",
3339 Return the canonicalized absolute pathname of C<path>. The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3342 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343 [InitBasicFS, Always, TestOutputStruct (
3346 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347 "create a hard link",
3349 This command creates a hard link using the C<ln> command.");
3351 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352 [InitBasicFS, Always, TestOutputStruct (
3355 ["ln_f"; "/a"; "/b"];
3356 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357 "create a hard link",
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3362 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363 [InitBasicFS, Always, TestOutputStruct (
3365 ["ln_s"; "a"; "/b"];
3366 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367 "create a symbolic link",
3369 This command creates a symbolic link using the C<ln -s> command.");
3371 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372 [InitBasicFS, Always, TestOutput (
3373 [["mkdir_p"; "/a/b"];
3374 ["touch"; "/a/b/c"];
3375 ["ln_sf"; "../d"; "/a/b/c"];
3376 ["readlink"; "/a/b/c"]], "../d")],
3377 "create a symbolic link",
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3382 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383 [] (* XXX tested above *),
3384 "read the target of a symbolic link",
3386 This command reads the target of a symbolic link.");
3388 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389 [InitBasicFS, Always, TestOutputStruct (
3390 [["fallocate"; "/a"; "1000000"];
3391 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392 "preallocate a file in the guest filesystem",
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes. If the file exists already, it
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3402 ("swapon_device", (RErr, [Device "device"]), 170, [],
3403 [InitPartition, Always, TestRun (
3404 [["mkswap"; "/dev/sda1"];
3405 ["swapon_device"; "/dev/sda1"];
3406 ["swapoff_device"; "/dev/sda1"]])],
3407 "enable swap on device",
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>. The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing. They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash. You also risk leaking
3418 information about the host to the guest this way. Instead,
3419 attach a new host device to the guest and swap on that.");
3421 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422 [], (* XXX tested by swapon_device *)
3423 "disable swap on device",
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3429 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430 [InitBasicFS, Always, TestRun (
3431 [["fallocate"; "/swap"; "8388608"];
3432 ["mkswap_file"; "/swap"];
3433 ["swapon_file"; "/swap"];
3434 ["swapoff_file"; "/swap"]])],
3435 "enable swap on file",
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3440 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441 [], (* XXX tested by swapon_file *)
3442 "disable swap on file",
3444 This command disables the libguestfs appliance swap on file.");
3446 ("swapon_label", (RErr, [String "label"]), 174, [],
3447 [InitEmpty, Always, TestRun (
3448 [["part_disk"; "/dev/sdb"; "mbr"];
3449 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450 ["swapon_label"; "swapit"];
3451 ["swapoff_label"; "swapit"];
3452 ["zero"; "/dev/sdb"];
3453 ["blockdev_rereadpt"; "/dev/sdb"]])],
3454 "enable swap on labeled swap partition",
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3459 ("swapoff_label", (RErr, [String "label"]), 175, [],
3460 [], (* XXX tested by swapon_label *)
3461 "disable swap on labeled swap partition",
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3466 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467 (let uuid = uuidgen () in
3468 [InitEmpty, Always, TestRun (
3469 [["mkswap_U"; uuid; "/dev/sdb"];
3470 ["swapon_uuid"; uuid];
3471 ["swapoff_uuid"; uuid]])]),
3472 "enable swap on swap partition by UUID",
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3477 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478 [], (* XXX tested by swapon_uuid *)
3479 "disable swap on swap partition by UUID",
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3484 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485 [InitBasicFS, Always, TestRun (
3486 [["fallocate"; "/swap"; "8388608"];
3487 ["mkswap_file"; "/swap"]])],
3488 "create a swap file",
3492 This command just writes a swap file signature to an existing
3493 file. To create the file itself, use something like C<guestfs_fallocate>.");
3495 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496 [InitISOFS, Always, TestRun (
3497 [["inotify_init"; "0"]])],
3498 "create an inotify handle",
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used. For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list. See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>). If you don't
3524 read the events out often enough then you risk the internal
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>. This also removes any
3529 watches automatically.
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs. Note that there is one global inotify handle
3534 per libguestfs instance.");
3536 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537 [InitBasicFS, Always, TestOutputList (
3538 [["inotify_init"; "0"];
3539 ["inotify_add_watch"; "/"; "1073741823"];
3542 ["inotify_files"]], ["a"; "b"])],
3543 "add an inotify watch",
3545 Watch C<path> for the events listed in C<mask>.
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3555 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3557 "remove an inotify watch",
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3562 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3564 "return list of inotify events",
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3569 If no events have happened, this returns an empty list.
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list. The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3577 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3579 "return list of watched files that had events",
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched. The returned pathnames are sorted and deduplicated.");
3585 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3587 "close the inotify handle",
3589 This closes the inotify handle which was previously
3590 opened by inotify_init. It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3593 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3595 "set SELinux security context",
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3602 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3604 "get SELinux security context",
3606 This gets the SELinux security context of the daemon.
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3611 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612 [InitEmpty, Always, TestOutput (
3613 [["part_disk"; "/dev/sda"; "mbr"];
3614 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615 ["mount_options"; ""; "/dev/sda1"; "/"];
3616 ["write_file"; "/new"; "new file contents"; "0"];
3617 ["cat"; "/new"]], "new file contents")],
3618 "make a filesystem with block size",
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem. Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3625 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626 [InitEmpty, Always, TestOutput (
3627 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628 ["mke2journal"; "4096"; "/dev/sda1"];
3629 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630 ["mount_options"; ""; "/dev/sda2"; "/"];
3631 ["write_file"; "/new"; "new file contents"; "0"];
3632 ["cat"; "/new"]], "new file contents")],
3633 "make ext2/3/4 external journal",
3635 This creates an ext2 external journal on C<device>. It is equivalent
3638 mke2fs -O journal_dev -b blocksize device");
3640 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641 [InitEmpty, Always, TestOutput (
3642 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3645 ["mount_options"; ""; "/dev/sda2"; "/"];
3646 ["write_file"; "/new"; "new file contents"; "0"];
3647 ["cat"; "/new"]], "new file contents")],
3648 "make ext2/3/4 external journal with label",
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3652 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653 (let uuid = uuidgen () in
3654 [InitEmpty, Always, TestOutput (
3655 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658 ["mount_options"; ""; "/dev/sda2"; "/"];
3659 ["write_file"; "/new"; "new file contents"; "0"];
3660 ["cat"; "/new"]], "new file contents")]),
3661 "make ext2/3/4 external journal with UUID",
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3665 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3667 "make ext2/3/4 filesystem with external journal",
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>. It is equivalent
3673 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3675 See also C<guestfs_mke2journal>.");
3677 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3679 "make ext2/3/4 filesystem with external journal",
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3684 See also C<guestfs_mke2journal_L>.");
3686 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3688 "make ext2/3/4 filesystem with external journal",
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3693 See also C<guestfs_mke2journal_U>.");
3695 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697 "load a kernel module",
3699 This loads a kernel module in the appliance.
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3704 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705 [InitNone, Always, TestOutput (
3706 [["echo_daemon"; "This is a test"]], "This is a test"
3708 "echo arguments back to the client",
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3713 You can use this command to test the connection through to the daemon.
3715 See also C<guestfs_ping_daemon>.");
3717 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718 [], (* There is a regression test for this. *)
3719 "find all files and directories, returning NUL-separated list",
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3732 The resulting list is written to an external file.
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters. See L<find(1)> option I<-print0>.
3741 This command is not limited in the number of names that it
3746 The result list is not sorted.
3750 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751 [InitISOFS, Always, TestOutput (
3752 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753 InitISOFS, Always, TestOutput (
3754 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755 InitISOFS, Always, TestOutput (
3756 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757 InitISOFS, Always, TestLastFail (
3758 [["case_sensitive_path"; "/Known-1/"]]);
3759 InitBasicFS, Always, TestOutput (
3761 ["mkdir"; "/a/bbb"];
3762 ["touch"; "/a/bbb/c"];
3763 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3764 InitBasicFS, Always, TestOutput (
3766 ["mkdir"; "/a/bbb"];
3767 ["touch"; "/a/bbb/c"];
3768 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769 InitBasicFS, Always, TestLastFail (
3771 ["mkdir"; "/a/bbb"];
3772 ["touch"; "/a/bbb/c"];
3773 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774 "return true path on case-insensitive filesystem",
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive. The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created. In Windows itself this would not be
3792 Bug or feature? You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3804 This function does not handle drive names, backslashes etc.
3806 See also C<guestfs_realpath>.");
3808 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809 [InitBasicFS, Always, TestOutput (
3810 [["vfs_type"; "/dev/sda1"]], "ext2")],
3811 "get the Linux VFS type corresponding to a mounted device",
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3820 ("truncate", (RErr, [Pathname "path"]), 199, [],
3821 [InitBasicFS, Always, TestOutputStruct (
3822 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823 ["truncate"; "/test"];
3824 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825 "truncate a file to zero size",
3827 This command truncates C<path> to a zero-length file. The
3828 file must exist already.");
3830 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831 [InitBasicFS, Always, TestOutputStruct (
3832 [["touch"; "/test"];
3833 ["truncate_size"; "/test"; "1000"];
3834 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835 "truncate a file to a particular size",
3837 This command truncates C<path> to size C<size> bytes. The file
3838 must exist already. If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3841 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842 [InitBasicFS, Always, TestOutputStruct (
3843 [["touch"; "/test"];
3844 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846 "set timestamp of a file with nanosecond precision",
3848 This command sets the timestamps of a file with nanosecond
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time. (The
3859 C<*secs> field is ignored in this case).
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged. (The
3863 C<*secs> field is ignored in this case).");
3865 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866 [InitBasicFS, Always, TestOutputStruct (
3867 [["mkdir_mode"; "/test"; "0o111"];
3868 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869 "create a directory with a particular mode",
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3874 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3876 "change file owner and group",
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3882 Only numeric uid and gid are supported. If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3886 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3888 "lstat on multiple files",
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list. If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes. Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail. The caller must split up such requests
3905 into smaller groups of names.");
3907 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3909 "lgetxattr on multiple files",
3911 This call allows you to get the extended attributes
3912 of multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3915 On return you get a flat list of xattr structs which must be
3916 interpreted sequentially. The first xattr struct always has a zero-length
3917 C<attrname>. C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">). Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats. Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail. The caller must split up such requests
3931 into smaller groups of names.");
3933 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3935 "readlink on multiple files",
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list. Each string is the
3943 value of the symbol link.
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail. The caller must split up such requests
3957 into smaller groups of names.");
3959 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960 [InitISOFS, Always, TestOutputBuffer (
3961 [["pread"; "/known-4"; "1"; "3"]], "\n");
3962 InitISOFS, Always, TestOutputBuffer (
3963 [["pread"; "/empty"; "0"; "100"]], "")],
3964 "read part of a file",
3966 This command lets you read part of a file. It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3969 This may read fewer bytes than requested. For further details
3970 see the L<pread(2)> system call.");
3972 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973 [InitEmpty, Always, TestRun (
3974 [["part_init"; "/dev/sda"; "gpt"]])],
3975 "create an empty partition table",
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below. Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3981 Initially there are no partitions. Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3984 Possible values for C<parttype> are:
3988 =item B<efi> | B<gpt>
3990 Intel EFI / GPT partition table.
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X. It also has limited backwards
3994 compatibility with the C<mbr> format.
3996 =item B<mbr> | B<msdos>
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows. This partition type will B<only> work
4000 for device sizes up to 2 TB. For large disks we recommend
4005 Other partition table types that may work but are not
4014 =item B<amiga> | B<rdb>
4016 Amiga \"Rigid Disk Block\" format.
4024 DASD, used on IBM mainframes.
4032 Old Mac partition format. Modern Macs use C<gpt>.
4036 NEC PC-98 format, common in Japan apparently.
4044 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045 [InitEmpty, Always, TestRun (
4046 [["part_init"; "/dev/sda"; "mbr"];
4047 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048 InitEmpty, Always, TestRun (
4049 [["part_init"; "/dev/sda"; "gpt"];
4050 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052 InitEmpty, Always, TestRun (
4053 [["part_init"; "/dev/sda"; "mbr"];
4054 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058 "add a partition to the device",
4060 This command adds a partition to C<device>. If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4063 The C<prlogex> parameter is the type of partition. Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>. C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4075 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076 [InitEmpty, Always, TestRun (
4077 [["part_disk"; "/dev/sda"; "mbr"]]);
4078 InitEmpty, Always, TestRun (
4079 [["part_disk"; "/dev/sda"; "gpt"]])],
4080 "partition whole disk with a single primary partition",
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4089 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090 [InitEmpty, Always, TestRun (
4091 [["part_disk"; "/dev/sda"; "mbr"];
4092 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093 "make a partition bootable",
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>. Note that partitions are numbered from 1.
4098 The bootable flag is used by some operating systems (notably
4099 Windows) to determine which partition to boot from. It is by
4100 no means universally recognized.");
4102 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4103 [InitEmpty, Always, TestRun (
4104 [["part_disk"; "/dev/sda"; "gpt"];
4105 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4106 "set partition name",
4108 This sets the partition name on partition numbered C<partnum> on
4109 device C<device>. Note that partitions are numbered from 1.
4111 The partition name can only be set on certain types of partition
4112 table. This works on C<gpt> but not on C<mbr> partitions.");
4114 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4115 [], (* XXX Add a regression test for this. *)
4116 "list partitions on a device",
4118 This command parses the partition table on C<device> and
4119 returns the list of partitions found.
4121 The fields in the returned structure are:
4127 Partition number, counting from 1.
4131 Start of the partition I<in bytes>. To get sectors you have to
4132 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4136 End of the partition in bytes.
4140 Size of the partition in bytes.
4144 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4145 [InitEmpty, Always, TestOutput (
4146 [["part_disk"; "/dev/sda"; "gpt"];
4147 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4148 "get the partition table type",
4150 This command examines the partition table on C<device> and
4151 returns the partition table type (format) being used.
4153 Common return values include: C<msdos> (a DOS/Windows style MBR
4154 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4155 values are possible, although unusual. See C<guestfs_part_init>
4158 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4159 [InitBasicFS, Always, TestOutputBuffer (
4160 [["fill"; "0x63"; "10"; "/test"];
4161 ["read_file"; "/test"]], "cccccccccc")],
4162 "fill a file with octets",
4164 This command creates a new file called C<path>. The initial
4165 content of the file is C<len> octets of C<c>, where C<c>
4166 must be a number in the range C<[0..255]>.
4168 To fill a file with zero bytes (sparsely), it is
4169 much more efficient to use C<guestfs_truncate_size>.");
4171 ("available", (RErr, [StringList "groups"]), 216, [],
4172 [InitNone, Always, TestRun [["available"; ""]]],
4173 "test availability of some parts of the API",
4175 This command is used to check the availability of some
4176 groups of functionality in the appliance, which not all builds of
4177 the libguestfs appliance will be able to provide.
4179 The libguestfs groups, and the functions that those
4180 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4182 The argument C<groups> is a list of group names, eg:
4183 C<[\"inotify\", \"augeas\"]> would check for the availability of
4184 the Linux inotify functions and Augeas (configuration file
4187 The command returns no error if I<all> requested groups are available.
4189 It fails with an error if one or more of the requested
4190 groups is unavailable in the appliance.
4192 If an unknown group name is included in the
4193 list of groups then an error is always returned.
4201 You must call C<guestfs_launch> before calling this function.
4203 The reason is because we don't know what groups are
4204 supported by the appliance/daemon until it is running and can
4209 If a group of functions is available, this does not necessarily
4210 mean that they will work. You still have to check for errors
4211 when calling individual API functions even if they are
4216 It is usually the job of distro packagers to build
4217 complete functionality into the libguestfs appliance.
4218 Upstream libguestfs, if built from source with all
4219 requirements satisfied, will support everything.
4223 This call was added in version C<1.0.80>. In previous
4224 versions of libguestfs all you could do would be to speculatively
4225 execute a command to find out if the daemon implemented it.
4226 See also C<guestfs_version>.
4230 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4231 [InitBasicFS, Always, TestOutputBuffer (
4232 [["write_file"; "/src"; "hello, world"; "0"];
4233 ["dd"; "/src"; "/dest"];
4234 ["read_file"; "/dest"]], "hello, world")],
4235 "copy from source to destination using dd",
4237 This command copies from one source device or file C<src>
4238 to another destination device or file C<dest>. Normally you
4239 would use this to copy to or from a device or partition, for
4240 example to duplicate a filesystem.
4242 If the destination is a device, it must be as large or larger
4243 than the source file or device, otherwise the copy will fail.
4244 This command cannot do partial copies (see C<guestfs_copy_size>).");
4246 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4247 [InitBasicFS, Always, TestOutputInt (
4248 [["write_file"; "/file"; "hello, world"; "0"];
4249 ["filesize"; "/file"]], 12)],
4250 "return the size of the file in bytes",
4252 This command returns the size of C<file> in bytes.
4254 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4255 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4256 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4258 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4259 [InitBasicFSonLVM, Always, TestOutputList (
4260 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4261 ["lvs"]], ["/dev/VG/LV2"])],
4262 "rename an LVM logical volume",
4264 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4266 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4267 [InitBasicFSonLVM, Always, TestOutputList (
4269 ["vg_activate"; "false"; "VG"];
4270 ["vgrename"; "VG"; "VG2"];
4271 ["vg_activate"; "true"; "VG2"];
4272 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4273 ["vgs"]], ["VG2"])],
4274 "rename an LVM volume group",
4276 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4278 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4279 [InitISOFS, Always, TestOutputBuffer (
4280 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4281 "list the contents of a single file in an initrd",
4283 This command unpacks the file C<filename> from the initrd file
4284 called C<initrdpath>. The filename must be given I<without> the
4285 initial C</> character.
4287 For example, in guestfish you could use the following command
4288 to examine the boot script (usually called C</init>)
4289 contained in a Linux initrd or initramfs image:
4291 initrd-cat /boot/initrd-<version>.img init
4293 See also C<guestfs_initrd_list>.");
4295 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4297 "get the UUID of a physical volume",
4299 This command returns the UUID of the LVM PV C<device>.");
4301 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4303 "get the UUID of a volume group",
4305 This command returns the UUID of the LVM VG named C<vgname>.");
4307 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4309 "get the UUID of a logical volume",
4311 This command returns the UUID of the LVM LV C<device>.");
4313 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4315 "get the PV UUIDs containing the volume group",
4317 Given a VG called C<vgname>, this returns the UUIDs of all
4318 the physical volumes that this volume group resides on.
4320 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4321 calls to associate physical volumes and volume groups.
4323 See also C<guestfs_vglvuuids>.");
4325 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4327 "get the LV UUIDs of all LVs in the volume group",
4329 Given a VG called C<vgname>, this returns the UUIDs of all
4330 the logical volumes created in this volume group.
4332 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4333 calls to associate logical volumes and volume groups.
4335 See also C<guestfs_vgpvuuids>.");
4337 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4338 [InitBasicFS, Always, TestOutputBuffer (
4339 [["write_file"; "/src"; "hello, world"; "0"];
4340 ["copy_size"; "/src"; "/dest"; "5"];
4341 ["read_file"; "/dest"]], "hello")],
4342 "copy size bytes from source to destination using dd",
4344 This command copies exactly C<size> bytes from one source device
4345 or file C<src> to another destination device or file C<dest>.
4347 Note this will fail if the source is too short or if the destination
4348 is not large enough.");
4350 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4351 [InitBasicFSonLVM, Always, TestRun (
4352 [["zero_device"; "/dev/VG/LV"]])],
4353 "write zeroes to an entire device",
4355 This command writes zeroes over the entire C<device>. Compare
4356 with C<guestfs_zero> which just zeroes the first few blocks of
4359 ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4360 [InitBasicFS, Always, TestOutput (
4361 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4362 ["cat"; "/hello"]], "hello\n")],
4363 "unpack compressed tarball to directory",
4365 This command uploads and unpacks local file C<tarball> (an
4366 I<xz compressed> tar file) into C<directory>.");
4368 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4370 "pack directory into compressed tarball",
4372 This command packs the contents of C<directory> and downloads
4373 it to local file C<tarball> (as an xz compressed tar archive).");
4375 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4377 "resize an NTFS filesystem",
4379 This command resizes an NTFS filesystem, expanding or
4380 shrinking it to the size of the underlying device.
4381 See also L<ntfsresize(8)>.");
4383 ("vgscan", (RErr, []), 232, [],
4384 [InitEmpty, Always, TestRun (
4386 "rescan for LVM physical volumes, volume groups and logical volumes",
4388 This rescans all block devices and rebuilds the list of LVM
4389 physical volumes, volume groups and logical volumes.");
4391 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4392 [InitEmpty, Always, TestRun (
4393 [["part_init"; "/dev/sda"; "mbr"];
4394 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4395 ["part_del"; "/dev/sda"; "1"]])],
4396 "delete a partition",
4398 This command deletes the partition numbered C<partnum> on C<device>.
4400 Note that in the case of MBR partitioning, deleting an
4401 extended partition also deletes any logical partitions
4404 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4405 [InitEmpty, Always, TestOutputTrue (
4406 [["part_init"; "/dev/sda"; "mbr"];
4407 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4408 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4409 ["part_get_bootable"; "/dev/sda"; "1"]])],
4410 "return true if a partition is bootable",
4412 This command returns true if the partition C<partnum> on
4413 C<device> has the bootable flag set.
4415 See also C<guestfs_part_set_bootable>.");
4417 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4418 [InitEmpty, Always, TestOutputInt (
4419 [["part_init"; "/dev/sda"; "mbr"];
4420 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4421 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4422 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4423 "get the MBR type byte (ID byte) from a partition",
4425 Returns the MBR type byte (also known as the ID byte) from
4426 the numbered partition C<partnum>.
4428 Note that only MBR (old DOS-style) partitions have type bytes.
4429 You will get undefined results for other partition table
4430 types (see C<guestfs_part_get_parttype>).");
4432 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4433 [], (* tested by part_get_mbr_id *)
4434 "set the MBR type byte (ID byte) of a partition",
4436 Sets the MBR type byte (also known as the ID byte) of
4437 the numbered partition C<partnum> to C<idbyte>. Note
4438 that the type bytes quoted in most documentation are
4439 in fact hexadecimal numbers, but usually documented
4440 without any leading \"0x\" which might be confusing.
4442 Note that only MBR (old DOS-style) partitions have type bytes.
4443 You will get undefined results for other partition table
4444 types (see C<guestfs_part_get_parttype>).");
4446 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4447 [InitISOFS, Always, TestOutput (
4448 [["checksum_device"; "md5"; "/dev/sdd"]],
4449 (Digest.to_hex (Digest.file "images/test.iso")))],
4450 "compute MD5, SHAx or CRC checksum of the contents of a device",
4452 This call computes the MD5, SHAx or CRC checksum of the
4453 contents of the device named C<device>. For the types of
4454 checksums supported see the C<guestfs_checksum> command.");
4456 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4457 [InitNone, Always, TestRun (
4458 [["part_disk"; "/dev/sda"; "mbr"];
4459 ["pvcreate"; "/dev/sda1"];
4460 ["vgcreate"; "VG"; "/dev/sda1"];
4461 ["lvcreate"; "LV"; "VG"; "10"];
4462 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4463 "expand an LV to fill free space",
4465 This expands an existing logical volume C<lv> so that it fills
4466 C<pc>% of the remaining free space in the volume group. Commonly
4467 you would call this with pc = 100 which expands the logical volume
4468 as much as possible, using all remaining free space in the volume
4473 let all_functions = non_daemon_functions @ daemon_functions
4475 (* In some places we want the functions to be displayed sorted
4476 * alphabetically, so this is useful:
4478 let all_functions_sorted =
4479 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4480 compare n1 n2) all_functions
4482 (* Field types for structures. *)
4484 | FChar (* C 'char' (really, a 7 bit byte). *)
4485 | FString (* nul-terminated ASCII string, NOT NULL. *)
4486 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4491 | FBytes (* Any int measure that counts bytes. *)
4492 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4493 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4495 (* Because we generate extra parsing code for LVM command line tools,
4496 * we have to pull out the LVM columns separately here.
4506 "pv_attr", FString (* XXX *);
4507 "pv_pe_count", FInt64;
4508 "pv_pe_alloc_count", FInt64;
4511 "pv_mda_count", FInt64;
4512 "pv_mda_free", FBytes;
4513 (* Not in Fedora 10:
4514 "pv_mda_size", FBytes;
4521 "vg_attr", FString (* XXX *);
4524 "vg_sysid", FString;
4525 "vg_extent_size", FBytes;
4526 "vg_extent_count", FInt64;
4527 "vg_free_count", FInt64;
4532 "snap_count", FInt64;
4535 "vg_mda_count", FInt64;
4536 "vg_mda_free", FBytes;
4537 (* Not in Fedora 10:
4538 "vg_mda_size", FBytes;
4544 "lv_attr", FString (* XXX *);
4547 "lv_kernel_major", FInt64;
4548 "lv_kernel_minor", FInt64;
4550 "seg_count", FInt64;
4552 "snap_percent", FOptPercent;
4553 "copy_percent", FOptPercent;
4556 "mirror_log", FString;
4560 (* Names and fields in all structures (in RStruct and RStructList)
4564 (* The old RIntBool return type, only ever used for aug_defnode. Do
4565 * not use this struct in any new code.
4568 "i", FInt32; (* for historical compatibility *)
4569 "b", FInt32; (* for historical compatibility *)
4572 (* LVM PVs, VGs, LVs. *)
4573 "lvm_pv", lvm_pv_cols;
4574 "lvm_vg", lvm_vg_cols;
4575 "lvm_lv", lvm_lv_cols;
4577 (* Column names and types from stat structures.
4578 * NB. Can't use things like 'st_atime' because glibc header files
4579 * define some of these as macros. Ugh.
4610 (* Column names in dirent structure. *)
4613 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4618 (* Version numbers. *)
4626 (* Extended attribute. *)
4628 "attrname", FString;
4632 (* Inotify events. *)
4636 "in_cookie", FUInt32;
4640 (* Partition table entry. *)
4643 "part_start", FBytes;
4645 "part_size", FBytes;
4647 ] (* end of structs *)
4649 (* Ugh, Java has to be different ..
4650 * These names are also used by the Haskell bindings.
4652 let java_structs = [
4653 "int_bool", "IntBool";
4658 "statvfs", "StatVFS";
4660 "version", "Version";
4662 "inotify_event", "INotifyEvent";
4663 "partition", "Partition";
4666 (* What structs are actually returned. *)
4667 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4669 (* Returns a list of RStruct/RStructList structs that are returned
4670 * by any function. Each element of returned list is a pair:
4672 * (structname, RStructOnly)
4673 * == there exists function which returns RStruct (_, structname)
4674 * (structname, RStructListOnly)
4675 * == there exists function which returns RStructList (_, structname)
4676 * (structname, RStructAndList)
4677 * == there are functions returning both RStruct (_, structname)
4678 * and RStructList (_, structname)
4680 let rstructs_used_by functions =
4681 (* ||| is a "logical OR" for rstructs_used_t *)
4685 | _, RStructAndList -> RStructAndList
4686 | RStructOnly, RStructListOnly
4687 | RStructListOnly, RStructOnly -> RStructAndList
4688 | RStructOnly, RStructOnly -> RStructOnly
4689 | RStructListOnly, RStructListOnly -> RStructListOnly
4692 let h = Hashtbl.create 13 in
4694 (* if elem->oldv exists, update entry using ||| operator,
4695 * else just add elem->newv to the hash
4697 let update elem newv =
4698 try let oldv = Hashtbl.find h elem in
4699 Hashtbl.replace h elem (newv ||| oldv)
4700 with Not_found -> Hashtbl.add h elem newv
4704 fun (_, style, _, _, _, _, _) ->
4705 match fst style with
4706 | RStruct (_, structname) -> update structname RStructOnly
4707 | RStructList (_, structname) -> update structname RStructListOnly
4711 (* return key->values as a list of (key,value) *)
4712 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4714 (* Used for testing language bindings. *)
4716 | CallString of string
4717 | CallOptString of string option
4718 | CallStringList of string list
4720 | CallInt64 of int64
4723 (* Used to memoize the result of pod2text. *)
4724 let pod2text_memo_filename = "src/.pod2text.data"
4725 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4727 let chan = open_in pod2text_memo_filename in
4728 let v = input_value chan in
4732 _ -> Hashtbl.create 13
4733 let pod2text_memo_updated () =
4734 let chan = open_out pod2text_memo_filename in
4735 output_value chan pod2text_memo;
4738 (* Useful functions.
4739 * Note we don't want to use any external OCaml libraries which
4740 * makes this a bit harder than it should be.
4742 module StringMap = Map.Make (String)
4744 let failwithf fs = ksprintf failwith fs
4746 let unique = let i = ref 0 in fun () -> incr i; !i
4748 let replace_char s c1 c2 =
4749 let s2 = String.copy s in
4750 let r = ref false in
4751 for i = 0 to String.length s2 - 1 do
4752 if String.unsafe_get s2 i = c1 then (
4753 String.unsafe_set s2 i c2;
4757 if not !r then s else s2
4761 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4763 let triml ?(test = isspace) str =
4765 let n = ref (String.length str) in
4766 while !n > 0 && test str.[!i]; do
4771 else String.sub str !i !n
4773 let trimr ?(test = isspace) str =
4774 let n = ref (String.length str) in
4775 while !n > 0 && test str.[!n-1]; do
4778 if !n = String.length str then str
4779 else String.sub str 0 !n
4781 let trim ?(test = isspace) str =
4782 trimr ~test (triml ~test str)
4784 let rec find s sub =
4785 let len = String.length s in
4786 let sublen = String.length sub in
4788 if i <= len-sublen then (
4790 if j < sublen then (
4791 if s.[i+j] = sub.[j] then loop2 (j+1)
4797 if r = -1 then loop (i+1) else r
4803 let rec replace_str s s1 s2 =
4804 let len = String.length s in
4805 let sublen = String.length s1 in
4806 let i = find s s1 in
4809 let s' = String.sub s 0 i in
4810 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4811 s' ^ s2 ^ replace_str s'' s1 s2
4814 let rec string_split sep str =
4815 let len = String.length str in
4816 let seplen = String.length sep in
4817 let i = find str sep in
4818 if i = -1 then [str]
4820 let s' = String.sub str 0 i in
4821 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4822 s' :: string_split sep s''
4825 let files_equal n1 n2 =
4826 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4827 match Sys.command cmd with
4830 | i -> failwithf "%s: failed with error code %d" cmd i
4832 let rec filter_map f = function
4836 | Some y -> y :: filter_map f xs
4837 | None -> filter_map f xs
4839 let rec find_map f = function
4840 | [] -> raise Not_found
4844 | None -> find_map f xs
4847 let rec loop i = function
4849 | x :: xs -> f i x; loop (i+1) xs
4854 let rec loop i = function
4856 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4860 let count_chars c str =
4861 let count = ref 0 in
4862 for i = 0 to String.length str - 1 do
4863 if c = String.unsafe_get str i then incr count
4867 let name_of_argt = function
4868 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4869 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4870 | FileIn n | FileOut n -> n
4872 let java_name_of_struct typ =
4873 try List.assoc typ java_structs
4876 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4878 let cols_of_struct typ =
4879 try List.assoc typ structs
4881 failwithf "cols_of_struct: unknown struct %s" typ
4883 let seq_of_test = function
4884 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4885 | TestOutputListOfDevices (s, _)
4886 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4887 | TestOutputTrue s | TestOutputFalse s
4888 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4889 | TestOutputStruct (s, _)
4890 | TestLastFail s -> s
4892 (* Handling for function flags. *)
4893 let protocol_limit_warning =
4894 "Because of the message protocol, there is a transfer limit
4895 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4897 let danger_will_robinson =
4898 "B<This command is dangerous. Without careful use you
4899 can easily destroy all your data>."
4901 let deprecation_notice flags =
4904 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4906 sprintf "This function is deprecated.
4907 In new code, use the C<%s> call instead.
4909 Deprecated functions will not be removed from the API, but the
4910 fact that they are deprecated indicates that there are problems
4911 with correct use of these functions." alt in
4916 (* Create list of optional groups. *)
4918 let h = Hashtbl.create 13 in
4920 fun (name, _, _, flags, _, _, _) ->
4924 let names = try Hashtbl.find h group with Not_found -> [] in
4925 Hashtbl.replace h group (name :: names)
4929 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4932 fun group -> group, List.sort compare (Hashtbl.find h group)
4934 List.sort (fun x y -> compare (fst x) (fst y)) groups
4936 (* Check function names etc. for consistency. *)
4937 let check_functions () =
4938 let contains_uppercase str =
4939 let len = String.length str in
4941 if i >= len then false
4944 if c >= 'A' && c <= 'Z' then true
4951 (* Check function names. *)
4953 fun (name, _, _, _, _, _, _) ->
4954 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4955 failwithf "function name %s does not need 'guestfs' prefix" name;
4957 failwithf "function name is empty";
4958 if name.[0] < 'a' || name.[0] > 'z' then
4959 failwithf "function name %s must start with lowercase a-z" name;
4960 if String.contains name '-' then
4961 failwithf "function name %s should not contain '-', use '_' instead."
4965 (* Check function parameter/return names. *)
4967 fun (name, style, _, _, _, _, _) ->
4968 let check_arg_ret_name n =
4969 if contains_uppercase n then
4970 failwithf "%s param/ret %s should not contain uppercase chars"
4972 if String.contains n '-' || String.contains n '_' then
4973 failwithf "%s param/ret %s should not contain '-' or '_'"
4976 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;
4977 if n = "int" || n = "char" || n = "short" || n = "long" then
4978 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4979 if n = "i" || n = "n" then
4980 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4981 if n = "argv" || n = "args" then
4982 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4984 (* List Haskell, OCaml and C keywords here.
4985 * http://www.haskell.org/haskellwiki/Keywords
4986 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4987 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4988 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4989 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4990 * Omitting _-containing words, since they're handled above.
4991 * Omitting the OCaml reserved word, "val", is ok,
4992 * and saves us from renaming several parameters.
4995 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4996 "char"; "class"; "const"; "constraint"; "continue"; "data";
4997 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4998 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4999 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5000 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5001 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5003 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5004 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5005 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5006 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5007 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5008 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5009 "volatile"; "when"; "where"; "while";
5011 if List.mem n reserved then
5012 failwithf "%s has param/ret using reserved word %s" name n;
5015 (match fst style with
5017 | RInt n | RInt64 n | RBool n
5018 | RConstString n | RConstOptString n | RString n
5019 | RStringList n | RStruct (n, _) | RStructList (n, _)
5020 | RHashtable n | RBufferOut n ->
5021 check_arg_ret_name n
5023 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5026 (* Check short descriptions. *)
5028 fun (name, _, _, _, _, shortdesc, _) ->
5029 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5030 failwithf "short description of %s should begin with lowercase." name;
5031 let c = shortdesc.[String.length shortdesc-1] in
5032 if c = '\n' || c = '.' then
5033 failwithf "short description of %s should not end with . or \\n." name
5036 (* Check long dscriptions. *)
5038 fun (name, _, _, _, _, _, longdesc) ->
5039 if longdesc.[String.length longdesc-1] = '\n' then
5040 failwithf "long description of %s should not end with \\n." name
5043 (* Check proc_nrs. *)
5045 fun (name, _, proc_nr, _, _, _, _) ->
5046 if proc_nr <= 0 then
5047 failwithf "daemon function %s should have proc_nr > 0" name
5051 fun (name, _, proc_nr, _, _, _, _) ->
5052 if proc_nr <> -1 then
5053 failwithf "non-daemon function %s should have proc_nr -1" name
5054 ) non_daemon_functions;
5057 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5060 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5061 let rec loop = function
5064 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5066 | (name1,nr1) :: (name2,nr2) :: _ ->
5067 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5075 (* Ignore functions that have no tests. We generate a
5076 * warning when the user does 'make check' instead.
5078 | name, _, _, _, [], _, _ -> ()
5079 | name, _, _, _, tests, _, _ ->
5083 match seq_of_test test with
5085 failwithf "%s has a test containing an empty sequence" name
5086 | cmds -> List.map List.hd cmds
5088 let funcs = List.flatten funcs in
5090 let tested = List.mem name funcs in
5093 failwithf "function %s has tests but does not test itself" name
5096 (* 'pr' prints to the current output file. *)
5097 let chan = ref Pervasives.stdout
5102 let i = count_chars '\n' str in
5103 lines := !lines + i;
5104 output_string !chan str
5107 let copyright_years =
5108 let this_year = 1900 + (localtime (time ())).tm_year in
5109 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5111 (* Generate a header block in a number of standard styles. *)
5112 type comment_style =
5113 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5114 type license = GPLv2plus | LGPLv2plus
5116 let generate_header ?(extra_inputs = []) comment license =
5117 let inputs = "src/generator.ml" :: extra_inputs in
5118 let c = match comment with
5119 | CStyle -> pr "/* "; " *"
5120 | CPlusPlusStyle -> pr "// "; "//"
5121 | HashStyle -> pr "# "; "#"
5122 | OCamlStyle -> pr "(* "; " *"
5123 | HaskellStyle -> pr "{- "; " " in
5124 pr "libguestfs generated file\n";
5125 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5126 List.iter (pr "%s %s\n" c) inputs;
5127 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5129 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5133 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5134 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5135 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5136 pr "%s (at your option) any later version.\n" c;
5138 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5139 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5140 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5141 pr "%s GNU General Public License for more details.\n" c;
5143 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5144 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5145 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5148 pr "%s This library is free software; you can redistribute it and/or\n" c;
5149 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5150 pr "%s License as published by the Free Software Foundation; either\n" c;
5151 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5153 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5154 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5155 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5156 pr "%s Lesser General Public License for more details.\n" c;
5158 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5159 pr "%s License along with this library; if not, write to the Free Software\n" c;
5160 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5163 | CStyle -> pr " */\n"
5166 | OCamlStyle -> pr " *)\n"
5167 | HaskellStyle -> pr "-}\n"
5171 (* Start of main code generation functions below this line. *)
5173 (* Generate the pod documentation for the C API. *)
5174 let rec generate_actions_pod () =
5176 fun (shortname, style, _, flags, _, _, longdesc) ->
5177 if not (List.mem NotInDocs flags) then (
5178 let name = "guestfs_" ^ shortname in
5179 pr "=head2 %s\n\n" name;
5181 generate_prototype ~extern:false ~handle:"handle" name style;
5183 pr "%s\n\n" longdesc;
5184 (match fst style with
5186 pr "This function returns 0 on success or -1 on error.\n\n"
5188 pr "On error this function returns -1.\n\n"
5190 pr "On error this function returns -1.\n\n"
5192 pr "This function returns a C truth value on success or -1 on error.\n\n"
5194 pr "This function returns a string, or NULL on error.
5195 The string is owned by the guest handle and must I<not> be freed.\n\n"
5196 | RConstOptString _ ->
5197 pr "This function returns a string which may be NULL.
5198 There is way to return an error from this function.
5199 The string is owned by the guest handle and must I<not> be freed.\n\n"
5201 pr "This function returns a string, or NULL on error.
5202 I<The caller must free the returned string after use>.\n\n"
5204 pr "This function returns a NULL-terminated array of strings
5205 (like L<environ(3)>), or NULL if there was an error.
5206 I<The caller must free the strings and the array after use>.\n\n"
5207 | RStruct (_, typ) ->
5208 pr "This function returns a C<struct guestfs_%s *>,
5209 or NULL if there was an error.
5210 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5211 | RStructList (_, typ) ->
5212 pr "This function returns a C<struct guestfs_%s_list *>
5213 (see E<lt>guestfs-structs.hE<gt>),
5214 or NULL if there was an error.
5215 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5217 pr "This function returns a NULL-terminated array of
5218 strings, or NULL if there was an error.
5219 The array of strings will always have length C<2n+1>, where
5220 C<n> keys and values alternate, followed by the trailing NULL entry.
5221 I<The caller must free the strings and the array after use>.\n\n"
5223 pr "This function returns a buffer, or NULL on error.
5224 The size of the returned buffer is written to C<*size_r>.
5225 I<The caller must free the returned buffer after use>.\n\n"
5227 if List.mem ProtocolLimitWarning flags then
5228 pr "%s\n\n" protocol_limit_warning;
5229 if List.mem DangerWillRobinson flags then
5230 pr "%s\n\n" danger_will_robinson;
5231 match deprecation_notice flags with
5233 | Some txt -> pr "%s\n\n" txt
5235 ) all_functions_sorted
5237 and generate_structs_pod () =
5238 (* Structs documentation. *)
5241 pr "=head2 guestfs_%s\n" typ;
5243 pr " struct guestfs_%s {\n" typ;
5246 | name, FChar -> pr " char %s;\n" name
5247 | name, FUInt32 -> pr " uint32_t %s;\n" name
5248 | name, FInt32 -> pr " int32_t %s;\n" name
5249 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5250 | name, FInt64 -> pr " int64_t %s;\n" name
5251 | name, FString -> pr " char *%s;\n" name
5253 pr " /* The next two fields describe a byte array. */\n";
5254 pr " uint32_t %s_len;\n" name;
5255 pr " char *%s;\n" name
5257 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5258 pr " char %s[32];\n" name
5259 | name, FOptPercent ->
5260 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5261 pr " float %s;\n" name
5265 pr " struct guestfs_%s_list {\n" typ;
5266 pr " uint32_t len; /* Number of elements in list. */\n";
5267 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5270 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5271 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5276 and generate_availability_pod () =
5277 (* Availability documentation. *)
5281 fun (group, functions) ->
5282 pr "=item B<%s>\n" group;
5284 pr "The following functions:\n";
5285 List.iter (pr "L</guestfs_%s>\n") functions;
5291 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5292 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5294 * We have to use an underscore instead of a dash because otherwise
5295 * rpcgen generates incorrect code.
5297 * This header is NOT exported to clients, but see also generate_structs_h.
5299 and generate_xdr () =
5300 generate_header CStyle LGPLv2plus;
5302 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5303 pr "typedef string str<>;\n";
5306 (* Internal structures. *)
5310 pr "struct guestfs_int_%s {\n" typ;
5312 | name, FChar -> pr " char %s;\n" name
5313 | name, FString -> pr " string %s<>;\n" name
5314 | name, FBuffer -> pr " opaque %s<>;\n" name
5315 | name, FUUID -> pr " opaque %s[32];\n" name
5316 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5317 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5318 | name, FOptPercent -> pr " float %s;\n" name
5322 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5327 fun (shortname, style, _, _, _, _, _) ->
5328 let name = "guestfs_" ^ shortname in
5330 (match snd style with
5333 pr "struct %s_args {\n" name;
5336 | Pathname n | Device n | Dev_or_Path n | String n ->
5337 pr " string %s<>;\n" n
5338 | OptString n -> pr " str *%s;\n" n
5339 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5340 | Bool n -> pr " bool %s;\n" n
5341 | Int n -> pr " int %s;\n" n
5342 | Int64 n -> pr " hyper %s;\n" n
5343 | FileIn _ | FileOut _ -> ()
5347 (match fst style with
5350 pr "struct %s_ret {\n" name;
5354 pr "struct %s_ret {\n" name;
5355 pr " hyper %s;\n" n;
5358 pr "struct %s_ret {\n" name;
5361 | RConstString _ | RConstOptString _ ->
5362 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5364 pr "struct %s_ret {\n" name;
5365 pr " string %s<>;\n" n;
5368 pr "struct %s_ret {\n" name;
5369 pr " str %s<>;\n" n;
5371 | RStruct (n, typ) ->
5372 pr "struct %s_ret {\n" name;
5373 pr " guestfs_int_%s %s;\n" typ n;
5375 | RStructList (n, typ) ->
5376 pr "struct %s_ret {\n" name;
5377 pr " guestfs_int_%s_list %s;\n" typ n;
5380 pr "struct %s_ret {\n" name;
5381 pr " str %s<>;\n" n;
5384 pr "struct %s_ret {\n" name;
5385 pr " opaque %s<>;\n" n;
5390 (* Table of procedure numbers. *)
5391 pr "enum guestfs_procedure {\n";
5393 fun (shortname, _, proc_nr, _, _, _, _) ->
5394 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5396 pr " GUESTFS_PROC_NR_PROCS\n";
5400 (* Having to choose a maximum message size is annoying for several
5401 * reasons (it limits what we can do in the API), but it (a) makes
5402 * the protocol a lot simpler, and (b) provides a bound on the size
5403 * of the daemon which operates in limited memory space.
5405 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5408 (* Message header, etc. *)
5410 /* The communication protocol is now documented in the guestfs(3)
5414 const GUESTFS_PROGRAM = 0x2000F5F5;
5415 const GUESTFS_PROTOCOL_VERSION = 1;
5417 /* These constants must be larger than any possible message length. */
5418 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5419 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5421 enum guestfs_message_direction {
5422 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5423 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5426 enum guestfs_message_status {
5427 GUESTFS_STATUS_OK = 0,
5428 GUESTFS_STATUS_ERROR = 1
5431 const GUESTFS_ERROR_LEN = 256;
5433 struct guestfs_message_error {
5434 string error_message<GUESTFS_ERROR_LEN>;
5437 struct guestfs_message_header {
5438 unsigned prog; /* GUESTFS_PROGRAM */
5439 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5440 guestfs_procedure proc; /* GUESTFS_PROC_x */
5441 guestfs_message_direction direction;
5442 unsigned serial; /* message serial number */
5443 guestfs_message_status status;
5446 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5448 struct guestfs_chunk {
5449 int cancel; /* if non-zero, transfer is cancelled */
5450 /* data size is 0 bytes if the transfer has finished successfully */
5451 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5455 (* Generate the guestfs-structs.h file. *)
5456 and generate_structs_h () =
5457 generate_header CStyle LGPLv2plus;
5459 (* This is a public exported header file containing various
5460 * structures. The structures are carefully written to have
5461 * exactly the same in-memory format as the XDR structures that
5462 * we use on the wire to the daemon. The reason for creating
5463 * copies of these structures here is just so we don't have to
5464 * export the whole of guestfs_protocol.h (which includes much
5465 * unrelated and XDR-dependent stuff that we don't want to be
5466 * public, or required by clients).
5468 * To reiterate, we will pass these structures to and from the
5469 * client with a simple assignment or memcpy, so the format
5470 * must be identical to what rpcgen / the RFC defines.
5473 (* Public structures. *)
5476 pr "struct guestfs_%s {\n" typ;
5479 | name, FChar -> pr " char %s;\n" name
5480 | name, FString -> pr " char *%s;\n" name
5482 pr " uint32_t %s_len;\n" name;
5483 pr " char *%s;\n" name
5484 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5485 | name, FUInt32 -> pr " uint32_t %s;\n" name
5486 | name, FInt32 -> pr " int32_t %s;\n" name
5487 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5488 | name, FInt64 -> pr " int64_t %s;\n" name
5489 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5493 pr "struct guestfs_%s_list {\n" typ;
5494 pr " uint32_t len;\n";
5495 pr " struct guestfs_%s *val;\n" typ;
5498 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5499 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5503 (* Generate the guestfs-actions.h file. *)
5504 and generate_actions_h () =
5505 generate_header CStyle LGPLv2plus;
5507 fun (shortname, style, _, _, _, _, _) ->
5508 let name = "guestfs_" ^ shortname in
5509 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5513 (* Generate the guestfs-internal-actions.h file. *)
5514 and generate_internal_actions_h () =
5515 generate_header CStyle LGPLv2plus;
5517 fun (shortname, style, _, _, _, _, _) ->
5518 let name = "guestfs__" ^ shortname in
5519 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5521 ) non_daemon_functions
5523 (* Generate the client-side dispatch stubs. *)
5524 and generate_client_actions () =
5525 generate_header CStyle LGPLv2plus;
5532 #include <inttypes.h>
5534 #include \"guestfs.h\"
5535 #include \"guestfs-internal.h\"
5536 #include \"guestfs-internal-actions.h\"
5537 #include \"guestfs_protocol.h\"
5539 #define error guestfs_error
5540 //#define perrorf guestfs_perrorf
5541 #define safe_malloc guestfs_safe_malloc
5542 #define safe_realloc guestfs_safe_realloc
5543 //#define safe_strdup guestfs_safe_strdup
5544 #define safe_memdup guestfs_safe_memdup
5546 /* Check the return message from a call for validity. */
5548 check_reply_header (guestfs_h *g,
5549 const struct guestfs_message_header *hdr,
5550 unsigned int proc_nr, unsigned int serial)
5552 if (hdr->prog != GUESTFS_PROGRAM) {
5553 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5556 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5557 error (g, \"wrong protocol version (%%d/%%d)\",
5558 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5561 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5562 error (g, \"unexpected message direction (%%d/%%d)\",
5563 hdr->direction, GUESTFS_DIRECTION_REPLY);
5566 if (hdr->proc != proc_nr) {
5567 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5570 if (hdr->serial != serial) {
5571 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5578 /* Check we are in the right state to run a high-level action. */
5580 check_state (guestfs_h *g, const char *caller)
5582 if (!guestfs__is_ready (g)) {
5583 if (guestfs__is_config (g) || guestfs__is_launching (g))
5584 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5587 error (g, \"%%s called from the wrong state, %%d != READY\",
5588 caller, guestfs__get_state (g));
5596 (* Generate code to generate guestfish call traces. *)
5597 let trace_call shortname style =
5598 pr " if (guestfs__get_trace (g)) {\n";
5601 List.exists (function
5602 | StringList _ | DeviceList _ -> true
5603 | _ -> false) (snd style) in
5609 pr " printf (\"%s\");\n" shortname;
5612 | String n (* strings *)
5618 (* guestfish doesn't support string escaping, so neither do we *)
5619 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5620 | OptString n -> (* string option *)
5621 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5622 pr " else printf (\" null\");\n"
5624 | DeviceList n -> (* string list *)
5625 pr " putchar (' ');\n";
5626 pr " putchar ('\"');\n";
5627 pr " for (i = 0; %s[i]; ++i) {\n" n;
5628 pr " if (i > 0) putchar (' ');\n";
5629 pr " fputs (%s[i], stdout);\n" n;
5631 pr " putchar ('\"');\n";
5632 | Bool n -> (* boolean *)
5633 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5634 | Int n -> (* int *)
5635 pr " printf (\" %%d\", %s);\n" n
5637 pr " printf (\" %%\" PRIi64, %s);\n" n
5639 pr " putchar ('\\n');\n";
5644 (* For non-daemon functions, generate a wrapper around each function. *)
5646 fun (shortname, style, _, _, _, _, _) ->
5647 let name = "guestfs_" ^ shortname in
5649 generate_prototype ~extern:false ~semicolon:false ~newline:true
5650 ~handle:"g" name style;
5652 trace_call shortname style;
5653 pr " return guestfs__%s " shortname;
5654 generate_c_call_args ~handle:"g" style;
5658 ) non_daemon_functions;
5660 (* Client-side stubs for each function. *)
5662 fun (shortname, style, _, _, _, _, _) ->
5663 let name = "guestfs_" ^ shortname in
5665 (* Generate the action stub. *)
5666 generate_prototype ~extern:false ~semicolon:false ~newline:true
5667 ~handle:"g" name style;
5670 match fst style with
5671 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5672 | RConstString _ | RConstOptString _ ->
5673 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5674 | RString _ | RStringList _
5675 | RStruct _ | RStructList _
5676 | RHashtable _ | RBufferOut _ ->
5681 (match snd style with
5683 | _ -> pr " struct %s_args args;\n" name
5686 pr " guestfs_message_header hdr;\n";
5687 pr " guestfs_message_error err;\n";
5689 match fst style with
5691 | RConstString _ | RConstOptString _ ->
5692 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5694 | RBool _ | RString _ | RStringList _
5695 | RStruct _ | RStructList _
5696 | RHashtable _ | RBufferOut _ ->
5697 pr " struct %s_ret ret;\n" name;
5700 pr " int serial;\n";
5703 trace_call shortname style;
5704 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5705 pr " guestfs___set_busy (g);\n";
5708 (* Send the main header and arguments. *)
5709 (match snd style with
5711 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5712 (String.uppercase shortname)
5716 | Pathname n | Device n | Dev_or_Path n | String n ->
5717 pr " args.%s = (char *) %s;\n" n n
5719 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5720 | StringList n | DeviceList n ->
5721 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5722 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5724 pr " args.%s = %s;\n" n n
5726 pr " args.%s = %s;\n" n n
5728 pr " args.%s = %s;\n" n n
5729 | FileIn _ | FileOut _ -> ()
5731 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5732 (String.uppercase shortname);
5733 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5736 pr " if (serial == -1) {\n";
5737 pr " guestfs___end_busy (g);\n";
5738 pr " return %s;\n" error_code;
5742 (* Send any additional files (FileIn) requested. *)
5743 let need_read_reply_label = ref false in
5747 pr " r = guestfs___send_file (g, %s);\n" n;
5748 pr " if (r == -1) {\n";
5749 pr " guestfs___end_busy (g);\n";
5750 pr " return %s;\n" error_code;
5752 pr " if (r == -2) /* daemon cancelled */\n";
5753 pr " goto read_reply;\n";
5754 need_read_reply_label := true;
5759 (* Wait for the reply from the remote end. *)
5760 if !need_read_reply_label then pr " read_reply:\n";
5761 pr " memset (&hdr, 0, sizeof hdr);\n";
5762 pr " memset (&err, 0, sizeof err);\n";
5763 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5765 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5769 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5772 pr " if (r == -1) {\n";
5773 pr " guestfs___end_busy (g);\n";
5774 pr " return %s;\n" error_code;
5778 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5779 (String.uppercase shortname);
5780 pr " guestfs___end_busy (g);\n";
5781 pr " return %s;\n" error_code;
5785 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5786 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5787 pr " free (err.error_message);\n";
5788 pr " guestfs___end_busy (g);\n";
5789 pr " return %s;\n" error_code;
5793 (* Expecting to receive further files (FileOut)? *)
5797 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5798 pr " guestfs___end_busy (g);\n";
5799 pr " return %s;\n" error_code;
5805 pr " guestfs___end_busy (g);\n";
5807 (match fst style with
5808 | RErr -> pr " return 0;\n"
5809 | RInt n | RInt64 n | RBool n ->
5810 pr " return ret.%s;\n" n
5811 | RConstString _ | RConstOptString _ ->
5812 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5814 pr " return ret.%s; /* caller will free */\n" n
5815 | RStringList n | RHashtable n ->
5816 pr " /* caller will free this, but we need to add a NULL entry */\n";
5817 pr " ret.%s.%s_val =\n" n n;
5818 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5819 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5821 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5822 pr " return ret.%s.%s_val;\n" n n
5824 pr " /* caller will free this */\n";
5825 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5826 | RStructList (n, _) ->
5827 pr " /* caller will free this */\n";
5828 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5830 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5831 pr " * _val might be NULL here. To make the API saner for\n";
5832 pr " * callers, we turn this case into a unique pointer (using\n";
5833 pr " * malloc(1)).\n";
5835 pr " if (ret.%s.%s_len > 0) {\n" n n;
5836 pr " *size_r = ret.%s.%s_len;\n" n n;
5837 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5839 pr " free (ret.%s.%s_val);\n" n n;
5840 pr " char *p = safe_malloc (g, 1);\n";
5841 pr " *size_r = ret.%s.%s_len;\n" n n;
5849 (* Functions to free structures. *)
5850 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5851 pr " * structure format is identical to the XDR format. See note in\n";
5852 pr " * generator.ml.\n";
5859 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5861 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5867 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5869 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5876 (* Generate daemon/actions.h. *)
5877 and generate_daemon_actions_h () =
5878 generate_header CStyle GPLv2plus;
5880 pr "#include \"../src/guestfs_protocol.h\"\n";
5884 fun (name, style, _, _, _, _, _) ->
5886 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5890 (* Generate the linker script which controls the visibility of
5891 * symbols in the public ABI and ensures no other symbols get
5892 * exported accidentally.
5894 and generate_linker_script () =
5895 generate_header HashStyle GPLv2plus;
5900 "guestfs_get_error_handler";
5901 "guestfs_get_out_of_memory_handler";
5902 "guestfs_last_error";
5903 "guestfs_set_error_handler";
5904 "guestfs_set_launch_done_callback";
5905 "guestfs_set_log_message_callback";
5906 "guestfs_set_out_of_memory_handler";
5907 "guestfs_set_subprocess_quit_callback";
5909 (* Unofficial parts of the API: the bindings code use these
5910 * functions, so it is useful to export them.
5912 "guestfs_safe_calloc";
5913 "guestfs_safe_malloc";
5916 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5920 List.map (fun (typ, _) ->
5921 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5924 let globals = List.sort compare (globals @ functions @ structs) in
5928 List.iter (pr " %s;\n") globals;
5935 (* Generate the server-side stubs. *)
5936 and generate_daemon_actions () =
5937 generate_header CStyle GPLv2plus;
5939 pr "#include <config.h>\n";
5941 pr "#include <stdio.h>\n";
5942 pr "#include <stdlib.h>\n";
5943 pr "#include <string.h>\n";
5944 pr "#include <inttypes.h>\n";
5945 pr "#include <rpc/types.h>\n";
5946 pr "#include <rpc/xdr.h>\n";
5948 pr "#include \"daemon.h\"\n";
5949 pr "#include \"c-ctype.h\"\n";
5950 pr "#include \"../src/guestfs_protocol.h\"\n";
5951 pr "#include \"actions.h\"\n";
5955 fun (name, style, _, _, _, _, _) ->
5956 (* Generate server-side stubs. *)
5957 pr "static void %s_stub (XDR *xdr_in)\n" name;
5960 match fst style with
5961 | RErr | RInt _ -> pr " int r;\n"; "-1"
5962 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5963 | RBool _ -> pr " int r;\n"; "-1"
5964 | RConstString _ | RConstOptString _ ->
5965 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5966 | RString _ -> pr " char *r;\n"; "NULL"
5967 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5968 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5969 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5971 pr " size_t size = 1;\n";
5975 (match snd style with
5978 pr " struct guestfs_%s_args args;\n" name;
5981 | Device n | Dev_or_Path n
5984 | OptString n -> pr " char *%s;\n" n
5985 | StringList n | DeviceList n -> pr " char **%s;\n" n
5986 | Bool n -> pr " int %s;\n" n
5987 | Int n -> pr " int %s;\n" n
5988 | Int64 n -> pr " int64_t %s;\n" n
5989 | FileIn _ | FileOut _ -> ()
5994 (match snd style with
5997 pr " memset (&args, 0, sizeof args);\n";
5999 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6000 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6004 pr " char *%s = args.%s;\n" n n
6006 let pr_list_handling_code n =
6007 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6008 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6009 pr " if (%s == NULL) {\n" n;
6010 pr " reply_with_perror (\"realloc\");\n";
6013 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6014 pr " args.%s.%s_val = %s;\n" n n n;
6020 pr " ABS_PATH (%s, goto done);\n" n;
6023 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6026 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6027 | String n -> pr_args n
6028 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6030 pr_list_handling_code n;
6032 pr_list_handling_code n;
6033 pr " /* Ensure that each is a device,\n";
6034 pr " * and perform device name translation. */\n";
6035 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6036 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6038 | Bool n -> pr " %s = args.%s;\n" n n
6039 | Int n -> pr " %s = args.%s;\n" n n
6040 | Int64 n -> pr " %s = args.%s;\n" n n
6041 | FileIn _ | FileOut _ -> ()
6047 (* this is used at least for do_equal *)
6048 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6049 (* Emit NEED_ROOT just once, even when there are two or
6050 more Pathname args *)
6051 pr " NEED_ROOT (goto done);\n";
6054 (* Don't want to call the impl with any FileIn or FileOut
6055 * parameters, since these go "outside" the RPC protocol.
6058 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6060 pr " r = do_%s " name;
6061 generate_c_call_args (fst style, args');
6064 (match fst style with
6065 | RErr | RInt _ | RInt64 _ | RBool _
6066 | RConstString _ | RConstOptString _
6067 | RString _ | RStringList _ | RHashtable _
6068 | RStruct (_, _) | RStructList (_, _) ->
6069 pr " if (r == %s)\n" error_code;
6070 pr " /* do_%s has already called reply_with_error */\n" name;
6074 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6075 pr " * an ordinary zero-length buffer), so be careful ...\n";
6077 pr " if (size == 1 && r == %s)\n" error_code;
6078 pr " /* do_%s has already called reply_with_error */\n" name;
6083 (* If there are any FileOut parameters, then the impl must
6084 * send its own reply.
6087 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6089 pr " /* do_%s has already sent a reply */\n" name
6091 match fst style with
6092 | RErr -> pr " reply (NULL, NULL);\n"
6093 | RInt n | RInt64 n | RBool n ->
6094 pr " struct guestfs_%s_ret ret;\n" name;
6095 pr " ret.%s = r;\n" n;
6096 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6098 | RConstString _ | RConstOptString _ ->
6099 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6101 pr " struct guestfs_%s_ret ret;\n" name;
6102 pr " ret.%s = r;\n" n;
6103 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6106 | RStringList n | RHashtable n ->
6107 pr " struct guestfs_%s_ret ret;\n" name;
6108 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6109 pr " ret.%s.%s_val = r;\n" n n;
6110 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6112 pr " free_strings (r);\n"
6114 pr " struct guestfs_%s_ret ret;\n" name;
6115 pr " ret.%s = *r;\n" n;
6116 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6118 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6120 | RStructList (n, _) ->
6121 pr " struct guestfs_%s_ret ret;\n" name;
6122 pr " ret.%s = *r;\n" n;
6123 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6125 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6128 pr " struct guestfs_%s_ret ret;\n" name;
6129 pr " ret.%s.%s_val = r;\n" n n;
6130 pr " ret.%s.%s_len = size;\n" n n;
6131 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6136 (* Free the args. *)
6137 (match snd style with
6142 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6149 (* Dispatch function. *)
6150 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6152 pr " switch (proc_nr) {\n";
6155 fun (name, style, _, _, _, _, _) ->
6156 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6157 pr " %s_stub (xdr_in);\n" name;
6162 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";
6167 (* LVM columns and tokenization functions. *)
6168 (* XXX This generates crap code. We should rethink how we
6174 pr "static const char *lvm_%s_cols = \"%s\";\n"
6175 typ (String.concat "," (List.map fst cols));
6178 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6180 pr " char *tok, *p, *next;\n";
6184 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6187 pr " if (!str) {\n";
6188 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6191 pr " if (!*str || c_isspace (*str)) {\n";
6192 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6197 fun (name, coltype) ->
6198 pr " if (!tok) {\n";
6199 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6202 pr " p = strchrnul (tok, ',');\n";
6203 pr " if (*p) next = p+1; else next = NULL;\n";
6204 pr " *p = '\\0';\n";
6207 pr " r->%s = strdup (tok);\n" name;
6208 pr " if (r->%s == NULL) {\n" name;
6209 pr " perror (\"strdup\");\n";
6213 pr " for (i = j = 0; i < 32; ++j) {\n";
6214 pr " if (tok[j] == '\\0') {\n";
6215 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6217 pr " } else if (tok[j] != '-')\n";
6218 pr " r->%s[i++] = tok[j];\n" name;
6221 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6222 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6226 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6227 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6231 pr " if (tok[0] == '\\0')\n";
6232 pr " r->%s = -1;\n" name;
6233 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6234 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6237 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6238 assert false (* can never be an LVM column *)
6240 pr " tok = next;\n";
6243 pr " if (tok != NULL) {\n";
6244 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6251 pr "guestfs_int_lvm_%s_list *\n" typ;
6252 pr "parse_command_line_%ss (void)\n" typ;
6254 pr " char *out, *err;\n";
6255 pr " char *p, *pend;\n";
6257 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6258 pr " void *newp;\n";
6260 pr " ret = malloc (sizeof *ret);\n";
6261 pr " if (!ret) {\n";
6262 pr " reply_with_perror (\"malloc\");\n";
6263 pr " return NULL;\n";
6266 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6267 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6269 pr " r = command (&out, &err,\n";
6270 pr " \"lvm\", \"%ss\",\n" typ;
6271 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6272 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6273 pr " if (r == -1) {\n";
6274 pr " reply_with_error (\"%%s\", err);\n";
6275 pr " free (out);\n";
6276 pr " free (err);\n";
6277 pr " free (ret);\n";
6278 pr " return NULL;\n";
6281 pr " free (err);\n";
6283 pr " /* Tokenize each line of the output. */\n";
6286 pr " while (p) {\n";
6287 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6288 pr " if (pend) {\n";
6289 pr " *pend = '\\0';\n";
6293 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6296 pr " if (!*p) { /* Empty line? Skip it. */\n";
6301 pr " /* Allocate some space to store this next entry. */\n";
6302 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6303 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6304 pr " if (newp == NULL) {\n";
6305 pr " reply_with_perror (\"realloc\");\n";
6306 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6307 pr " free (ret);\n";
6308 pr " free (out);\n";
6309 pr " return NULL;\n";
6311 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6313 pr " /* Tokenize the next entry. */\n";
6314 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6315 pr " if (r == -1) {\n";
6316 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6317 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6318 pr " free (ret);\n";
6319 pr " free (out);\n";
6320 pr " return NULL;\n";
6327 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6329 pr " free (out);\n";
6330 pr " return ret;\n";
6333 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6335 (* Generate a list of function names, for debugging in the daemon.. *)
6336 and generate_daemon_names () =
6337 generate_header CStyle GPLv2plus;
6339 pr "#include <config.h>\n";
6341 pr "#include \"daemon.h\"\n";
6344 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6345 pr "const char *function_names[] = {\n";
6347 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6351 (* Generate the optional groups for the daemon to implement
6352 * guestfs_available.
6354 and generate_daemon_optgroups_c () =
6355 generate_header CStyle GPLv2plus;
6357 pr "#include <config.h>\n";
6359 pr "#include \"daemon.h\"\n";
6360 pr "#include \"optgroups.h\"\n";
6363 pr "struct optgroup optgroups[] = {\n";
6366 pr " { \"%s\", optgroup_%s_available },\n" group group
6368 pr " { NULL, NULL }\n";
6371 and generate_daemon_optgroups_h () =
6372 generate_header CStyle GPLv2plus;
6376 pr "extern int optgroup_%s_available (void);\n" group
6379 (* Generate the tests. *)
6380 and generate_tests () =
6381 generate_header CStyle GPLv2plus;
6388 #include <sys/types.h>
6391 #include \"guestfs.h\"
6392 #include \"guestfs-internal.h\"
6394 static guestfs_h *g;
6395 static int suppress_error = 0;
6397 static void print_error (guestfs_h *g, void *data, const char *msg)
6399 if (!suppress_error)
6400 fprintf (stderr, \"%%s\\n\", msg);
6403 /* FIXME: nearly identical code appears in fish.c */
6404 static void print_strings (char *const *argv)
6408 for (argc = 0; argv[argc] != NULL; ++argc)
6409 printf (\"\\t%%s\\n\", argv[argc]);
6413 static void print_table (char const *const *argv)
6417 for (i = 0; argv[i] != NULL; i += 2)
6418 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6424 (* Generate a list of commands which are not tested anywhere. *)
6425 pr "static void no_test_warnings (void)\n";
6428 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6430 fun (_, _, _, _, tests, _, _) ->
6431 let tests = filter_map (
6433 | (_, (Always|If _|Unless _), test) -> Some test
6434 | (_, Disabled, _) -> None
6436 let seq = List.concat (List.map seq_of_test tests) in
6437 let cmds_tested = List.map List.hd seq in
6438 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6442 fun (name, _, _, _, _, _, _) ->
6443 if not (Hashtbl.mem hash name) then
6444 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6450 (* Generate the actual tests. Note that we generate the tests
6451 * in reverse order, deliberately, so that (in general) the
6452 * newest tests run first. This makes it quicker and easier to
6457 fun (name, _, _, flags, tests, _, _) ->
6458 mapi (generate_one_test name flags) tests
6459 ) (List.rev all_functions) in
6460 let test_names = List.concat test_names in
6461 let nr_tests = List.length test_names in
6464 int main (int argc, char *argv[])
6467 unsigned long int n_failed = 0;
6468 const char *filename;
6470 int nr_tests, test_num = 0;
6472 setbuf (stdout, NULL);
6474 no_test_warnings ();
6476 g = guestfs_create ();
6478 printf (\"guestfs_create FAILED\\n\");
6479 exit (EXIT_FAILURE);
6482 guestfs_set_error_handler (g, print_error, NULL);
6484 guestfs_set_path (g, \"../appliance\");
6486 filename = \"test1.img\";
6487 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6490 exit (EXIT_FAILURE);
6492 if (lseek (fd, %d, SEEK_SET) == -1) {
6496 exit (EXIT_FAILURE);
6498 if (write (fd, &c, 1) == -1) {
6502 exit (EXIT_FAILURE);
6504 if (close (fd) == -1) {
6507 exit (EXIT_FAILURE);
6509 if (guestfs_add_drive (g, filename) == -1) {
6510 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6511 exit (EXIT_FAILURE);
6514 filename = \"test2.img\";
6515 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6518 exit (EXIT_FAILURE);
6520 if (lseek (fd, %d, SEEK_SET) == -1) {
6524 exit (EXIT_FAILURE);
6526 if (write (fd, &c, 1) == -1) {
6530 exit (EXIT_FAILURE);
6532 if (close (fd) == -1) {
6535 exit (EXIT_FAILURE);
6537 if (guestfs_add_drive (g, filename) == -1) {
6538 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6539 exit (EXIT_FAILURE);
6542 filename = \"test3.img\";
6543 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6546 exit (EXIT_FAILURE);
6548 if (lseek (fd, %d, SEEK_SET) == -1) {
6552 exit (EXIT_FAILURE);
6554 if (write (fd, &c, 1) == -1) {
6558 exit (EXIT_FAILURE);
6560 if (close (fd) == -1) {
6563 exit (EXIT_FAILURE);
6565 if (guestfs_add_drive (g, filename) == -1) {
6566 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6567 exit (EXIT_FAILURE);
6570 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6571 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6572 exit (EXIT_FAILURE);
6575 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6578 if (guestfs_launch (g) == -1) {
6579 printf (\"guestfs_launch FAILED\\n\");
6580 exit (EXIT_FAILURE);
6583 /* Cancel previous alarm. */
6588 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6592 pr " test_num++;\n";
6593 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6594 pr " if (%s () == -1) {\n" test_name;
6595 pr " printf (\"%s FAILED\\n\");\n" test_name;
6596 pr " n_failed++;\n";
6601 pr " guestfs_close (g);\n";
6602 pr " unlink (\"test1.img\");\n";
6603 pr " unlink (\"test2.img\");\n";
6604 pr " unlink (\"test3.img\");\n";
6607 pr " if (n_failed > 0) {\n";
6608 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6609 pr " exit (EXIT_FAILURE);\n";
6613 pr " exit (EXIT_SUCCESS);\n";
6616 and generate_one_test name flags i (init, prereq, test) =
6617 let test_name = sprintf "test_%s_%d" name i in
6620 static int %s_skip (void)
6624 str = getenv (\"TEST_ONLY\");
6626 return strstr (str, \"%s\") == NULL;
6627 str = getenv (\"SKIP_%s\");
6628 if (str && STREQ (str, \"1\")) return 1;
6629 str = getenv (\"SKIP_TEST_%s\");
6630 if (str && STREQ (str, \"1\")) return 1;
6634 " test_name name (String.uppercase test_name) (String.uppercase name);
6637 | Disabled | Always -> ()
6638 | If code | Unless code ->
6639 pr "static int %s_prereq (void)\n" test_name;
6647 static int %s (void)
6650 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6654 " test_name test_name test_name;
6656 (* Optional functions should only be tested if the relevant
6657 * support is available in the daemon.
6663 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6665 pr " suppress_error = 1;\n";
6666 pr " r = guestfs_available (g, (char **) groups);\n";
6667 pr " suppress_error = 0;\n";
6668 pr " if (r == -1) {\n";
6669 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6678 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6680 pr " if (! %s_prereq ()) {\n" test_name;
6681 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6685 generate_one_test_body name i test_name init test;
6687 pr " if (%s_prereq ()) {\n" test_name;
6688 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6692 generate_one_test_body name i test_name init test;
6694 generate_one_test_body name i test_name init test
6702 and generate_one_test_body name i test_name init test =
6704 | InitNone (* XXX at some point, InitNone and InitEmpty became
6705 * folded together as the same thing. Really we should
6706 * make InitNone do nothing at all, but the tests may
6707 * need to be checked to make sure this is OK.
6710 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6711 List.iter (generate_test_command_call test_name)
6712 [["blockdev_setrw"; "/dev/sda"];
6716 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6717 List.iter (generate_test_command_call test_name)
6718 [["blockdev_setrw"; "/dev/sda"];
6721 ["part_disk"; "/dev/sda"; "mbr"]]
6723 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6724 List.iter (generate_test_command_call test_name)
6725 [["blockdev_setrw"; "/dev/sda"];
6728 ["part_disk"; "/dev/sda"; "mbr"];
6729 ["mkfs"; "ext2"; "/dev/sda1"];
6730 ["mount_options"; ""; "/dev/sda1"; "/"]]
6731 | InitBasicFSonLVM ->
6732 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6734 List.iter (generate_test_command_call test_name)
6735 [["blockdev_setrw"; "/dev/sda"];
6738 ["part_disk"; "/dev/sda"; "mbr"];
6739 ["pvcreate"; "/dev/sda1"];
6740 ["vgcreate"; "VG"; "/dev/sda1"];
6741 ["lvcreate"; "LV"; "VG"; "8"];
6742 ["mkfs"; "ext2"; "/dev/VG/LV"];
6743 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6745 pr " /* InitISOFS for %s */\n" test_name;
6746 List.iter (generate_test_command_call test_name)
6747 [["blockdev_setrw"; "/dev/sda"];
6750 ["mount_ro"; "/dev/sdd"; "/"]]
6753 let get_seq_last = function
6755 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6758 let seq = List.rev seq in
6759 List.rev (List.tl seq), List.hd seq
6764 pr " /* TestRun for %s (%d) */\n" name i;
6765 List.iter (generate_test_command_call test_name) seq
6766 | TestOutput (seq, expected) ->
6767 pr " /* TestOutput for %s (%d) */\n" name i;
6768 pr " const char *expected = \"%s\";\n" (c_quote expected);
6769 let seq, last = get_seq_last seq in
6771 pr " if (STRNEQ (r, expected)) {\n";
6772 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6776 List.iter (generate_test_command_call test_name) seq;
6777 generate_test_command_call ~test test_name last
6778 | TestOutputList (seq, expected) ->
6779 pr " /* TestOutputList for %s (%d) */\n" name i;
6780 let seq, last = get_seq_last seq in
6784 pr " if (!r[%d]) {\n" i;
6785 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6786 pr " print_strings (r);\n";
6790 pr " const char *expected = \"%s\";\n" (c_quote str);
6791 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6792 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6797 pr " if (r[%d] != NULL) {\n" (List.length expected);
6798 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6800 pr " print_strings (r);\n";
6804 List.iter (generate_test_command_call test_name) seq;
6805 generate_test_command_call ~test test_name last
6806 | TestOutputListOfDevices (seq, expected) ->
6807 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6808 let seq, last = get_seq_last seq in
6812 pr " if (!r[%d]) {\n" i;
6813 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6814 pr " print_strings (r);\n";
6818 pr " const char *expected = \"%s\";\n" (c_quote str);
6819 pr " r[%d][5] = 's';\n" i;
6820 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6821 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6826 pr " if (r[%d] != NULL) {\n" (List.length expected);
6827 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6829 pr " print_strings (r);\n";
6833 List.iter (generate_test_command_call test_name) seq;
6834 generate_test_command_call ~test test_name last
6835 | TestOutputInt (seq, expected) ->
6836 pr " /* TestOutputInt for %s (%d) */\n" name i;
6837 let seq, last = get_seq_last seq in
6839 pr " if (r != %d) {\n" expected;
6840 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6846 List.iter (generate_test_command_call test_name) seq;
6847 generate_test_command_call ~test test_name last
6848 | TestOutputIntOp (seq, op, expected) ->
6849 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6850 let seq, last = get_seq_last seq in
6852 pr " if (! (r %s %d)) {\n" op expected;
6853 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6854 test_name op expected;
6859 List.iter (generate_test_command_call test_name) seq;
6860 generate_test_command_call ~test test_name last
6861 | TestOutputTrue seq ->
6862 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6863 let seq, last = get_seq_last seq in
6866 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6871 List.iter (generate_test_command_call test_name) seq;
6872 generate_test_command_call ~test test_name last
6873 | TestOutputFalse seq ->
6874 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6875 let seq, last = get_seq_last seq in
6878 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6883 List.iter (generate_test_command_call test_name) seq;
6884 generate_test_command_call ~test test_name last
6885 | TestOutputLength (seq, expected) ->
6886 pr " /* TestOutputLength for %s (%d) */\n" name i;
6887 let seq, last = get_seq_last seq in
6890 pr " for (j = 0; j < %d; ++j)\n" expected;
6891 pr " if (r[j] == NULL) {\n";
6892 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6894 pr " print_strings (r);\n";
6897 pr " if (r[j] != NULL) {\n";
6898 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6900 pr " print_strings (r);\n";
6904 List.iter (generate_test_command_call test_name) seq;
6905 generate_test_command_call ~test test_name last
6906 | TestOutputBuffer (seq, expected) ->
6907 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6908 pr " const char *expected = \"%s\";\n" (c_quote expected);
6909 let seq, last = get_seq_last seq in
6910 let len = String.length expected in
6912 pr " if (size != %d) {\n" len;
6913 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6916 pr " if (STRNEQLEN (r, expected, size)) {\n";
6917 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6921 List.iter (generate_test_command_call test_name) seq;
6922 generate_test_command_call ~test test_name last
6923 | TestOutputStruct (seq, checks) ->
6924 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6925 let seq, last = get_seq_last seq in
6929 | CompareWithInt (field, expected) ->
6930 pr " if (r->%s != %d) {\n" field expected;
6931 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6932 test_name field expected;
6933 pr " (int) r->%s);\n" field;
6936 | CompareWithIntOp (field, op, expected) ->
6937 pr " if (!(r->%s %s %d)) {\n" field op expected;
6938 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6939 test_name field op expected;
6940 pr " (int) r->%s);\n" field;
6943 | CompareWithString (field, expected) ->
6944 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6945 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6946 test_name field expected;
6947 pr " r->%s);\n" field;
6950 | CompareFieldsIntEq (field1, field2) ->
6951 pr " if (r->%s != r->%s) {\n" field1 field2;
6952 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6953 test_name field1 field2;
6954 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6957 | CompareFieldsStrEq (field1, field2) ->
6958 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6959 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6960 test_name field1 field2;
6961 pr " r->%s, r->%s);\n" field1 field2;
6966 List.iter (generate_test_command_call test_name) seq;
6967 generate_test_command_call ~test test_name last
6968 | TestLastFail seq ->
6969 pr " /* TestLastFail for %s (%d) */\n" name i;
6970 let seq, last = get_seq_last seq in
6971 List.iter (generate_test_command_call test_name) seq;
6972 generate_test_command_call test_name ~expect_error:true last
6974 (* Generate the code to run a command, leaving the result in 'r'.
6975 * If you expect to get an error then you should set expect_error:true.
6977 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6979 | [] -> assert false
6981 (* Look up the command to find out what args/ret it has. *)
6984 let _, style, _, _, _, _, _ =
6985 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6988 failwithf "%s: in test, command %s was not found" test_name name in
6990 if List.length (snd style) <> List.length args then
6991 failwithf "%s: in test, wrong number of args given to %s"
6998 | OptString n, "NULL" -> ()
7001 | Dev_or_Path n, arg
7003 | OptString n, arg ->
7004 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7008 | FileIn _, _ | FileOut _, _ -> ()
7009 | StringList n, "" | DeviceList n, "" ->
7010 pr " const char *const %s[1] = { NULL };\n" n
7011 | StringList n, arg | DeviceList n, arg ->
7012 let strs = string_split " " arg in
7015 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7017 pr " const char *const %s[] = {\n" n;
7019 fun i _ -> pr " %s_%d,\n" n i
7023 ) (List.combine (snd style) args);
7026 match fst style with
7027 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7028 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7029 | RConstString _ | RConstOptString _ ->
7030 pr " const char *r;\n"; "NULL"
7031 | RString _ -> pr " char *r;\n"; "NULL"
7032 | RStringList _ | RHashtable _ ->
7036 | RStruct (_, typ) ->
7037 pr " struct guestfs_%s *r;\n" typ; "NULL"
7038 | RStructList (_, typ) ->
7039 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7042 pr " size_t size;\n";
7045 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7046 pr " r = guestfs_%s (g" name;
7048 (* Generate the parameters. *)
7051 | OptString _, "NULL" -> pr ", NULL"
7053 | Device n, _ | Dev_or_Path n, _
7057 | FileIn _, arg | FileOut _, arg ->
7058 pr ", \"%s\"" (c_quote arg)
7059 | StringList n, _ | DeviceList n, _ ->
7060 pr ", (char **) %s" n
7063 try int_of_string arg
7064 with Failure "int_of_string" ->
7065 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7069 try Int64.of_string arg
7070 with Failure "int_of_string" ->
7071 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7074 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7075 ) (List.combine (snd style) args);
7077 (match fst style with
7078 | RBufferOut _ -> pr ", &size"
7084 if not expect_error then
7085 pr " if (r == %s)\n" error_code
7087 pr " if (r != %s)\n" error_code;
7090 (* Insert the test code. *)
7096 (match fst style with
7097 | RErr | RInt _ | RInt64 _ | RBool _
7098 | RConstString _ | RConstOptString _ -> ()
7099 | RString _ | RBufferOut _ -> pr " free (r);\n"
7100 | RStringList _ | RHashtable _ ->
7101 pr " for (i = 0; r[i] != NULL; ++i)\n";
7102 pr " free (r[i]);\n";
7104 | RStruct (_, typ) ->
7105 pr " guestfs_free_%s (r);\n" typ
7106 | RStructList (_, typ) ->
7107 pr " guestfs_free_%s_list (r);\n" typ
7113 let str = replace_str str "\r" "\\r" in
7114 let str = replace_str str "\n" "\\n" in
7115 let str = replace_str str "\t" "\\t" in
7116 let str = replace_str str "\000" "\\0" in
7119 (* Generate a lot of different functions for guestfish. *)
7120 and generate_fish_cmds () =
7121 generate_header CStyle GPLv2plus;
7125 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7127 let all_functions_sorted =
7129 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7130 ) all_functions_sorted in
7132 pr "#include <config.h>\n";
7134 pr "#include <stdio.h>\n";
7135 pr "#include <stdlib.h>\n";
7136 pr "#include <string.h>\n";
7137 pr "#include <inttypes.h>\n";
7139 pr "#include <guestfs.h>\n";
7140 pr "#include \"c-ctype.h\"\n";
7141 pr "#include \"full-write.h\"\n";
7142 pr "#include \"xstrtol.h\"\n";
7143 pr "#include \"fish.h\"\n";
7146 (* list_commands function, which implements guestfish -h *)
7147 pr "void list_commands (void)\n";
7149 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7150 pr " list_builtin_commands ();\n";
7152 fun (name, _, _, flags, _, shortdesc, _) ->
7153 let name = replace_char name '_' '-' in
7154 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7156 ) all_functions_sorted;
7157 pr " printf (\" %%s\\n\",";
7158 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7162 (* display_command function, which implements guestfish -h cmd *)
7163 pr "void display_command (const char *cmd)\n";
7166 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7167 let name2 = replace_char name '_' '-' in
7169 try find_map (function FishAlias n -> Some n | _ -> None) flags
7170 with Not_found -> name in
7171 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7173 match snd style with
7177 name2 (String.concat " " (List.map name_of_argt args)) in
7180 if List.mem ProtocolLimitWarning flags then
7181 ("\n\n" ^ protocol_limit_warning)
7184 (* For DangerWillRobinson commands, we should probably have
7185 * guestfish prompt before allowing you to use them (especially
7186 * in interactive mode). XXX
7190 if List.mem DangerWillRobinson flags then
7191 ("\n\n" ^ danger_will_robinson)
7196 match deprecation_notice flags with
7198 | Some txt -> "\n\n" ^ txt in
7200 let describe_alias =
7201 if name <> alias then
7202 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7206 pr "STRCASEEQ (cmd, \"%s\")" name;
7207 if name <> name2 then
7208 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7209 if name <> alias then
7210 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7212 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7214 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7215 "=head1 DESCRIPTION\n\n" ^
7216 longdesc ^ warnings ^ describe_alias);
7219 pr " display_builtin_command (cmd);\n";
7223 let emit_print_list_function typ =
7224 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7227 pr " unsigned int i;\n";
7229 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7230 pr " printf (\"[%%d] = {\\n\", i);\n";
7231 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7232 pr " printf (\"}\\n\");\n";
7238 (* print_* functions *)
7242 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7244 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7247 pr " unsigned int i;\n";
7253 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7255 pr " printf (\"%%s%s: \", indent);\n" name;
7256 pr " for (i = 0; i < 32; ++i)\n";
7257 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7258 pr " printf (\"\\n\");\n"
7260 pr " printf (\"%%s%s: \", indent);\n" name;
7261 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7262 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7263 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7265 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7266 pr " printf (\"\\n\");\n"
7267 | name, (FUInt64|FBytes) ->
7268 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7271 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7274 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7277 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7280 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7282 | name, FOptPercent ->
7283 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7284 typ name name typ name;
7285 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7291 (* Emit a print_TYPE_list function definition only if that function is used. *)
7294 | typ, (RStructListOnly | RStructAndList) ->
7295 (* generate the function for typ *)
7296 emit_print_list_function typ
7297 | typ, _ -> () (* empty *)
7298 ) (rstructs_used_by all_functions);
7300 (* Emit a print_TYPE function definition only if that function is used. *)
7303 | typ, (RStructOnly | RStructAndList) ->
7304 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7306 pr " print_%s_indent (%s, \"\");\n" typ typ;
7309 | typ, _ -> () (* empty *)
7310 ) (rstructs_used_by all_functions);
7312 (* run_<action> actions *)
7314 fun (name, style, _, flags, _, _, _) ->
7315 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7317 (match fst style with
7320 | RBool _ -> pr " int r;\n"
7321 | RInt64 _ -> pr " int64_t r;\n"
7322 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7323 | RString _ -> pr " char *r;\n"
7324 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7325 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7326 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7329 pr " size_t size;\n";
7337 | FileOut n -> pr " const char *%s;\n" n
7339 | Dev_or_Path n -> pr " char *%s;\n" n
7340 | StringList n | DeviceList n -> pr " char **%s;\n" n
7341 | Bool n -> pr " int %s;\n" n
7342 | Int n -> pr " int %s;\n" n
7343 | Int64 n -> pr " int64_t %s;\n" n
7346 (* Check and convert parameters. *)
7347 let argc_expected = List.length (snd style) in
7348 pr " if (argc != %d) {\n" argc_expected;
7349 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7351 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7355 let parse_integer fn fntyp rtyp range name i =
7357 pr " strtol_error xerr;\n";
7358 pr " %s r;\n" fntyp;
7360 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7361 pr " if (xerr != LONGINT_OK) {\n";
7362 pr " fprintf (stderr,\n";
7363 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7364 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7369 | Some (min, max, comment) ->
7370 pr " /* %s */\n" comment;
7371 pr " if (r < %s || r > %s) {\n" min max;
7372 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7376 pr " /* The check above should ensure this assignment does not overflow. */\n";
7378 pr " %s = r;\n" name;
7387 pr " %s = argv[%d];\n" name i
7389 | Dev_or_Path name ->
7390 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7391 pr " if (%s == NULL) return -1;\n" name
7393 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7396 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7399 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7401 | StringList name | DeviceList name ->
7402 pr " %s = parse_string_list (argv[%d]);\n" name i;
7403 pr " if (%s == NULL) return -1;\n" name;
7405 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7408 let min = "(-(2LL<<30))"
7409 and max = "((2LL<<30)-1)"
7411 "The Int type in the generator is a signed 31 bit int." in
7412 Some (min, max, comment) in
7413 parse_integer "xstrtoll" "long long" "int" range name i
7415 parse_integer "xstrtoll" "long long" "int64_t" None name i
7418 (* Call C API function. *)
7420 try find_map (function FishAction n -> Some n | _ -> None) flags
7421 with Not_found -> sprintf "guestfs_%s" name in
7423 generate_c_call_args ~handle:"g" style;
7428 | Device name | String name
7429 | OptString name | FileIn name | FileOut name | Bool name
7430 | Int name | Int64 name -> ()
7431 | Pathname name | Dev_or_Path name ->
7432 pr " free (%s);\n" name
7433 | StringList name | DeviceList name ->
7434 pr " free_strings (%s);\n" name
7437 (* Check return value for errors and display command results. *)
7438 (match fst style with
7439 | RErr -> pr " return r;\n"
7441 pr " if (r == -1) return -1;\n";
7442 pr " printf (\"%%d\\n\", r);\n";
7445 pr " if (r == -1) return -1;\n";
7446 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7449 pr " if (r == -1) return -1;\n";
7450 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7453 pr " if (r == NULL) return -1;\n";
7454 pr " printf (\"%%s\\n\", r);\n";
7456 | RConstOptString _ ->
7457 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7460 pr " if (r == NULL) return -1;\n";
7461 pr " printf (\"%%s\\n\", r);\n";
7465 pr " if (r == NULL) return -1;\n";
7466 pr " print_strings (r);\n";
7467 pr " free_strings (r);\n";
7469 | RStruct (_, typ) ->
7470 pr " if (r == NULL) return -1;\n";
7471 pr " print_%s (r);\n" typ;
7472 pr " guestfs_free_%s (r);\n" typ;
7474 | RStructList (_, typ) ->
7475 pr " if (r == NULL) return -1;\n";
7476 pr " print_%s_list (r);\n" typ;
7477 pr " guestfs_free_%s_list (r);\n" typ;
7480 pr " if (r == NULL) return -1;\n";
7481 pr " print_table (r);\n";
7482 pr " free_strings (r);\n";
7485 pr " if (r == NULL) return -1;\n";
7486 pr " if (full_write (1, r, size) != size) {\n";
7487 pr " perror (\"write\");\n";
7498 (* run_action function *)
7499 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7502 fun (name, _, _, flags, _, _, _) ->
7503 let name2 = replace_char name '_' '-' in
7505 try find_map (function FishAlias n -> Some n | _ -> None) flags
7506 with Not_found -> name in
7508 pr "STRCASEEQ (cmd, \"%s\")" name;
7509 if name <> name2 then
7510 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7511 if name <> alias then
7512 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7514 pr " return run_%s (cmd, argc, argv);\n" name;
7518 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7519 pr " if (command_num == 1)\n";
7520 pr " extended_help_message ();\n";
7527 (* Readline completion for guestfish. *)
7528 and generate_fish_completion () =
7529 generate_header CStyle GPLv2plus;
7533 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7543 #ifdef HAVE_LIBREADLINE
7544 #include <readline/readline.h>
7549 #ifdef HAVE_LIBREADLINE
7551 static const char *const commands[] = {
7552 BUILTIN_COMMANDS_FOR_COMPLETION,
7555 (* Get the commands, including the aliases. They don't need to be
7556 * sorted - the generator() function just does a dumb linear search.
7560 fun (name, _, _, flags, _, _, _) ->
7561 let name2 = replace_char name '_' '-' in
7563 try find_map (function FishAlias n -> Some n | _ -> None) flags
7564 with Not_found -> name in
7566 if name <> alias then [name2; alias] else [name2]
7568 let commands = List.flatten commands in
7570 List.iter (pr " \"%s\",\n") commands;
7576 generator (const char *text, int state)
7578 static int index, len;
7583 len = strlen (text);
7586 rl_attempted_completion_over = 1;
7588 while ((name = commands[index]) != NULL) {
7590 if (STRCASEEQLEN (name, text, len))
7591 return strdup (name);
7597 #endif /* HAVE_LIBREADLINE */
7599 #ifdef HAVE_RL_COMPLETION_MATCHES
7600 #define RL_COMPLETION_MATCHES rl_completion_matches
7602 #ifdef HAVE_COMPLETION_MATCHES
7603 #define RL_COMPLETION_MATCHES completion_matches
7605 #endif /* else just fail if we don't have either symbol */
7608 do_completion (const char *text, int start, int end)
7610 char **matches = NULL;
7612 #ifdef HAVE_LIBREADLINE
7613 rl_completion_append_character = ' ';
7616 matches = RL_COMPLETION_MATCHES (text, generator);
7617 else if (complete_dest_paths)
7618 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7625 (* Generate the POD documentation for guestfish. *)
7626 and generate_fish_actions_pod () =
7627 let all_functions_sorted =
7629 fun (_, _, _, flags, _, _, _) ->
7630 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7631 ) all_functions_sorted in
7633 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7636 fun (name, style, _, flags, _, _, longdesc) ->
7638 Str.global_substitute rex (
7641 try Str.matched_group 1 s
7643 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7644 "C<" ^ replace_char sub '_' '-' ^ ">"
7646 let name = replace_char name '_' '-' in
7648 try find_map (function FishAlias n -> Some n | _ -> None) flags
7649 with Not_found -> name in
7651 pr "=head2 %s" name;
7652 if name <> alias then
7659 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7660 | OptString n -> pr " %s" n
7661 | StringList n | DeviceList n -> pr " '%s ...'" n
7662 | Bool _ -> pr " true|false"
7663 | Int n -> pr " %s" n
7664 | Int64 n -> pr " %s" n
7665 | FileIn n | FileOut n -> pr " (%s|-)" n
7669 pr "%s\n\n" longdesc;
7671 if List.exists (function FileIn _ | FileOut _ -> true
7672 | _ -> false) (snd style) then
7673 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7675 if List.mem ProtocolLimitWarning flags then
7676 pr "%s\n\n" protocol_limit_warning;
7678 if List.mem DangerWillRobinson flags then
7679 pr "%s\n\n" danger_will_robinson;
7681 match deprecation_notice flags with
7683 | Some txt -> pr "%s\n\n" txt
7684 ) all_functions_sorted
7686 (* Generate a C function prototype. *)
7687 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7688 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7690 ?handle name style =
7691 if extern then pr "extern ";
7692 if static then pr "static ";
7693 (match fst style with
7695 | RInt _ -> pr "int "
7696 | RInt64 _ -> pr "int64_t "
7697 | RBool _ -> pr "int "
7698 | RConstString _ | RConstOptString _ -> pr "const char *"
7699 | RString _ | RBufferOut _ -> pr "char *"
7700 | RStringList _ | RHashtable _ -> pr "char **"
7701 | RStruct (_, typ) ->
7702 if not in_daemon then pr "struct guestfs_%s *" typ
7703 else pr "guestfs_int_%s *" typ
7704 | RStructList (_, typ) ->
7705 if not in_daemon then pr "struct guestfs_%s_list *" typ
7706 else pr "guestfs_int_%s_list *" typ
7708 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7709 pr "%s%s (" prefix name;
7710 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7713 let comma = ref false in
7716 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7720 if single_line then pr ", " else pr ",\n\t\t"
7727 | Device n | Dev_or_Path n
7731 pr "const char *%s" n
7732 | StringList n | DeviceList n ->
7734 pr "char *const *%s" n
7735 | Bool n -> next (); pr "int %s" n
7736 | Int n -> next (); pr "int %s" n
7737 | Int64 n -> next (); pr "int64_t %s" n
7740 if not in_daemon then (next (); pr "const char *%s" n)
7742 if is_RBufferOut then (next (); pr "size_t *size_r");
7745 if semicolon then pr ";";
7746 if newline then pr "\n"
7748 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7749 and generate_c_call_args ?handle ?(decl = false) style =
7751 let comma = ref false in
7753 if !comma then pr ", ";
7758 | Some handle -> pr "%s" handle; comma := true
7763 pr "%s" (name_of_argt arg)
7765 (* For RBufferOut calls, add implicit &size parameter. *)
7767 match fst style with
7775 (* Generate the OCaml bindings interface. *)
7776 and generate_ocaml_mli () =
7777 generate_header OCamlStyle LGPLv2plus;
7780 (** For API documentation you should refer to the C API
7781 in the guestfs(3) manual page. The OCaml API uses almost
7782 exactly the same calls. *)
7785 (** A [guestfs_h] handle. *)
7787 exception Error of string
7788 (** This exception is raised when there is an error. *)
7790 exception Handle_closed of string
7791 (** This exception is raised if you use a {!Guestfs.t} handle
7792 after calling {!close} on it. The string is the name of
7795 val create : unit -> t
7796 (** Create a {!Guestfs.t} handle. *)
7798 val close : t -> unit
7799 (** Close the {!Guestfs.t} handle and free up all resources used
7802 Handles are closed by the garbage collector when they become
7803 unreferenced, but callers can call this in order to provide
7804 predictable cleanup. *)
7807 generate_ocaml_structure_decls ();
7811 fun (name, style, _, _, _, shortdesc, _) ->
7812 generate_ocaml_prototype name style;
7813 pr "(** %s *)\n" shortdesc;
7815 ) all_functions_sorted
7817 (* Generate the OCaml bindings implementation. *)
7818 and generate_ocaml_ml () =
7819 generate_header OCamlStyle LGPLv2plus;
7824 exception Error of string
7825 exception Handle_closed of string
7827 external create : unit -> t = \"ocaml_guestfs_create\"
7828 external close : t -> unit = \"ocaml_guestfs_close\"
7830 (* Give the exceptions names, so they can be raised from the C code. *)
7832 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7833 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7837 generate_ocaml_structure_decls ();
7841 fun (name, style, _, _, _, shortdesc, _) ->
7842 generate_ocaml_prototype ~is_external:true name style;
7843 ) all_functions_sorted
7845 (* Generate the OCaml bindings C implementation. *)
7846 and generate_ocaml_c () =
7847 generate_header CStyle LGPLv2plus;
7854 #include <caml/config.h>
7855 #include <caml/alloc.h>
7856 #include <caml/callback.h>
7857 #include <caml/fail.h>
7858 #include <caml/memory.h>
7859 #include <caml/mlvalues.h>
7860 #include <caml/signals.h>
7862 #include <guestfs.h>
7864 #include \"guestfs_c.h\"
7866 /* Copy a hashtable of string pairs into an assoc-list. We return
7867 * the list in reverse order, but hashtables aren't supposed to be
7870 static CAMLprim value
7871 copy_table (char * const * argv)
7874 CAMLlocal5 (rv, pairv, kv, vv, cons);
7878 for (i = 0; argv[i] != NULL; i += 2) {
7879 kv = caml_copy_string (argv[i]);
7880 vv = caml_copy_string (argv[i+1]);
7881 pairv = caml_alloc (2, 0);
7882 Store_field (pairv, 0, kv);
7883 Store_field (pairv, 1, vv);
7884 cons = caml_alloc (2, 0);
7885 Store_field (cons, 1, rv);
7887 Store_field (cons, 0, pairv);
7895 (* Struct copy functions. *)
7897 let emit_ocaml_copy_list_function typ =
7898 pr "static CAMLprim value\n";
7899 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7901 pr " CAMLparam0 ();\n";
7902 pr " CAMLlocal2 (rv, v);\n";
7903 pr " unsigned int i;\n";
7905 pr " if (%ss->len == 0)\n" typ;
7906 pr " CAMLreturn (Atom (0));\n";
7908 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7909 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7910 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7911 pr " caml_modify (&Field (rv, i), v);\n";
7913 pr " CAMLreturn (rv);\n";
7921 let has_optpercent_col =
7922 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7924 pr "static CAMLprim value\n";
7925 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7927 pr " CAMLparam0 ();\n";
7928 if has_optpercent_col then
7929 pr " CAMLlocal3 (rv, v, v2);\n"
7931 pr " CAMLlocal2 (rv, v);\n";
7933 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7938 pr " v = caml_copy_string (%s->%s);\n" typ name
7940 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7941 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7944 pr " v = caml_alloc_string (32);\n";
7945 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7946 | name, (FBytes|FInt64|FUInt64) ->
7947 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7948 | name, (FInt32|FUInt32) ->
7949 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7950 | name, FOptPercent ->
7951 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7952 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7953 pr " v = caml_alloc (1, 0);\n";
7954 pr " Store_field (v, 0, v2);\n";
7955 pr " } else /* None */\n";
7956 pr " v = Val_int (0);\n";
7958 pr " v = Val_int (%s->%s);\n" typ name
7960 pr " Store_field (rv, %d, v);\n" i
7962 pr " CAMLreturn (rv);\n";
7967 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7970 | typ, (RStructListOnly | RStructAndList) ->
7971 (* generate the function for typ *)
7972 emit_ocaml_copy_list_function typ
7973 | typ, _ -> () (* empty *)
7974 ) (rstructs_used_by all_functions);
7978 fun (name, style, _, _, _, _, _) ->
7979 pr "/* Automatically generated wrapper for function\n";
7981 generate_ocaml_prototype name style;
7986 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7988 let needs_extra_vs =
7989 match fst style with RConstOptString _ -> true | _ -> false in
7991 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7992 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7993 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7996 pr "CAMLprim value\n";
7997 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7998 List.iter (pr ", value %s") (List.tl params);
8003 | [p1; p2; p3; p4; p5] ->
8004 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8005 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8006 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8007 pr " CAMLxparam%d (%s);\n"
8008 (List.length rest) (String.concat ", " rest)
8010 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8012 if not needs_extra_vs then
8013 pr " CAMLlocal1 (rv);\n"
8015 pr " CAMLlocal3 (rv, v, v2);\n";
8018 pr " guestfs_h *g = Guestfs_val (gv);\n";
8019 pr " if (g == NULL)\n";
8020 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8026 | Device n | Dev_or_Path n
8030 pr " const char *%s = String_val (%sv);\n" n n
8032 pr " const char *%s =\n" n;
8033 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8035 | StringList n | DeviceList n ->
8036 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8038 pr " int %s = Bool_val (%sv);\n" n n
8040 pr " int %s = Int_val (%sv);\n" n n
8042 pr " int64_t %s = Int64_val (%sv);\n" n n
8045 match fst style with
8046 | RErr -> pr " int r;\n"; "-1"
8047 | RInt _ -> pr " int r;\n"; "-1"
8048 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8049 | RBool _ -> pr " int r;\n"; "-1"
8050 | RConstString _ | RConstOptString _ ->
8051 pr " const char *r;\n"; "NULL"
8052 | RString _ -> pr " char *r;\n"; "NULL"
8057 | RStruct (_, typ) ->
8058 pr " struct guestfs_%s *r;\n" typ; "NULL"
8059 | RStructList (_, typ) ->
8060 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8067 pr " size_t size;\n";
8071 pr " caml_enter_blocking_section ();\n";
8072 pr " r = guestfs_%s " name;
8073 generate_c_call_args ~handle:"g" style;
8075 pr " caml_leave_blocking_section ();\n";
8079 | StringList n | DeviceList n ->
8080 pr " ocaml_guestfs_free_strings (%s);\n" n;
8081 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8082 | Bool _ | Int _ | Int64 _
8083 | FileIn _ | FileOut _ -> ()
8086 pr " if (r == %s)\n" error_code;
8087 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8090 (match fst style with
8091 | RErr -> pr " rv = Val_unit;\n"
8092 | RInt _ -> pr " rv = Val_int (r);\n"
8094 pr " rv = caml_copy_int64 (r);\n"
8095 | RBool _ -> pr " rv = Val_bool (r);\n"
8097 pr " rv = caml_copy_string (r);\n"
8098 | RConstOptString _ ->
8099 pr " if (r) { /* Some string */\n";
8100 pr " v = caml_alloc (1, 0);\n";
8101 pr " v2 = caml_copy_string (r);\n";
8102 pr " Store_field (v, 0, v2);\n";
8103 pr " } else /* None */\n";
8104 pr " v = Val_int (0);\n";
8106 pr " rv = caml_copy_string (r);\n";
8109 pr " rv = caml_copy_string_array ((const char **) r);\n";
8110 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8112 | RStruct (_, typ) ->
8113 pr " rv = copy_%s (r);\n" typ;
8114 pr " guestfs_free_%s (r);\n" typ;
8115 | RStructList (_, typ) ->
8116 pr " rv = copy_%s_list (r);\n" typ;
8117 pr " guestfs_free_%s_list (r);\n" typ;
8119 pr " rv = copy_table (r);\n";
8120 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8123 pr " rv = caml_alloc_string (size);\n";
8124 pr " memcpy (String_val (rv), r, size);\n";
8127 pr " CAMLreturn (rv);\n";
8131 if List.length params > 5 then (
8132 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8133 pr "CAMLprim value ";
8134 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8135 pr "CAMLprim value\n";
8136 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8138 pr " return ocaml_guestfs_%s (argv[0]" name;
8139 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8144 ) all_functions_sorted
8146 and generate_ocaml_structure_decls () =
8149 pr "type %s = {\n" typ;
8152 | name, FString -> pr " %s : string;\n" name
8153 | name, FBuffer -> pr " %s : string;\n" name
8154 | name, FUUID -> pr " %s : string;\n" name
8155 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8156 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8157 | name, FChar -> pr " %s : char;\n" name
8158 | name, FOptPercent -> pr " %s : float option;\n" name
8164 and generate_ocaml_prototype ?(is_external = false) name style =
8165 if is_external then pr "external " else pr "val ";
8166 pr "%s : t -> " name;
8169 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8170 | OptString _ -> pr "string option -> "
8171 | StringList _ | DeviceList _ -> pr "string array -> "
8172 | Bool _ -> pr "bool -> "
8173 | Int _ -> pr "int -> "
8174 | Int64 _ -> pr "int64 -> "
8176 (match fst style with
8177 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8178 | RInt _ -> pr "int"
8179 | RInt64 _ -> pr "int64"
8180 | RBool _ -> pr "bool"
8181 | RConstString _ -> pr "string"
8182 | RConstOptString _ -> pr "string option"
8183 | RString _ | RBufferOut _ -> pr "string"
8184 | RStringList _ -> pr "string array"
8185 | RStruct (_, typ) -> pr "%s" typ
8186 | RStructList (_, typ) -> pr "%s array" typ
8187 | RHashtable _ -> pr "(string * string) list"
8189 if is_external then (
8191 if List.length (snd style) + 1 > 5 then
8192 pr "\"ocaml_guestfs_%s_byte\" " name;
8193 pr "\"ocaml_guestfs_%s\"" name
8197 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8198 and generate_perl_xs () =
8199 generate_header CStyle LGPLv2plus;
8202 #include \"EXTERN.h\"
8206 #include <guestfs.h>
8209 #define PRId64 \"lld\"
8213 my_newSVll(long long val) {
8214 #ifdef USE_64_BIT_ALL
8215 return newSViv(val);
8219 len = snprintf(buf, 100, \"%%\" PRId64, val);
8220 return newSVpv(buf, len);
8225 #define PRIu64 \"llu\"
8229 my_newSVull(unsigned long long val) {
8230 #ifdef USE_64_BIT_ALL
8231 return newSVuv(val);
8235 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8236 return newSVpv(buf, len);
8240 /* http://www.perlmonks.org/?node_id=680842 */
8242 XS_unpack_charPtrPtr (SV *arg) {
8247 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8248 croak (\"array reference expected\");
8250 av = (AV *)SvRV (arg);
8251 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8253 croak (\"malloc failed\");
8255 for (i = 0; i <= av_len (av); i++) {
8256 SV **elem = av_fetch (av, i, 0);
8258 if (!elem || !*elem)
8259 croak (\"missing element in list\");
8261 ret[i] = SvPV_nolen (*elem);
8269 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8276 RETVAL = guestfs_create ();
8278 croak (\"could not create guestfs handle\");
8279 guestfs_set_error_handler (RETVAL, NULL, NULL);
8292 fun (name, style, _, _, _, _, _) ->
8293 (match fst style with
8294 | RErr -> pr "void\n"
8295 | RInt _ -> pr "SV *\n"
8296 | RInt64 _ -> pr "SV *\n"
8297 | RBool _ -> pr "SV *\n"
8298 | RConstString _ -> pr "SV *\n"
8299 | RConstOptString _ -> pr "SV *\n"
8300 | RString _ -> pr "SV *\n"
8301 | RBufferOut _ -> pr "SV *\n"
8303 | RStruct _ | RStructList _
8305 pr "void\n" (* all lists returned implictly on the stack *)
8307 (* Call and arguments. *)
8309 generate_c_call_args ~handle:"g" ~decl:true style;
8311 pr " guestfs_h *g;\n";
8315 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8318 (* http://www.perlmonks.org/?node_id=554277
8319 * Note that the implicit handle argument means we have
8320 * to add 1 to the ST(x) operator.
8322 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8323 | StringList n | DeviceList n -> pr " char **%s;\n" n
8324 | Bool n -> pr " int %s;\n" n
8325 | Int n -> pr " int %s;\n" n
8326 | Int64 n -> pr " int64_t %s;\n" n
8329 let do_cleanups () =
8332 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8333 | Bool _ | Int _ | Int64 _
8334 | FileIn _ | FileOut _ -> ()
8335 | StringList n | DeviceList n -> pr " free (%s);\n" n
8340 (match fst style with
8345 pr " r = guestfs_%s " name;
8346 generate_c_call_args ~handle:"g" style;
8349 pr " if (r == -1)\n";
8350 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8356 pr " %s = guestfs_%s " n name;
8357 generate_c_call_args ~handle:"g" style;
8360 pr " if (%s == -1)\n" n;
8361 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8362 pr " RETVAL = newSViv (%s);\n" n;
8367 pr " int64_t %s;\n" n;
8369 pr " %s = guestfs_%s " n name;
8370 generate_c_call_args ~handle:"g" style;
8373 pr " if (%s == -1)\n" n;
8374 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8375 pr " RETVAL = my_newSVll (%s);\n" n;
8380 pr " const char *%s;\n" n;
8382 pr " %s = guestfs_%s " n name;
8383 generate_c_call_args ~handle:"g" style;
8386 pr " if (%s == NULL)\n" n;
8387 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8388 pr " RETVAL = newSVpv (%s, 0);\n" n;
8391 | RConstOptString n ->
8393 pr " const char *%s;\n" n;
8395 pr " %s = guestfs_%s " n name;
8396 generate_c_call_args ~handle:"g" style;
8399 pr " if (%s == NULL)\n" n;
8400 pr " RETVAL = &PL_sv_undef;\n";
8402 pr " RETVAL = newSVpv (%s, 0);\n" n;
8407 pr " char *%s;\n" n;
8409 pr " %s = guestfs_%s " n name;
8410 generate_c_call_args ~handle:"g" style;
8413 pr " if (%s == NULL)\n" n;
8414 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8415 pr " RETVAL = newSVpv (%s, 0);\n" n;
8416 pr " free (%s);\n" n;
8419 | RStringList n | RHashtable n ->
8421 pr " char **%s;\n" n;
8424 pr " %s = guestfs_%s " n name;
8425 generate_c_call_args ~handle:"g" style;
8428 pr " if (%s == NULL)\n" n;
8429 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8430 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8431 pr " EXTEND (SP, n);\n";
8432 pr " for (i = 0; i < n; ++i) {\n";
8433 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8434 pr " free (%s[i]);\n" n;
8436 pr " free (%s);\n" n;
8437 | RStruct (n, typ) ->
8438 let cols = cols_of_struct typ in
8439 generate_perl_struct_code typ cols name style n do_cleanups
8440 | RStructList (n, typ) ->
8441 let cols = cols_of_struct typ in
8442 generate_perl_struct_list_code typ cols name style n do_cleanups
8445 pr " char *%s;\n" n;
8446 pr " size_t size;\n";
8448 pr " %s = guestfs_%s " n name;
8449 generate_c_call_args ~handle:"g" style;
8452 pr " if (%s == NULL)\n" n;
8453 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8454 pr " RETVAL = newSVpvn (%s, size);\n" n;
8455 pr " free (%s);\n" n;
8463 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8465 pr " struct guestfs_%s_list *%s;\n" typ n;
8469 pr " %s = guestfs_%s " n name;
8470 generate_c_call_args ~handle:"g" style;
8473 pr " if (%s == NULL)\n" n;
8474 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8475 pr " EXTEND (SP, %s->len);\n" n;
8476 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8477 pr " hv = newHV ();\n";
8481 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8482 name (String.length name) n name
8484 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8485 name (String.length name) n name
8487 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8488 name (String.length name) n name n name
8489 | name, (FBytes|FUInt64) ->
8490 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8491 name (String.length name) n name
8493 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8494 name (String.length name) n name
8495 | name, (FInt32|FUInt32) ->
8496 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8497 name (String.length name) n name
8499 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8500 name (String.length name) n name
8501 | name, FOptPercent ->
8502 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8503 name (String.length name) n name
8505 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8507 pr " guestfs_free_%s_list (%s);\n" typ n
8509 and generate_perl_struct_code typ cols name style n do_cleanups =
8511 pr " struct guestfs_%s *%s;\n" typ n;
8513 pr " %s = guestfs_%s " n name;
8514 generate_c_call_args ~handle:"g" style;
8517 pr " if (%s == NULL)\n" n;
8518 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8519 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8521 fun ((name, _) as col) ->
8522 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8526 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8529 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8532 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8534 | name, (FBytes|FUInt64) ->
8535 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8538 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8540 | name, (FInt32|FUInt32) ->
8541 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8544 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8546 | name, FOptPercent ->
8547 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8550 pr " free (%s);\n" n
8552 (* Generate Sys/Guestfs.pm. *)
8553 and generate_perl_pm () =
8554 generate_header HashStyle LGPLv2plus;
8561 Sys::Guestfs - Perl bindings for libguestfs
8567 my $h = Sys::Guestfs->new ();
8568 $h->add_drive ('guest.img');
8570 $h->mount ('/dev/sda1', '/');
8571 $h->touch ('/hello');
8576 The C<Sys::Guestfs> module provides a Perl XS binding to the
8577 libguestfs API for examining and modifying virtual machine
8580 Amongst the things this is good for: making batch configuration
8581 changes to guests, getting disk used/free statistics (see also:
8582 virt-df), migrating between virtualization systems (see also:
8583 virt-p2v), performing partial backups, performing partial guest
8584 clones, cloning guests and changing registry/UUID/hostname info, and
8587 Libguestfs uses Linux kernel and qemu code, and can access any type of
8588 guest filesystem that Linux and qemu can, including but not limited
8589 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8590 schemes, qcow, qcow2, vmdk.
8592 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8593 LVs, what filesystem is in each LV, etc.). It can also run commands
8594 in the context of the guest. Also you can access filesystems over
8597 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8598 functions for using libguestfs from Perl, including integration
8603 All errors turn into calls to C<croak> (see L<Carp(3)>).
8611 package Sys::Guestfs;
8617 XSLoader::load ('Sys::Guestfs');
8619 =item $h = Sys::Guestfs->new ();
8621 Create a new guestfs handle.
8627 my $class = ref ($proto) || $proto;
8629 my $self = Sys::Guestfs::_create ();
8630 bless $self, $class;
8636 (* Actions. We only need to print documentation for these as
8637 * they are pulled in from the XS code automatically.
8640 fun (name, style, _, flags, _, _, longdesc) ->
8641 if not (List.mem NotInDocs flags) then (
8642 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8644 generate_perl_prototype name style;
8646 pr "%s\n\n" longdesc;
8647 if List.mem ProtocolLimitWarning flags then
8648 pr "%s\n\n" protocol_limit_warning;
8649 if List.mem DangerWillRobinson flags then
8650 pr "%s\n\n" danger_will_robinson;
8651 match deprecation_notice flags with
8653 | Some txt -> pr "%s\n\n" txt
8655 ) all_functions_sorted;
8667 Copyright (C) %s Red Hat Inc.
8671 Please see the file COPYING.LIB for the full license.
8677 L<http://libguestfs.org>,
8678 L<Sys::Guestfs::Lib(3)>.
8683 and generate_perl_prototype name style =
8684 (match fst style with
8692 | RBufferOut n -> pr "$%s = " n
8694 | RHashtable n -> pr "%%%s = " n
8696 | RStructList (n,_) -> pr "@%s = " n
8699 let comma = ref false in
8702 if !comma then pr ", ";
8705 | Pathname n | Device n | Dev_or_Path n | String n
8706 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8708 | StringList n | DeviceList n ->
8713 (* Generate Python C module. *)
8714 and generate_python_c () =
8715 generate_header CStyle LGPLv2plus;
8724 #include \"guestfs.h\"
8732 get_handle (PyObject *obj)
8735 assert (obj != Py_None);
8736 return ((Pyguestfs_Object *) obj)->g;
8740 put_handle (guestfs_h *g)
8744 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8747 /* This list should be freed (but not the strings) after use. */
8749 get_string_list (PyObject *obj)
8756 if (!PyList_Check (obj)) {
8757 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8761 len = PyList_Size (obj);
8762 r = malloc (sizeof (char *) * (len+1));
8764 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8768 for (i = 0; i < len; ++i)
8769 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8776 put_string_list (char * const * const argv)
8781 for (argc = 0; argv[argc] != NULL; ++argc)
8784 list = PyList_New (argc);
8785 for (i = 0; i < argc; ++i)
8786 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8792 put_table (char * const * const argv)
8794 PyObject *list, *item;
8797 for (argc = 0; argv[argc] != NULL; ++argc)
8800 list = PyList_New (argc >> 1);
8801 for (i = 0; i < argc; i += 2) {
8802 item = PyTuple_New (2);
8803 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8804 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8805 PyList_SetItem (list, i >> 1, item);
8812 free_strings (char **argv)
8816 for (argc = 0; argv[argc] != NULL; ++argc)
8822 py_guestfs_create (PyObject *self, PyObject *args)
8826 g = guestfs_create ();
8828 PyErr_SetString (PyExc_RuntimeError,
8829 \"guestfs.create: failed to allocate handle\");
8832 guestfs_set_error_handler (g, NULL, NULL);
8833 return put_handle (g);
8837 py_guestfs_close (PyObject *self, PyObject *args)
8842 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8844 g = get_handle (py_g);
8848 Py_INCREF (Py_None);
8854 let emit_put_list_function typ =
8855 pr "static PyObject *\n";
8856 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8858 pr " PyObject *list;\n";
8861 pr " list = PyList_New (%ss->len);\n" typ;
8862 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8863 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8864 pr " return list;\n";
8869 (* Structures, turned into Python dictionaries. *)
8872 pr "static PyObject *\n";
8873 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8875 pr " PyObject *dict;\n";
8877 pr " dict = PyDict_New ();\n";
8881 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8882 pr " PyString_FromString (%s->%s));\n"
8885 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8886 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8889 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8890 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8892 | name, (FBytes|FUInt64) ->
8893 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8894 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8897 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8898 pr " PyLong_FromLongLong (%s->%s));\n"
8901 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8902 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8905 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8906 pr " PyLong_FromLong (%s->%s));\n"
8908 | name, FOptPercent ->
8909 pr " if (%s->%s >= 0)\n" typ name;
8910 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8911 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8914 pr " Py_INCREF (Py_None);\n";
8915 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8918 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8919 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8921 pr " return dict;\n";
8927 (* Emit a put_TYPE_list function definition only if that function is used. *)
8930 | typ, (RStructListOnly | RStructAndList) ->
8931 (* generate the function for typ *)
8932 emit_put_list_function typ
8933 | typ, _ -> () (* empty *)
8934 ) (rstructs_used_by all_functions);
8936 (* Python wrapper functions. *)
8938 fun (name, style, _, _, _, _, _) ->
8939 pr "static PyObject *\n";
8940 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8943 pr " PyObject *py_g;\n";
8944 pr " guestfs_h *g;\n";
8945 pr " PyObject *py_r;\n";
8948 match fst style with
8949 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8950 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8951 | RConstString _ | RConstOptString _ ->
8952 pr " const char *r;\n"; "NULL"
8953 | RString _ -> pr " char *r;\n"; "NULL"
8954 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8955 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8956 | RStructList (_, typ) ->
8957 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8960 pr " size_t size;\n";
8965 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8966 pr " const char *%s;\n" n
8967 | OptString n -> pr " const char *%s;\n" n
8968 | StringList n | DeviceList n ->
8969 pr " PyObject *py_%s;\n" n;
8970 pr " char **%s;\n" n
8971 | Bool n -> pr " int %s;\n" n
8972 | Int n -> pr " int %s;\n" n
8973 | Int64 n -> pr " long long %s;\n" n
8978 (* Convert the parameters. *)
8979 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8982 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8983 | OptString _ -> pr "z"
8984 | StringList _ | DeviceList _ -> pr "O"
8985 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8987 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8988 * emulate C's int/long/long long in Python?
8991 pr ":guestfs_%s\",\n" name;
8995 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8996 | OptString n -> pr ", &%s" n
8997 | StringList n | DeviceList n -> pr ", &py_%s" n
8998 | Bool n -> pr ", &%s" n
8999 | Int n -> pr ", &%s" n
9000 | Int64 n -> pr ", &%s" n
9004 pr " return NULL;\n";
9006 pr " g = get_handle (py_g);\n";
9009 | Pathname _ | Device _ | Dev_or_Path _ | String _
9010 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9011 | StringList n | DeviceList n ->
9012 pr " %s = get_string_list (py_%s);\n" n n;
9013 pr " if (!%s) return NULL;\n" n
9018 pr " r = guestfs_%s " name;
9019 generate_c_call_args ~handle:"g" style;
9024 | Pathname _ | Device _ | Dev_or_Path _ | String _
9025 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9026 | StringList n | DeviceList n ->
9027 pr " free (%s);\n" n
9030 pr " if (r == %s) {\n" error_code;
9031 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9032 pr " return NULL;\n";
9036 (match fst style with
9038 pr " Py_INCREF (Py_None);\n";
9039 pr " py_r = Py_None;\n"
9041 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9042 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9043 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9044 | RConstOptString _ ->
9046 pr " py_r = PyString_FromString (r);\n";
9048 pr " Py_INCREF (Py_None);\n";
9049 pr " py_r = Py_None;\n";
9052 pr " py_r = PyString_FromString (r);\n";
9055 pr " py_r = put_string_list (r);\n";
9056 pr " free_strings (r);\n"
9057 | RStruct (_, typ) ->
9058 pr " py_r = put_%s (r);\n" typ;
9059 pr " guestfs_free_%s (r);\n" typ
9060 | RStructList (_, typ) ->
9061 pr " py_r = put_%s_list (r);\n" typ;
9062 pr " guestfs_free_%s_list (r);\n" typ
9064 pr " py_r = put_table (r);\n";
9065 pr " free_strings (r);\n"
9067 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9071 pr " return py_r;\n";
9076 (* Table of functions. *)
9077 pr "static PyMethodDef methods[] = {\n";
9078 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9079 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9081 fun (name, _, _, _, _, _, _) ->
9082 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9085 pr " { NULL, NULL, 0, NULL }\n";
9089 (* Init function. *)
9092 initlibguestfsmod (void)
9094 static int initialized = 0;
9096 if (initialized) return;
9097 Py_InitModule ((char *) \"libguestfsmod\", methods);
9102 (* Generate Python module. *)
9103 and generate_python_py () =
9104 generate_header HashStyle LGPLv2plus;
9107 u\"\"\"Python bindings for libguestfs
9110 g = guestfs.GuestFS ()
9111 g.add_drive (\"guest.img\")
9113 parts = g.list_partitions ()
9115 The guestfs module provides a Python binding to the libguestfs API
9116 for examining and modifying virtual machine disk images.
9118 Amongst the things this is good for: making batch configuration
9119 changes to guests, getting disk used/free statistics (see also:
9120 virt-df), migrating between virtualization systems (see also:
9121 virt-p2v), performing partial backups, performing partial guest
9122 clones, cloning guests and changing registry/UUID/hostname info, and
9125 Libguestfs uses Linux kernel and qemu code, and can access any type of
9126 guest filesystem that Linux and qemu can, including but not limited
9127 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9128 schemes, qcow, qcow2, vmdk.
9130 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9131 LVs, what filesystem is in each LV, etc.). It can also run commands
9132 in the context of the guest. Also you can access filesystems over
9135 Errors which happen while using the API are turned into Python
9136 RuntimeError exceptions.
9138 To create a guestfs handle you usually have to perform the following
9141 # Create the handle, call add_drive at least once, and possibly
9142 # several times if the guest has multiple block devices:
9143 g = guestfs.GuestFS ()
9144 g.add_drive (\"guest.img\")
9146 # Launch the qemu subprocess and wait for it to become ready:
9149 # Now you can issue commands, for example:
9154 import libguestfsmod
9157 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9159 def __init__ (self):
9160 \"\"\"Create a new libguestfs handle.\"\"\"
9161 self._o = libguestfsmod.create ()
9164 libguestfsmod.close (self._o)
9169 fun (name, style, _, flags, _, _, longdesc) ->
9171 generate_py_call_args ~handle:"self" (snd style);
9174 if not (List.mem NotInDocs flags) then (
9175 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9177 match fst style with
9178 | RErr | RInt _ | RInt64 _ | RBool _
9179 | RConstOptString _ | RConstString _
9180 | RString _ | RBufferOut _ -> doc
9182 doc ^ "\n\nThis function returns a list of strings."
9183 | RStruct (_, typ) ->
9184 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9185 | RStructList (_, typ) ->
9186 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9188 doc ^ "\n\nThis function returns a dictionary." in
9190 if List.mem ProtocolLimitWarning flags then
9191 doc ^ "\n\n" ^ protocol_limit_warning
9194 if List.mem DangerWillRobinson flags then
9195 doc ^ "\n\n" ^ danger_will_robinson
9198 match deprecation_notice flags with
9200 | Some txt -> doc ^ "\n\n" ^ txt in
9201 let doc = pod2text ~width:60 name doc in
9202 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9203 let doc = String.concat "\n " doc in
9204 pr " u\"\"\"%s\"\"\"\n" doc;
9206 pr " return libguestfsmod.%s " name;
9207 generate_py_call_args ~handle:"self._o" (snd style);
9212 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9213 and generate_py_call_args ~handle args =
9215 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9218 (* Useful if you need the longdesc POD text as plain text. Returns a
9221 * Because this is very slow (the slowest part of autogeneration),
9222 * we memoize the results.
9224 and pod2text ~width name longdesc =
9225 let key = width, name, longdesc in
9226 try Hashtbl.find pod2text_memo key
9228 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9229 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9231 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9232 let chan = open_process_in cmd in
9233 let lines = ref [] in
9235 let line = input_line chan in
9236 if i = 1 then (* discard the first line of output *)
9239 let line = triml line in
9240 lines := line :: !lines;
9243 let lines = try loop 1 with End_of_file -> List.rev !lines in
9245 (match close_process_in chan with
9248 failwithf "pod2text: process exited with non-zero status (%d)" i
9249 | WSIGNALED i | WSTOPPED i ->
9250 failwithf "pod2text: process signalled or stopped by signal %d" i
9252 Hashtbl.add pod2text_memo key lines;
9253 pod2text_memo_updated ();
9256 (* Generate ruby bindings. *)
9257 and generate_ruby_c () =
9258 generate_header CStyle LGPLv2plus;
9266 #include \"guestfs.h\"
9268 #include \"extconf.h\"
9270 /* For Ruby < 1.9 */
9272 #define RARRAY_LEN(r) (RARRAY((r))->len)
9275 static VALUE m_guestfs; /* guestfs module */
9276 static VALUE c_guestfs; /* guestfs_h handle */
9277 static VALUE e_Error; /* used for all errors */
9279 static void ruby_guestfs_free (void *p)
9282 guestfs_close ((guestfs_h *) p);
9285 static VALUE ruby_guestfs_create (VALUE m)
9289 g = guestfs_create ();
9291 rb_raise (e_Error, \"failed to create guestfs handle\");
9293 /* Don't print error messages to stderr by default. */
9294 guestfs_set_error_handler (g, NULL, NULL);
9296 /* Wrap it, and make sure the close function is called when the
9299 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9302 static VALUE ruby_guestfs_close (VALUE gv)
9305 Data_Get_Struct (gv, guestfs_h, g);
9307 ruby_guestfs_free (g);
9308 DATA_PTR (gv) = NULL;
9316 fun (name, style, _, _, _, _, _) ->
9317 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9318 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9321 pr " guestfs_h *g;\n";
9322 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9324 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9330 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9331 pr " Check_Type (%sv, T_STRING);\n" n;
9332 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9334 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9335 pr " \"%s\", \"%s\");\n" n name
9337 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9338 | StringList n | DeviceList n ->
9339 pr " char **%s;\n" n;
9340 pr " Check_Type (%sv, T_ARRAY);\n" n;
9342 pr " int i, len;\n";
9343 pr " len = RARRAY_LEN (%sv);\n" n;
9344 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9346 pr " for (i = 0; i < len; ++i) {\n";
9347 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9348 pr " %s[i] = StringValueCStr (v);\n" n;
9350 pr " %s[len] = NULL;\n" n;
9353 pr " int %s = RTEST (%sv);\n" n n
9355 pr " int %s = NUM2INT (%sv);\n" n n
9357 pr " long long %s = NUM2LL (%sv);\n" n n
9362 match fst style with
9363 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9364 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9365 | RConstString _ | RConstOptString _ ->
9366 pr " const char *r;\n"; "NULL"
9367 | RString _ -> pr " char *r;\n"; "NULL"
9368 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9369 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9370 | RStructList (_, typ) ->
9371 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9374 pr " size_t size;\n";
9378 pr " r = guestfs_%s " name;
9379 generate_c_call_args ~handle:"g" style;
9384 | Pathname _ | Device _ | Dev_or_Path _ | String _
9385 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9386 | StringList n | DeviceList n ->
9387 pr " free (%s);\n" n
9390 pr " if (r == %s)\n" error_code;
9391 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9394 (match fst style with
9396 pr " return Qnil;\n"
9397 | RInt _ | RBool _ ->
9398 pr " return INT2NUM (r);\n"
9400 pr " return ULL2NUM (r);\n"
9402 pr " return rb_str_new2 (r);\n";
9403 | RConstOptString _ ->
9405 pr " return rb_str_new2 (r);\n";
9407 pr " return Qnil;\n";
9409 pr " VALUE rv = rb_str_new2 (r);\n";
9413 pr " int i, len = 0;\n";
9414 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9415 pr " VALUE rv = rb_ary_new2 (len);\n";
9416 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9417 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9418 pr " free (r[i]);\n";
9422 | RStruct (_, typ) ->
9423 let cols = cols_of_struct typ in
9424 generate_ruby_struct_code typ cols
9425 | RStructList (_, typ) ->
9426 let cols = cols_of_struct typ in
9427 generate_ruby_struct_list_code typ cols
9429 pr " VALUE rv = rb_hash_new ();\n";
9431 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9432 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9433 pr " free (r[i]);\n";
9434 pr " free (r[i+1]);\n";
9439 pr " VALUE rv = rb_str_new (r, size);\n";
9449 /* Initialize the module. */
9450 void Init__guestfs ()
9452 m_guestfs = rb_define_module (\"Guestfs\");
9453 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9454 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9456 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9457 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9460 (* Define the rest of the methods. *)
9462 fun (name, style, _, _, _, _, _) ->
9463 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9464 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9469 (* Ruby code to return a struct. *)
9470 and generate_ruby_struct_code typ cols =
9471 pr " VALUE rv = rb_hash_new ();\n";
9475 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9477 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9479 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9480 | name, (FBytes|FUInt64) ->
9481 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9483 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9485 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9487 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9488 | name, FOptPercent ->
9489 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9490 | name, FChar -> (* XXX wrong? *)
9491 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9493 pr " guestfs_free_%s (r);\n" typ;
9496 (* Ruby code to return a struct list. *)
9497 and generate_ruby_struct_list_code typ cols =
9498 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9500 pr " for (i = 0; i < r->len; ++i) {\n";
9501 pr " VALUE hv = rb_hash_new ();\n";
9505 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9507 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
9509 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9510 | name, (FBytes|FUInt64) ->
9511 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9513 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9515 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9517 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9518 | name, FOptPercent ->
9519 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9520 | name, FChar -> (* XXX wrong? *)
9521 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9523 pr " rb_ary_push (rv, hv);\n";
9525 pr " guestfs_free_%s_list (r);\n" typ;
9528 (* Generate Java bindings GuestFS.java file. *)
9529 and generate_java_java () =
9530 generate_header CStyle LGPLv2plus;
9533 package com.redhat.et.libguestfs;
9535 import java.util.HashMap;
9536 import com.redhat.et.libguestfs.LibGuestFSException;
9537 import com.redhat.et.libguestfs.PV;
9538 import com.redhat.et.libguestfs.VG;
9539 import com.redhat.et.libguestfs.LV;
9540 import com.redhat.et.libguestfs.Stat;
9541 import com.redhat.et.libguestfs.StatVFS;
9542 import com.redhat.et.libguestfs.IntBool;
9543 import com.redhat.et.libguestfs.Dirent;
9546 * The GuestFS object is a libguestfs handle.
9550 public class GuestFS {
9551 // Load the native code.
9553 System.loadLibrary (\"guestfs_jni\");
9557 * The native guestfs_h pointer.
9562 * Create a libguestfs handle.
9564 * @throws LibGuestFSException
9566 public GuestFS () throws LibGuestFSException
9570 private native long _create () throws LibGuestFSException;
9573 * Close a libguestfs handle.
9575 * You can also leave handles to be collected by the garbage
9576 * collector, but this method ensures that the resources used
9577 * by the handle are freed up immediately. If you call any
9578 * other methods after closing the handle, you will get an
9581 * @throws LibGuestFSException
9583 public void close () throws LibGuestFSException
9589 private native void _close (long g) throws LibGuestFSException;
9591 public void finalize () throws LibGuestFSException
9599 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9600 if not (List.mem NotInDocs flags); then (
9601 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9603 if List.mem ProtocolLimitWarning flags then
9604 doc ^ "\n\n" ^ protocol_limit_warning
9607 if List.mem DangerWillRobinson flags then
9608 doc ^ "\n\n" ^ danger_will_robinson
9611 match deprecation_notice flags with
9613 | Some txt -> doc ^ "\n\n" ^ txt in
9614 let doc = pod2text ~width:60 name doc in
9615 let doc = List.map ( (* RHBZ#501883 *)
9618 | nonempty -> nonempty
9620 let doc = String.concat "\n * " doc in
9623 pr " * %s\n" shortdesc;
9626 pr " * @throws LibGuestFSException\n";
9630 generate_java_prototype ~public:true ~semicolon:false name style;
9633 pr " if (g == 0)\n";
9634 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9637 if fst style <> RErr then pr "return ";
9639 generate_java_call_args ~handle:"g" (snd style);
9643 generate_java_prototype ~privat:true ~native:true name style;
9650 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9651 and generate_java_call_args ~handle args =
9653 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9656 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9657 ?(semicolon=true) name style =
9658 if privat then pr "private ";
9659 if public then pr "public ";
9660 if native then pr "native ";
9663 (match fst style with
9664 | RErr -> pr "void ";
9665 | RInt _ -> pr "int ";
9666 | RInt64 _ -> pr "long ";
9667 | RBool _ -> pr "boolean ";
9668 | RConstString _ | RConstOptString _ | RString _
9669 | RBufferOut _ -> pr "String ";
9670 | RStringList _ -> pr "String[] ";
9671 | RStruct (_, typ) ->
9672 let name = java_name_of_struct typ in
9674 | RStructList (_, typ) ->
9675 let name = java_name_of_struct typ in
9677 | RHashtable _ -> pr "HashMap<String,String> ";
9680 if native then pr "_%s " name else pr "%s " name;
9682 let needs_comma = ref false in
9691 if !needs_comma then pr ", ";
9692 needs_comma := true;
9696 | Device n | Dev_or_Path n
9702 | StringList n | DeviceList n ->
9713 pr " throws LibGuestFSException";
9714 if semicolon then pr ";"
9716 and generate_java_struct jtyp cols () =
9717 generate_header CStyle LGPLv2plus;
9720 package com.redhat.et.libguestfs;
9723 * Libguestfs %s structure.
9735 | name, FBuffer -> pr " public String %s;\n" name
9736 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9737 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9738 | name, FChar -> pr " public char %s;\n" name
9739 | name, FOptPercent ->
9740 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9741 pr " public float %s;\n" name
9746 and generate_java_c () =
9747 generate_header CStyle LGPLv2plus;
9754 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9755 #include \"guestfs.h\"
9757 /* Note that this function returns. The exception is not thrown
9758 * until after the wrapper function returns.
9761 throw_exception (JNIEnv *env, const char *msg)
9764 cl = (*env)->FindClass (env,
9765 \"com/redhat/et/libguestfs/LibGuestFSException\");
9766 (*env)->ThrowNew (env, cl, msg);
9769 JNIEXPORT jlong JNICALL
9770 Java_com_redhat_et_libguestfs_GuestFS__1create
9771 (JNIEnv *env, jobject obj)
9775 g = guestfs_create ();
9777 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9780 guestfs_set_error_handler (g, NULL, NULL);
9781 return (jlong) (long) g;
9784 JNIEXPORT void JNICALL
9785 Java_com_redhat_et_libguestfs_GuestFS__1close
9786 (JNIEnv *env, jobject obj, jlong jg)
9788 guestfs_h *g = (guestfs_h *) (long) jg;
9795 fun (name, style, _, _, _, _, _) ->
9797 (match fst style with
9798 | RErr -> pr "void ";
9799 | RInt _ -> pr "jint ";
9800 | RInt64 _ -> pr "jlong ";
9801 | RBool _ -> pr "jboolean ";
9802 | RConstString _ | RConstOptString _ | RString _
9803 | RBufferOut _ -> pr "jstring ";
9804 | RStruct _ | RHashtable _ ->
9806 | RStringList _ | RStructList _ ->
9810 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9811 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9813 pr " (JNIEnv *env, jobject obj, jlong jg";
9817 | Device n | Dev_or_Path n
9822 pr ", jstring j%s" n
9823 | StringList n | DeviceList n ->
9824 pr ", jobjectArray j%s" n
9826 pr ", jboolean j%s" n
9834 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9835 let error_code, no_ret =
9836 match fst style with
9837 | RErr -> pr " int r;\n"; "-1", ""
9839 | RInt _ -> pr " int r;\n"; "-1", "0"
9840 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9841 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9842 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9844 pr " jstring jr;\n";
9845 pr " char *r;\n"; "NULL", "NULL"
9847 pr " jobjectArray jr;\n";
9850 pr " jstring jstr;\n";
9851 pr " char **r;\n"; "NULL", "NULL"
9852 | RStruct (_, typ) ->
9853 pr " jobject jr;\n";
9855 pr " jfieldID fl;\n";
9856 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9857 | RStructList (_, typ) ->
9858 pr " jobjectArray jr;\n";
9860 pr " jfieldID fl;\n";
9861 pr " jobject jfl;\n";
9862 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9863 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9865 pr " jstring jr;\n";
9867 pr " size_t size;\n";
9872 | Device n | Dev_or_Path n
9877 pr " const char *%s;\n" n
9878 | StringList n | DeviceList n ->
9879 pr " int %s_len;\n" n;
9880 pr " const char **%s;\n" n
9885 pr " int64_t %s;\n" n
9889 (match fst style with
9890 | RStringList _ | RStructList _ -> true
9891 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9893 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9894 List.exists (function
9895 | StringList _ -> true
9896 | DeviceList _ -> true
9897 | _ -> false) (snd style) in
9903 (* Get the parameters. *)
9907 | Device n | Dev_or_Path n
9911 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9913 (* This is completely undocumented, but Java null becomes
9916 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9917 | StringList n | DeviceList n ->
9918 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9919 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9920 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9921 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9923 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9925 pr " %s[%s_len] = NULL;\n" n n;
9929 pr " %s = j%s;\n" n n
9932 (* Make the call. *)
9933 pr " r = guestfs_%s " name;
9934 generate_c_call_args ~handle:"g" style;
9937 (* Release the parameters. *)
9941 | Device n | Dev_or_Path n
9945 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9948 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9949 | StringList n | DeviceList n ->
9950 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9951 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9953 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9955 pr " free (%s);\n" n
9961 (* Check for errors. *)
9962 pr " if (r == %s) {\n" error_code;
9963 pr " throw_exception (env, guestfs_last_error (g));\n";
9964 pr " return %s;\n" no_ret;
9968 (match fst style with
9970 | RInt _ -> pr " return (jint) r;\n"
9971 | RBool _ -> pr " return (jboolean) r;\n"
9972 | RInt64 _ -> pr " return (jlong) r;\n"
9973 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9974 | RConstOptString _ ->
9975 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9977 pr " jr = (*env)->NewStringUTF (env, r);\n";
9981 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9982 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9983 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9984 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9985 pr " for (i = 0; i < r_len; ++i) {\n";
9986 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9987 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9988 pr " free (r[i]);\n";
9992 | RStruct (_, typ) ->
9993 let jtyp = java_name_of_struct typ in
9994 let cols = cols_of_struct typ in
9995 generate_java_struct_return typ jtyp cols
9996 | RStructList (_, typ) ->
9997 let jtyp = java_name_of_struct typ in
9998 let cols = cols_of_struct typ in
9999 generate_java_struct_list_return typ jtyp cols
10002 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10003 pr " return NULL;\n"
10005 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10014 and generate_java_struct_return typ jtyp cols =
10015 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10016 pr " jr = (*env)->AllocObject (env, cl);\n";
10020 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10021 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10024 pr " char s[33];\n";
10025 pr " memcpy (s, r->%s, 32);\n" name;
10026 pr " s[32] = 0;\n";
10027 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10028 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10032 pr " int len = r->%s_len;\n" name;
10033 pr " char s[len+1];\n";
10034 pr " memcpy (s, r->%s, len);\n" name;
10035 pr " s[len] = 0;\n";
10036 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10037 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10039 | name, (FBytes|FUInt64|FInt64) ->
10040 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10041 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10042 | name, (FUInt32|FInt32) ->
10043 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10044 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10045 | name, FOptPercent ->
10046 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10047 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10049 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10050 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10055 and generate_java_struct_list_return typ jtyp cols =
10056 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10057 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10058 pr " for (i = 0; i < r->len; ++i) {\n";
10059 pr " jfl = (*env)->AllocObject (env, cl);\n";
10063 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10064 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10067 pr " char s[33];\n";
10068 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10069 pr " s[32] = 0;\n";
10070 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10071 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10075 pr " int len = r->val[i].%s_len;\n" name;
10076 pr " char s[len+1];\n";
10077 pr " memcpy (s, r->val[i].%s, len);\n" name;
10078 pr " s[len] = 0;\n";
10079 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10080 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10082 | name, (FBytes|FUInt64|FInt64) ->
10083 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10084 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10085 | name, (FUInt32|FInt32) ->
10086 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10087 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10088 | name, FOptPercent ->
10089 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10090 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10092 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10093 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10095 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10097 pr " guestfs_free_%s_list (r);\n" typ;
10100 and generate_java_makefile_inc () =
10101 generate_header HashStyle GPLv2plus;
10103 pr "java_built_sources = \\\n";
10106 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10108 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10110 and generate_haskell_hs () =
10111 generate_header HaskellStyle LGPLv2plus;
10113 (* XXX We only know how to generate partial FFI for Haskell
10114 * at the moment. Please help out!
10116 let can_generate style =
10120 | RInt64 _, _ -> true
10122 | RConstString _, _
10123 | RConstOptString _, _
10129 | RBufferOut _, _ -> false in
10132 {-# INCLUDE <guestfs.h> #-}
10133 {-# LANGUAGE ForeignFunctionInterface #-}
10138 (* List out the names of the actions we want to export. *)
10140 fun (name, style, _, _, _, _, _) ->
10141 if can_generate style then pr ",\n %s" name
10147 -- Unfortunately some symbols duplicate ones already present
10148 -- in Prelude. We don't know which, so we hard-code a list
10150 import Prelude hiding (truncate)
10154 import Foreign.C.Types
10156 import Control.Exception
10157 import Data.Typeable
10159 data GuestfsS = GuestfsS -- represents the opaque C struct
10160 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10161 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10163 -- XXX define properly later XXX
10167 data IntBool = IntBool
10169 data StatVFS = StatVFS
10170 data Hashtable = Hashtable
10172 foreign import ccall unsafe \"guestfs_create\" c_create
10174 foreign import ccall unsafe \"&guestfs_close\" c_close
10175 :: FunPtr (GuestfsP -> IO ())
10176 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10177 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10179 create :: IO GuestfsH
10182 c_set_error_handler p nullPtr nullPtr
10183 h <- newForeignPtr c_close p
10186 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10187 :: GuestfsP -> IO CString
10189 -- last_error :: GuestfsH -> IO (Maybe String)
10190 -- last_error h = do
10191 -- str <- withForeignPtr h (\\p -> c_last_error p)
10192 -- maybePeek peekCString str
10194 last_error :: GuestfsH -> IO (String)
10196 str <- withForeignPtr h (\\p -> c_last_error p)
10197 if (str == nullPtr)
10198 then return \"no error\"
10199 else peekCString str
10203 (* Generate wrappers for each foreign function. *)
10205 fun (name, style, _, _, _, _, _) ->
10206 if can_generate style then (
10207 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10209 generate_haskell_prototype ~handle:"GuestfsP" style;
10213 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10215 pr "%s %s = do\n" name
10216 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10218 (* Convert pointer arguments using with* functions. *)
10223 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10224 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10225 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10226 | Bool _ | Int _ | Int64 _ -> ()
10228 (* Convert integer arguments. *)
10232 | Bool n -> sprintf "(fromBool %s)" n
10233 | Int n -> sprintf "(fromIntegral %s)" n
10234 | Int64 n -> sprintf "(fromIntegral %s)" n
10235 | FileIn n | FileOut n
10236 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10238 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10239 (String.concat " " ("p" :: args));
10240 (match fst style with
10241 | RErr | RInt _ | RInt64 _ | RBool _ ->
10242 pr " if (r == -1)\n";
10244 pr " err <- last_error h\n";
10246 | RConstString _ | RConstOptString _ | RString _
10247 | RStringList _ | RStruct _
10248 | RStructList _ | RHashtable _ | RBufferOut _ ->
10249 pr " if (r == nullPtr)\n";
10251 pr " err <- last_error h\n";
10254 (match fst style with
10256 pr " else return ()\n"
10258 pr " else return (fromIntegral r)\n"
10260 pr " else return (fromIntegral r)\n"
10262 pr " else return (toBool r)\n"
10264 | RConstOptString _
10271 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10277 and generate_haskell_prototype ~handle ?(hs = false) style =
10278 pr "%s -> " handle;
10279 let string = if hs then "String" else "CString" in
10280 let int = if hs then "Int" else "CInt" in
10281 let bool = if hs then "Bool" else "CInt" in
10282 let int64 = if hs then "Integer" else "Int64" in
10286 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10287 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10288 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10289 | Bool _ -> pr "%s" bool
10290 | Int _ -> pr "%s" int
10291 | Int64 _ -> pr "%s" int
10292 | FileIn _ -> pr "%s" string
10293 | FileOut _ -> pr "%s" string
10298 (match fst style with
10299 | RErr -> if not hs then pr "CInt"
10300 | RInt _ -> pr "%s" int
10301 | RInt64 _ -> pr "%s" int64
10302 | RBool _ -> pr "%s" bool
10303 | RConstString _ -> pr "%s" string
10304 | RConstOptString _ -> pr "Maybe %s" string
10305 | RString _ -> pr "%s" string
10306 | RStringList _ -> pr "[%s]" string
10307 | RStruct (_, typ) ->
10308 let name = java_name_of_struct typ in
10310 | RStructList (_, typ) ->
10311 let name = java_name_of_struct typ in
10313 | RHashtable _ -> pr "Hashtable"
10314 | RBufferOut _ -> pr "%s" string
10318 and generate_csharp () =
10319 generate_header CPlusPlusStyle LGPLv2plus;
10321 (* XXX Make this configurable by the C# assembly users. *)
10322 let library = "libguestfs.so.0" in
10325 // These C# bindings are highly experimental at present.
10327 // Firstly they only work on Linux (ie. Mono). In order to get them
10328 // to work on Windows (ie. .Net) you would need to port the library
10329 // itself to Windows first.
10331 // The second issue is that some calls are known to be incorrect and
10332 // can cause Mono to segfault. Particularly: calls which pass or
10333 // return string[], or return any structure value. This is because
10334 // we haven't worked out the correct way to do this from C#.
10336 // The third issue is that when compiling you get a lot of warnings.
10337 // We are not sure whether the warnings are important or not.
10339 // Fourthly we do not routinely build or test these bindings as part
10340 // of the make && make check cycle, which means that regressions might
10343 // Suggestions and patches are welcome.
10347 // gmcs Libguestfs.cs
10348 // mono Libguestfs.exe
10350 // (You'll probably want to add a Test class / static main function
10351 // otherwise this won't do anything useful).
10355 using System.Runtime.InteropServices;
10356 using System.Runtime.Serialization;
10357 using System.Collections;
10361 class Error : System.ApplicationException
10363 public Error (string message) : base (message) {}
10364 protected Error (SerializationInfo info, StreamingContext context) {}
10371 [DllImport (\"%s\")]
10372 static extern IntPtr guestfs_create ();
10376 _handle = guestfs_create ();
10377 if (_handle == IntPtr.Zero)
10378 throw new Error (\"could not create guestfs handle\");
10381 [DllImport (\"%s\")]
10382 static extern void guestfs_close (IntPtr h);
10386 guestfs_close (_handle);
10389 [DllImport (\"%s\")]
10390 static extern string guestfs_last_error (IntPtr h);
10392 " library library library;
10394 (* Generate C# structure bindings. We prefix struct names with
10395 * underscore because C# cannot have conflicting struct names and
10396 * method names (eg. "class stat" and "stat").
10400 pr " [StructLayout (LayoutKind.Sequential)]\n";
10401 pr " public class _%s {\n" typ;
10404 | name, FChar -> pr " char %s;\n" name
10405 | name, FString -> pr " string %s;\n" name
10407 pr " uint %s_len;\n" name;
10408 pr " string %s;\n" name
10410 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10411 pr " string %s;\n" name
10412 | name, FUInt32 -> pr " uint %s;\n" name
10413 | name, FInt32 -> pr " int %s;\n" name
10414 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10415 | name, FInt64 -> pr " long %s;\n" name
10416 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10422 (* Generate C# function bindings. *)
10424 fun (name, style, _, _, _, shortdesc, _) ->
10425 let rec csharp_return_type () =
10426 match fst style with
10428 | RBool n -> "bool"
10430 | RInt64 n -> "long"
10432 | RConstOptString n
10434 | RBufferOut n -> "string"
10435 | RStruct (_,n) -> "_" ^ n
10436 | RHashtable n -> "Hashtable"
10437 | RStringList n -> "string[]"
10438 | RStructList (_,n) -> sprintf "_%s[]" n
10440 and c_return_type () =
10441 match fst style with
10445 | RInt64 _ -> "long"
10447 | RConstOptString _
10449 | RBufferOut _ -> "string"
10450 | RStruct (_,n) -> "_" ^ n
10452 | RStringList _ -> "string[]"
10453 | RStructList (_,n) -> sprintf "_%s[]" n
10455 and c_error_comparison () =
10456 match fst style with
10460 | RInt64 _ -> "== -1"
10462 | RConstOptString _
10468 | RStructList (_,_) -> "== null"
10470 and generate_extern_prototype () =
10471 pr " static extern %s guestfs_%s (IntPtr h"
10472 (c_return_type ()) name;
10475 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10476 | FileIn n | FileOut n ->
10477 pr ", [In] string %s" n
10478 | StringList n | DeviceList n ->
10479 pr ", [In] string[] %s" n
10489 and generate_public_prototype () =
10490 pr " public %s %s (" (csharp_return_type ()) name;
10491 let comma = ref false in
10493 if !comma then pr ", ";
10498 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10499 | FileIn n | FileOut n ->
10500 next (); pr "string %s" n
10501 | StringList n | DeviceList n ->
10502 next (); pr "string[] %s" n
10504 next (); pr "bool %s" n
10506 next (); pr "int %s" n
10508 next (); pr "long %s" n
10512 and generate_call () =
10513 pr "guestfs_%s (_handle" name;
10514 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10518 pr " [DllImport (\"%s\")]\n" library;
10519 generate_extern_prototype ();
10521 pr " /// <summary>\n";
10522 pr " /// %s\n" shortdesc;
10523 pr " /// </summary>\n";
10524 generate_public_prototype ();
10526 pr " %s r;\n" (c_return_type ());
10529 pr " if (r %s)\n" (c_error_comparison ());
10530 pr " throw new Error (guestfs_last_error (_handle));\n";
10531 (match fst style with
10534 pr " return r != 0 ? true : false;\n"
10536 pr " Hashtable rr = new Hashtable ();\n";
10537 pr " for (int i = 0; i < r.Length; i += 2)\n";
10538 pr " rr.Add (r[i], r[i+1]);\n";
10540 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10541 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10547 ) all_functions_sorted;
10553 and generate_bindtests () =
10554 generate_header CStyle LGPLv2plus;
10558 #include <stdlib.h>
10559 #include <inttypes.h>
10560 #include <string.h>
10562 #include \"guestfs.h\"
10563 #include \"guestfs-internal.h\"
10564 #include \"guestfs-internal-actions.h\"
10565 #include \"guestfs_protocol.h\"
10567 #define error guestfs_error
10568 #define safe_calloc guestfs_safe_calloc
10569 #define safe_malloc guestfs_safe_malloc
10572 print_strings (char *const *argv)
10577 for (argc = 0; argv[argc] != NULL; ++argc) {
10578 if (argc > 0) printf (\", \");
10579 printf (\"\\\"%%s\\\"\", argv[argc]);
10584 /* The test0 function prints its parameters to stdout. */
10588 match test_functions with
10589 | [] -> assert false
10590 | test0 :: tests -> test0, tests in
10593 let (name, style, _, _, _, _, _) = test0 in
10594 generate_prototype ~extern:false ~semicolon:false ~newline:true
10595 ~handle:"g" ~prefix:"guestfs__" name style;
10600 | Device n | Dev_or_Path n
10603 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10604 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10605 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10606 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10607 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10608 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10610 pr " /* Java changes stdout line buffering so we need this: */\n";
10611 pr " fflush (stdout);\n";
10617 fun (name, style, _, _, _, _, _) ->
10618 if String.sub name (String.length name - 3) 3 <> "err" then (
10619 pr "/* Test normal return. */\n";
10620 generate_prototype ~extern:false ~semicolon:false ~newline:true
10621 ~handle:"g" ~prefix:"guestfs__" name style;
10623 (match fst style with
10628 pr " sscanf (val, \"%%d\", &r);\n";
10631 pr " int64_t r;\n";
10632 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10635 pr " return STREQ (val, \"true\");\n"
10637 | RConstOptString _ ->
10638 (* Can't return the input string here. Return a static
10639 * string so we ensure we get a segfault if the caller
10640 * tries to free it.
10642 pr " return \"static string\";\n"
10644 pr " return strdup (val);\n"
10646 pr " char **strs;\n";
10648 pr " sscanf (val, \"%%d\", &n);\n";
10649 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10650 pr " for (i = 0; i < n; ++i) {\n";
10651 pr " strs[i] = safe_malloc (g, 16);\n";
10652 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10654 pr " strs[n] = NULL;\n";
10655 pr " return strs;\n"
10656 | RStruct (_, typ) ->
10657 pr " struct guestfs_%s *r;\n" typ;
10658 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10660 | RStructList (_, typ) ->
10661 pr " struct guestfs_%s_list *r;\n" typ;
10662 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10663 pr " sscanf (val, \"%%d\", &r->len);\n";
10664 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10667 pr " char **strs;\n";
10669 pr " sscanf (val, \"%%d\", &n);\n";
10670 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10671 pr " for (i = 0; i < n; ++i) {\n";
10672 pr " strs[i*2] = safe_malloc (g, 16);\n";
10673 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10674 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10675 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10677 pr " strs[n*2] = NULL;\n";
10678 pr " return strs;\n"
10680 pr " return strdup (val);\n"
10685 pr "/* Test error return. */\n";
10686 generate_prototype ~extern:false ~semicolon:false ~newline:true
10687 ~handle:"g" ~prefix:"guestfs__" name style;
10689 pr " error (g, \"error\");\n";
10690 (match fst style with
10691 | RErr | RInt _ | RInt64 _ | RBool _ ->
10693 | RConstString _ | RConstOptString _
10694 | RString _ | RStringList _ | RStruct _
10698 pr " return NULL;\n"
10705 and generate_ocaml_bindtests () =
10706 generate_header OCamlStyle GPLv2plus;
10710 let g = Guestfs.create () in
10714 String.concat " " (
10717 | CallString s -> "\"" ^ s ^ "\""
10718 | CallOptString None -> "None"
10719 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10720 | CallStringList xs ->
10721 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10722 | CallInt i when i >= 0 -> string_of_int i
10723 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10724 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10725 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10726 | CallBool b -> string_of_bool b
10731 generate_lang_bindtests (
10732 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10735 pr "print_endline \"EOF\"\n"
10737 and generate_perl_bindtests () =
10738 pr "#!/usr/bin/perl -w\n";
10739 generate_header HashStyle GPLv2plus;
10746 my $g = Sys::Guestfs->new ();
10750 String.concat ", " (
10753 | CallString s -> "\"" ^ s ^ "\""
10754 | CallOptString None -> "undef"
10755 | CallOptString (Some s) -> sprintf "\"%s\"" s
10756 | CallStringList xs ->
10757 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10758 | CallInt i -> string_of_int i
10759 | CallInt64 i -> Int64.to_string i
10760 | CallBool b -> if b then "1" else "0"
10765 generate_lang_bindtests (
10766 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10769 pr "print \"EOF\\n\"\n"
10771 and generate_python_bindtests () =
10772 generate_header HashStyle GPLv2plus;
10777 g = guestfs.GuestFS ()
10781 String.concat ", " (
10784 | CallString s -> "\"" ^ s ^ "\""
10785 | CallOptString None -> "None"
10786 | CallOptString (Some s) -> sprintf "\"%s\"" s
10787 | CallStringList xs ->
10788 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10789 | CallInt i -> string_of_int i
10790 | CallInt64 i -> Int64.to_string i
10791 | CallBool b -> if b then "1" else "0"
10796 generate_lang_bindtests (
10797 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10800 pr "print \"EOF\"\n"
10802 and generate_ruby_bindtests () =
10803 generate_header HashStyle GPLv2plus;
10808 g = Guestfs::create()
10812 String.concat ", " (
10815 | CallString s -> "\"" ^ s ^ "\""
10816 | CallOptString None -> "nil"
10817 | CallOptString (Some s) -> sprintf "\"%s\"" s
10818 | CallStringList xs ->
10819 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10820 | CallInt i -> string_of_int i
10821 | CallInt64 i -> Int64.to_string i
10822 | CallBool b -> string_of_bool b
10827 generate_lang_bindtests (
10828 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10831 pr "print \"EOF\\n\"\n"
10833 and generate_java_bindtests () =
10834 generate_header CStyle GPLv2plus;
10837 import com.redhat.et.libguestfs.*;
10839 public class Bindtests {
10840 public static void main (String[] argv)
10843 GuestFS g = new GuestFS ();
10847 String.concat ", " (
10850 | CallString s -> "\"" ^ s ^ "\""
10851 | CallOptString None -> "null"
10852 | CallOptString (Some s) -> sprintf "\"%s\"" s
10853 | CallStringList xs ->
10855 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10856 | CallInt i -> string_of_int i
10857 | CallInt64 i -> Int64.to_string i
10858 | CallBool b -> string_of_bool b
10863 generate_lang_bindtests (
10864 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10868 System.out.println (\"EOF\");
10870 catch (Exception exn) {
10871 System.err.println (exn);
10878 and generate_haskell_bindtests () =
10879 generate_header HaskellStyle GPLv2plus;
10882 module Bindtests where
10883 import qualified Guestfs
10886 g <- Guestfs.create
10890 String.concat " " (
10893 | CallString s -> "\"" ^ s ^ "\""
10894 | CallOptString None -> "Nothing"
10895 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10896 | CallStringList xs ->
10897 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10898 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10899 | CallInt i -> string_of_int i
10900 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10901 | CallInt64 i -> Int64.to_string i
10902 | CallBool true -> "True"
10903 | CallBool false -> "False"
10908 generate_lang_bindtests (
10909 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10912 pr " putStrLn \"EOF\"\n"
10914 (* Language-independent bindings tests - we do it this way to
10915 * ensure there is parity in testing bindings across all languages.
10917 and generate_lang_bindtests call =
10918 call "test0" [CallString "abc"; CallOptString (Some "def");
10919 CallStringList []; CallBool false;
10920 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10921 call "test0" [CallString "abc"; CallOptString None;
10922 CallStringList []; CallBool false;
10923 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10924 call "test0" [CallString ""; CallOptString (Some "def");
10925 CallStringList []; CallBool false;
10926 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10927 call "test0" [CallString ""; CallOptString (Some "");
10928 CallStringList []; CallBool false;
10929 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10930 call "test0" [CallString "abc"; CallOptString (Some "def");
10931 CallStringList ["1"]; CallBool false;
10932 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10933 call "test0" [CallString "abc"; CallOptString (Some "def");
10934 CallStringList ["1"; "2"]; CallBool false;
10935 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10936 call "test0" [CallString "abc"; CallOptString (Some "def");
10937 CallStringList ["1"]; CallBool true;
10938 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10939 call "test0" [CallString "abc"; CallOptString (Some "def");
10940 CallStringList ["1"]; CallBool false;
10941 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10942 call "test0" [CallString "abc"; CallOptString (Some "def");
10943 CallStringList ["1"]; CallBool false;
10944 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10945 call "test0" [CallString "abc"; CallOptString (Some "def");
10946 CallStringList ["1"]; CallBool false;
10947 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10948 call "test0" [CallString "abc"; CallOptString (Some "def");
10949 CallStringList ["1"]; CallBool false;
10950 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10951 call "test0" [CallString "abc"; CallOptString (Some "def");
10952 CallStringList ["1"]; CallBool false;
10953 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10954 call "test0" [CallString "abc"; CallOptString (Some "def");
10955 CallStringList ["1"]; CallBool false;
10956 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10958 (* XXX Add here tests of the return and error functions. *)
10960 (* Code to generator bindings for virt-inspector. Currently only
10961 * implemented for OCaml code (for virt-p2v 2.0).
10963 let rng_input = "inspector/virt-inspector.rng"
10965 (* Read the input file and parse it into internal structures. This is
10966 * by no means a complete RELAX NG parser, but is just enough to be
10967 * able to parse the specific input file.
10970 | Element of string * rng list (* <element name=name/> *)
10971 | Attribute of string * rng list (* <attribute name=name/> *)
10972 | Interleave of rng list (* <interleave/> *)
10973 | ZeroOrMore of rng (* <zeroOrMore/> *)
10974 | OneOrMore of rng (* <oneOrMore/> *)
10975 | Optional of rng (* <optional/> *)
10976 | Choice of string list (* <choice><value/>*</choice> *)
10977 | Value of string (* <value>str</value> *)
10978 | Text (* <text/> *)
10980 let rec string_of_rng = function
10981 | Element (name, xs) ->
10982 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10983 | Attribute (name, xs) ->
10984 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10985 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10986 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10987 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10988 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10989 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10990 | Value value -> "Value \"" ^ value ^ "\""
10993 and string_of_rng_list xs =
10994 String.concat ", " (List.map string_of_rng xs)
10996 let rec parse_rng ?defines context = function
10998 | Xml.Element ("element", ["name", name], children) :: rest ->
10999 Element (name, parse_rng ?defines context children)
11000 :: parse_rng ?defines context rest
11001 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11002 Attribute (name, parse_rng ?defines context children)
11003 :: parse_rng ?defines context rest
11004 | Xml.Element ("interleave", [], children) :: rest ->
11005 Interleave (parse_rng ?defines context children)
11006 :: parse_rng ?defines context rest
11007 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11008 let rng = parse_rng ?defines context [child] in
11010 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11012 failwithf "%s: <zeroOrMore> contains more than one child element"
11015 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11016 let rng = parse_rng ?defines context [child] in
11018 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11020 failwithf "%s: <oneOrMore> contains more than one child element"
11023 | Xml.Element ("optional", [], [child]) :: rest ->
11024 let rng = parse_rng ?defines context [child] in
11026 | [child] -> Optional child :: parse_rng ?defines context rest
11028 failwithf "%s: <optional> contains more than one child element"
11031 | Xml.Element ("choice", [], children) :: rest ->
11032 let values = List.map (
11033 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11035 failwithf "%s: can't handle anything except <value> in <choice>"
11039 :: parse_rng ?defines context rest
11040 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11041 Value value :: parse_rng ?defines context rest
11042 | Xml.Element ("text", [], []) :: rest ->
11043 Text :: parse_rng ?defines context rest
11044 | Xml.Element ("ref", ["name", name], []) :: rest ->
11045 (* Look up the reference. Because of limitations in this parser,
11046 * we can't handle arbitrarily nested <ref> yet. You can only
11047 * use <ref> from inside <start>.
11049 (match defines with
11051 failwithf "%s: contains <ref>, but no refs are defined yet" context
11053 let rng = StringMap.find name map in
11054 rng @ parse_rng ?defines context rest
11057 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11060 let xml = Xml.parse_file rng_input in
11062 | Xml.Element ("grammar", _,
11063 Xml.Element ("start", _, gram) :: defines) ->
11064 (* The <define/> elements are referenced in the <start> section,
11065 * so build a map of those first.
11067 let defines = List.fold_left (
11069 function Xml.Element ("define", ["name", name], defn) ->
11070 StringMap.add name defn map
11072 failwithf "%s: expected <define name=name/>" rng_input
11073 ) StringMap.empty defines in
11074 let defines = StringMap.mapi parse_rng defines in
11076 (* Parse the <start> clause, passing the defines. *)
11077 parse_rng ~defines "<start>" gram
11079 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11082 let name_of_field = function
11083 | Element (name, _) | Attribute (name, _)
11084 | ZeroOrMore (Element (name, _))
11085 | OneOrMore (Element (name, _))
11086 | Optional (Element (name, _)) -> name
11087 | Optional (Attribute (name, _)) -> name
11088 | Text -> (* an unnamed field in an element *)
11091 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11093 (* At the moment this function only generates OCaml types. However we
11094 * should parameterize it later so it can generate types/structs in a
11095 * variety of languages.
11097 let generate_types xs =
11098 (* A simple type is one that can be printed out directly, eg.
11099 * "string option". A complex type is one which has a name and has
11100 * to be defined via another toplevel definition, eg. a struct.
11102 * generate_type generates code for either simple or complex types.
11103 * In the simple case, it returns the string ("string option"). In
11104 * the complex case, it returns the name ("mountpoint"). In the
11105 * complex case it has to print out the definition before returning,
11106 * so it should only be called when we are at the beginning of a
11107 * new line (BOL context).
11109 let rec generate_type = function
11110 | Text -> (* string *)
11112 | Choice values -> (* [`val1|`val2|...] *)
11113 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11114 | ZeroOrMore rng -> (* <rng> list *)
11115 let t, is_simple = generate_type rng in
11116 t ^ " list (* 0 or more *)", is_simple
11117 | OneOrMore rng -> (* <rng> list *)
11118 let t, is_simple = generate_type rng in
11119 t ^ " list (* 1 or more *)", is_simple
11120 (* virt-inspector hack: bool *)
11121 | Optional (Attribute (name, [Value "1"])) ->
11123 | Optional rng -> (* <rng> list *)
11124 let t, is_simple = generate_type rng in
11125 t ^ " option", is_simple
11126 (* type name = { fields ... } *)
11127 | Element (name, fields) when is_attrs_interleave fields ->
11128 generate_type_struct name (get_attrs_interleave fields)
11129 | Element (name, [field]) (* type name = field *)
11130 | Attribute (name, [field]) ->
11131 let t, is_simple = generate_type field in
11132 if is_simple then (t, true)
11134 pr "type %s = %s\n" name t;
11137 | Element (name, fields) -> (* type name = { fields ... } *)
11138 generate_type_struct name fields
11140 failwithf "generate_type failed at: %s" (string_of_rng rng)
11142 and is_attrs_interleave = function
11143 | [Interleave _] -> true
11144 | Attribute _ :: fields -> is_attrs_interleave fields
11145 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11148 and get_attrs_interleave = function
11149 | [Interleave fields] -> fields
11150 | ((Attribute _) as field) :: fields
11151 | ((Optional (Attribute _)) as field) :: fields ->
11152 field :: get_attrs_interleave fields
11153 | _ -> assert false
11155 and generate_types xs =
11156 List.iter (fun x -> ignore (generate_type x)) xs
11158 and generate_type_struct name fields =
11159 (* Calculate the types of the fields first. We have to do this
11160 * before printing anything so we are still in BOL context.
11162 let types = List.map fst (List.map generate_type fields) in
11164 (* Special case of a struct containing just a string and another
11165 * field. Turn it into an assoc list.
11168 | ["string"; other] ->
11169 let fname1, fname2 =
11171 | [f1; f2] -> name_of_field f1, name_of_field f2
11172 | _ -> assert false in
11173 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11177 pr "type %s = {\n" name;
11179 fun (field, ftype) ->
11180 let fname = name_of_field field in
11181 pr " %s_%s : %s;\n" name fname ftype
11182 ) (List.combine fields types);
11184 (* Return the name of this type, and
11185 * false because it's not a simple type.
11192 let generate_parsers xs =
11193 (* As for generate_type above, generate_parser makes a parser for
11194 * some type, and returns the name of the parser it has generated.
11195 * Because it (may) need to print something, it should always be
11196 * called in BOL context.
11198 let rec generate_parser = function
11199 | Text -> (* string *)
11200 "string_child_or_empty"
11201 | Choice values -> (* [`val1|`val2|...] *)
11202 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11204 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11205 | ZeroOrMore rng -> (* <rng> list *)
11206 let pa = generate_parser rng in
11207 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11208 | OneOrMore rng -> (* <rng> list *)
11209 let pa = generate_parser rng in
11210 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11211 (* virt-inspector hack: bool *)
11212 | Optional (Attribute (name, [Value "1"])) ->
11213 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11214 | Optional rng -> (* <rng> list *)
11215 let pa = generate_parser rng in
11216 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11217 (* type name = { fields ... } *)
11218 | Element (name, fields) when is_attrs_interleave fields ->
11219 generate_parser_struct name (get_attrs_interleave fields)
11220 | Element (name, [field]) -> (* type name = field *)
11221 let pa = generate_parser field in
11222 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11223 pr "let %s =\n" parser_name;
11225 pr "let parse_%s = %s\n" name parser_name;
11227 | Attribute (name, [field]) ->
11228 let pa = generate_parser field in
11229 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11230 pr "let %s =\n" parser_name;
11232 pr "let parse_%s = %s\n" name parser_name;
11234 | Element (name, fields) -> (* type name = { fields ... } *)
11235 generate_parser_struct name ([], fields)
11237 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11239 and is_attrs_interleave = function
11240 | [Interleave _] -> true
11241 | Attribute _ :: fields -> is_attrs_interleave fields
11242 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11245 and get_attrs_interleave = function
11246 | [Interleave fields] -> [], fields
11247 | ((Attribute _) as field) :: fields
11248 | ((Optional (Attribute _)) as field) :: fields ->
11249 let attrs, interleaves = get_attrs_interleave fields in
11250 (field :: attrs), interleaves
11251 | _ -> assert false
11253 and generate_parsers xs =
11254 List.iter (fun x -> ignore (generate_parser x)) xs
11256 and generate_parser_struct name (attrs, interleaves) =
11257 (* Generate parsers for the fields first. We have to do this
11258 * before printing anything so we are still in BOL context.
11260 let fields = attrs @ interleaves in
11261 let pas = List.map generate_parser fields in
11263 (* Generate an intermediate tuple from all the fields first.
11264 * If the type is just a string + another field, then we will
11265 * return this directly, otherwise it is turned into a record.
11267 * RELAX NG note: This code treats <interleave> and plain lists of
11268 * fields the same. In other words, it doesn't bother enforcing
11269 * any ordering of fields in the XML.
11271 pr "let parse_%s x =\n" name;
11272 pr " let t = (\n ";
11273 let comma = ref false in
11276 if !comma then pr ",\n ";
11279 | Optional (Attribute (fname, [field])), pa ->
11281 | Optional (Element (fname, [field])), pa ->
11282 pr "%s (optional_child %S x)" pa fname
11283 | Attribute (fname, [Text]), _ ->
11284 pr "attribute %S x" fname
11285 | (ZeroOrMore _ | OneOrMore _), pa ->
11290 let fname = name_of_field field in
11291 pr "%s (child %S x)" pa fname
11292 ) (List.combine fields pas);
11296 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11300 pr " (Obj.magic t : %s)\n" name
11304 | (Optional (Attribute (fname, [field])), pa) ->
11305 pr " %s_%s =\n" name fname;
11307 | (Optional (Element (fname, [field])), pa) ->
11308 pr " %s_%s =\n" name fname;
11309 pr " (let x = optional_child %S x in\n" fname;
11312 let fname = name_of_field field in
11313 pr " %s_%s =\n" name fname;
11314 pr " (let x = child %S x in\n" fname;
11316 ) (List.combine fields pas);
11320 sprintf "parse_%s" name
11323 generate_parsers xs
11325 (* Generate ocaml/guestfs_inspector.mli. *)
11326 let generate_ocaml_inspector_mli () =
11327 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11330 (** This is an OCaml language binding to the external [virt-inspector]
11333 For more information, please read the man page [virt-inspector(1)].
11338 generate_types grammar;
11339 pr "(** The nested information returned from the {!inspect} function. *)\n";
11343 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11344 (** To inspect a libvirt domain called [name], pass a singleton
11345 list: [inspect [name]]. When using libvirt only, you may
11346 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11348 To inspect a disk image or images, pass a list of the filenames
11349 of the disk images: [inspect filenames]
11351 This function inspects the given guest or disk images and
11352 returns a list of operating system(s) found and a large amount
11353 of information about them. In the vast majority of cases,
11354 a virtual machine only contains a single operating system.
11356 If the optional [~xml] parameter is given, then this function
11357 skips running the external virt-inspector program and just
11358 parses the given XML directly (which is expected to be XML
11359 produced from a previous run of virt-inspector). The list of
11360 names and connect URI are ignored in this case.
11362 This function can throw a wide variety of exceptions, for example
11363 if the external virt-inspector program cannot be found, or if
11364 it doesn't generate valid XML.
11368 (* Generate ocaml/guestfs_inspector.ml. *)
11369 let generate_ocaml_inspector_ml () =
11370 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11375 generate_types grammar;
11379 (* Misc functions which are used by the parser code below. *)
11380 let first_child = function
11381 | Xml.Element (_, _, c::_) -> c
11382 | Xml.Element (name, _, []) ->
11383 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11384 | Xml.PCData str ->
11385 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11387 let string_child_or_empty = function
11388 | Xml.Element (_, _, [Xml.PCData s]) -> s
11389 | Xml.Element (_, _, []) -> \"\"
11390 | Xml.Element (x, _, _) ->
11391 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11393 | Xml.PCData str ->
11394 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11396 let optional_child name xml =
11397 let children = Xml.children xml in
11399 Some (List.find (function
11400 | Xml.Element (n, _, _) when n = name -> true
11401 | _ -> false) children)
11405 let child name xml =
11406 match optional_child name xml with
11409 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11411 let attribute name xml =
11412 try Xml.attrib xml name
11413 with Xml.No_attribute _ ->
11414 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11418 generate_parsers grammar;
11422 (* Run external virt-inspector, then use parser to parse the XML. *)
11423 let inspect ?connect ?xml names =
11427 if names = [] then invalid_arg \"inspect: no names given\";
11428 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11429 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11431 let cmd = List.map Filename.quote cmd in
11432 let cmd = String.concat \" \" cmd in
11433 let chan = open_process_in cmd in
11434 let xml = Xml.parse_in chan in
11435 (match close_process_in chan with
11437 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11438 | WSIGNALED i | WSTOPPED i ->
11439 failwith (\"external virt-inspector command died or stopped on sig \" ^
11444 Xml.parse_string doc in
11445 parse_operatingsystems xml
11448 (* This is used to generate the src/MAX_PROC_NR file which
11449 * contains the maximum procedure number, a surrogate for the
11450 * ABI version number. See src/Makefile.am for the details.
11452 and generate_max_proc_nr () =
11453 let proc_nrs = List.map (
11454 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11455 ) daemon_functions in
11457 let max_proc_nr = List.fold_left max 0 proc_nrs in
11459 pr "%d\n" max_proc_nr
11461 let output_to filename k =
11462 let filename_new = filename ^ ".new" in
11463 chan := open_out filename_new;
11466 chan := Pervasives.stdout;
11468 (* Is the new file different from the current file? *)
11469 if Sys.file_exists filename && files_equal filename filename_new then
11470 unlink filename_new (* same, so skip it *)
11472 (* different, overwrite old one *)
11473 (try chmod filename 0o644 with Unix_error _ -> ());
11474 rename filename_new filename;
11475 chmod filename 0o444;
11476 printf "written %s\n%!" filename;
11479 let perror msg = function
11480 | Unix_error (err, _, _) ->
11481 eprintf "%s: %s\n" msg (error_message err)
11483 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11485 (* Main program. *)
11488 try openfile "HACKING" [O_RDWR] 0
11490 | Unix_error (ENOENT, _, _) ->
11492 You are probably running this from the wrong directory.
11493 Run it from the top source directory using the command
11498 perror "open: HACKING" exn;
11501 (* Acquire a lock so parallel builds won't try to run the generator
11502 * twice at the same time. Subsequent builds will wait for the first
11503 * one to finish. Note the lock is released implicitly when the
11506 (try lockf lock_fd F_LOCK 1
11508 perror "lock: HACKING" exn;
11511 check_functions ();
11513 output_to "src/guestfs_protocol.x" generate_xdr;
11514 output_to "src/guestfs-structs.h" generate_structs_h;
11515 output_to "src/guestfs-actions.h" generate_actions_h;
11516 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11517 output_to "src/guestfs-actions.c" generate_client_actions;
11518 output_to "src/guestfs-bindtests.c" generate_bindtests;
11519 output_to "src/guestfs-structs.pod" generate_structs_pod;
11520 output_to "src/guestfs-actions.pod" generate_actions_pod;
11521 output_to "src/guestfs-availability.pod" generate_availability_pod;
11522 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11523 output_to "src/libguestfs.syms" generate_linker_script;
11524 output_to "daemon/actions.h" generate_daemon_actions_h;
11525 output_to "daemon/stubs.c" generate_daemon_actions;
11526 output_to "daemon/names.c" generate_daemon_names;
11527 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11528 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11529 output_to "capitests/tests.c" generate_tests;
11530 output_to "fish/cmds.c" generate_fish_cmds;
11531 output_to "fish/completion.c" generate_fish_completion;
11532 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11533 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11534 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11535 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11536 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11537 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11538 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11539 output_to "perl/Guestfs.xs" generate_perl_xs;
11540 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11541 output_to "perl/bindtests.pl" generate_perl_bindtests;
11542 output_to "python/guestfs-py.c" generate_python_c;
11543 output_to "python/guestfs.py" generate_python_py;
11544 output_to "python/bindtests.py" generate_python_bindtests;
11545 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11546 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11547 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11551 let cols = cols_of_struct typ in
11552 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11553 output_to filename (generate_java_struct jtyp cols);
11556 output_to "java/Makefile.inc" generate_java_makefile_inc;
11557 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11558 output_to "java/Bindtests.java" generate_java_bindtests;
11559 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11560 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11561 output_to "csharp/Libguestfs.cs" generate_csharp;
11563 (* Always generate this file last, and unconditionally. It's used
11564 * by the Makefile to know when we must re-run the generator.
11566 let chan = open_out "src/stamp-generator" in
11567 fprintf chan "1\n";
11570 printf "generated %d lines of code\n" !lines