3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | NotInFish (* do not export via guestfish *)
186 | NotInDocs (* do not add this function to documentation *)
187 | DeprecatedBy of string (* function is deprecated, use .. instead *)
188 | Optional of string (* function is part of an optional group *)
190 (* You can supply zero or as many tests as you want per API call.
192 * Note that the test environment has 3 block devices, of size 500MB,
193 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194 * a fourth ISO block device with some known files on it (/dev/sdd).
196 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197 * Number of cylinders was 63 for IDE emulated disks with precisely
198 * the same size. How exactly this is calculated is a mystery.
200 * The ISO block device (/dev/sdd) comes from images/test.iso.
202 * To be able to run the tests in a reasonable amount of time,
203 * the virtual machine and block devices are reused between tests.
204 * So don't try testing kill_subprocess :-x
206 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
208 * Don't assume anything about the previous contents of the block
209 * devices. Use 'Init*' to create some initial scenarios.
211 * You can add a prerequisite clause to any individual test. This
212 * is a run-time check, which, if it fails, causes the test to be
213 * skipped. Useful if testing a command which might not work on
214 * all variations of libguestfs builds. A test that has prerequisite
215 * of 'Always' is run unconditionally.
217 * In addition, packagers can skip individual tests by setting the
218 * environment variables: eg:
219 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
220 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
222 type tests = (test_init * test_prereq * test) list
224 (* Run the command sequence and just expect nothing to fail. *)
227 (* Run the command sequence and expect the output of the final
228 * command to be the string.
230 | TestOutput of seq * string
232 (* Run the command sequence and expect the output of the final
233 * command to be the list of strings.
235 | TestOutputList of seq * string list
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of block devices (could be either
239 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240 * character of each string).
242 | TestOutputListOfDevices of seq * string list
244 (* Run the command sequence and expect the output of the final
245 * command to be the integer.
247 | TestOutputInt of seq * int
249 (* Run the command sequence and expect the output of the final
250 * command to be <op> <int>, eg. ">=", "1".
252 | TestOutputIntOp of seq * string * int
254 (* Run the command sequence and expect the output of the final
255 * command to be a true value (!= 0 or != NULL).
257 | TestOutputTrue of seq
259 (* Run the command sequence and expect the output of the final
260 * command to be a false value (== 0 or == NULL, but not an error).
262 | TestOutputFalse of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a list of the given length (but don't care about
268 | TestOutputLength of seq * int
270 (* Run the command sequence and expect the output of the final
271 * command to be a buffer (RBufferOut), ie. string + size.
273 | TestOutputBuffer of seq * string
275 (* Run the command sequence and expect the output of the final
276 * command to be a structure.
278 | TestOutputStruct of seq * test_field_compare list
280 (* Run the command sequence and expect the final command (only)
283 | TestLastFail of seq
285 and test_field_compare =
286 | CompareWithInt of string * int
287 | CompareWithIntOp of string * string * int
288 | CompareWithString of string * string
289 | CompareFieldsIntEq of string * string
290 | CompareFieldsStrEq of string * string
292 (* Test prerequisites. *)
294 (* Test always runs. *)
297 (* Test is currently disabled - eg. it fails, or it tests some
298 * unimplemented feature.
302 (* 'string' is some C code (a function body) that should return
303 * true or false. The test will run if the code returns true.
307 (* As for 'If' but the test runs _unless_ the code returns true. *)
310 (* Some initial scenarios for testing. *)
312 (* Do nothing, block devices could contain random stuff including
313 * LVM PVs, and some filesystems might be mounted. This is usually
318 (* Block devices are empty and no filesystems are mounted. *)
321 (* /dev/sda contains a single partition /dev/sda1, with random
322 * content. /dev/sdb and /dev/sdc may have random content.
327 (* /dev/sda contains a single partition /dev/sda1, which is formatted
328 * as ext2, empty [except for lost+found] and mounted on /.
329 * /dev/sdb and /dev/sdc may have random content.
335 * /dev/sda1 (is a PV):
336 * /dev/VG/LV (size 8MB):
337 * formatted as ext2, empty [except for lost+found], mounted on /
338 * /dev/sdb and /dev/sdc may have random content.
342 (* /dev/sdd (the ISO, see images/ directory in source)
347 (* Sequence of commands for testing. *)
349 and cmd = string list
351 (* Note about long descriptions: When referring to another
352 * action, use the format C<guestfs_other> (ie. the full name of
353 * the C function). This will be replaced as appropriate in other
356 * Apart from that, long descriptions are just perldoc paragraphs.
359 (* Generate a random UUID (used in tests). *)
361 let chan = open_process_in "uuidgen" in
362 let uuid = input_line chan in
363 (match close_process_in chan with
366 failwith "uuidgen: process exited with non-zero status"
367 | WSIGNALED _ | WSTOPPED _ ->
368 failwith "uuidgen: process signalled or stopped by signal"
372 (* These test functions are used in the language binding tests. *)
374 let test_all_args = [
377 StringList "strlist";
385 let test_all_rets = [
386 (* except for RErr, which is tested thoroughly elsewhere *)
387 "test0rint", RInt "valout";
388 "test0rint64", RInt64 "valout";
389 "test0rbool", RBool "valout";
390 "test0rconststring", RConstString "valout";
391 "test0rconstoptstring", RConstOptString "valout";
392 "test0rstring", RString "valout";
393 "test0rstringlist", RStringList "valout";
394 "test0rstruct", RStruct ("valout", "lvm_pv");
395 "test0rstructlist", RStructList ("valout", "lvm_pv");
396 "test0rhashtable", RHashtable "valout";
399 let test_functions = [
400 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
402 "internal test function - do not use",
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
408 It echos the contents of each parameter to stdout.
410 You probably don't want to call this function.");
414 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
416 "internal test function - do not use",
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
422 It converts string C<val> to the return type.
424 You probably don't want to call this function.");
425 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
427 "internal test function - do not use",
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
433 This function always returns an error.
435 You probably don't want to call this function.")]
439 (* non_daemon_functions are any functions which don't get processed
440 * in the daemon, eg. functions for setting and getting local
441 * configuration values.
444 let non_daemon_functions = test_functions @ [
445 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
447 "launch the qemu subprocess",
449 Internally libguestfs is implemented by running a virtual machine
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
455 ("wait_ready", (RErr, []), -1, [NotInFish],
457 "wait until the qemu subprocess launches (no op)",
459 This function is a no op.
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete. However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
470 ("kill_subprocess", (RErr, []), -1, [],
472 "kill the qemu subprocess",
474 This kills the qemu subprocess. You should never need to call this.");
476 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
478 "add an image to examine or modify",
480 This function adds a virtual machine disk image C<filename> to the
481 guest. The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
485 You don't necessarily need to be root when using libguestfs. However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>. In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
502 Note that this call checks for the existence of C<filename>. This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
505 the general C<guestfs_config> call instead.");
507 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
509 "add a CD-ROM disk image to examine",
511 This function adds a virtual CD-ROM disk image to the guest.
513 This is equivalent to the qemu parameter C<-cdrom filename>.
521 This call checks for the existence of C<filename>. This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
524 the general C<guestfs_config> call instead.
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
534 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
536 "add a drive in snapshot mode (read-only)",
538 This adds a drive in snapshot mode, making it effectively
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed. We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>. In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
555 C<readonly=on> is only added where qemu supports this option.
557 Note that this call checks for the existence of C<filename>. This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
560 the general C<guestfs_config> call instead.");
562 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
564 "add qemu parameters",
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>. Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
571 The first character of C<param> string must be a C<-> (dash).
573 C<value> can be NULL.");
575 ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
577 "set the qemu binary",
579 Set the qemu binary that we will use.
581 The default is chosen when the library was compiled by the
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
589 Note that you should call this function as early as possible
590 after creating the handle. This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results. Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
597 ("get_qemu", (RConstString "qemu", []), -1, [],
598 [InitNone, Always, TestRun (
600 "get the qemu binary",
602 Return the current qemu binary.
604 This is always non-NULL. If it wasn't set already, then this will
605 return the default qemu binary name.");
607 ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
609 "set the search path",
611 Set the path that libguestfs searches for kernel and initrd.img.
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
616 Setting C<path> to C<NULL> restores the default path.");
618 ("get_path", (RConstString "path", []), -1, [],
619 [InitNone, Always, TestRun (
621 "get the search path",
623 Return the current search path.
625 This is always non-NULL. If it wasn't set already, then this will
626 return the default path.");
628 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
630 "add options to kernel command line",
632 This function is used to add additional options to the
633 guest kernel command line.
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
641 ("get_append", (RConstOptString "append", []), -1, [],
642 (* This cannot be tested with the current framework. The
643 * function can return NULL in normal operations, which the
644 * test framework interprets as an error.
647 "get the additional kernel options",
649 Return the additional kernel options which are added to the
650 guest kernel command line.
652 If C<NULL> then no options are added.");
654 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658 If C<autosync> is true, this enables autosync. Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
666 ("get_autosync", (RBool "autosync", []), -1, [],
667 [InitNone, Always, TestRun (
668 [["get_autosync"]])],
671 Get the autosync flag.");
673 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
682 ("get_verbose", (RBool "verbose", []), -1, [],
686 This returns the verbose messages flag.");
688 ("is_ready", (RBool "ready", []), -1, [],
689 [InitNone, Always, TestOutputTrue (
691 "is ready to accept commands",
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
696 For more information on states, see L<guestfs(3)>.");
698 ("is_config", (RBool "config", []), -1, [],
699 [InitNone, Always, TestOutputFalse (
701 "is in configuration state",
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
706 For more information on states, see L<guestfs(3)>.");
708 ("is_launching", (RBool "launching", []), -1, [],
709 [InitNone, Always, TestOutputFalse (
710 [["is_launching"]])],
711 "is launching subprocess",
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
716 For more information on states, see L<guestfs(3)>.");
718 ("is_busy", (RBool "busy", []), -1, [],
719 [InitNone, Always, TestOutputFalse (
721 "is busy processing a command",
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
726 For more information on states, see L<guestfs(3)>.");
728 ("get_state", (RInt "state", []), -1, [],
730 "get the current state",
732 This returns the current state as an opaque integer. This is
733 only useful for printing debug and internal error messages.
735 For more information on states, see L<guestfs(3)>.");
737 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738 [InitNone, Always, TestOutputInt (
739 [["set_memsize"; "500"];
740 ["get_memsize"]], 500)],
741 "set memory allocated to the qemu subprocess",
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess. This only has any effect if called before
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
754 ("get_memsize", (RInt "memsize", []), -1, [],
755 [InitNone, Always, TestOutputIntOp (
756 [["get_memsize"]], ">=", 256)],
757 "get memory allocated to the qemu subprocess",
759 This gets the memory size in megabytes allocated to the
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
769 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770 [InitNone, Always, TestOutputIntOp (
771 [["get_pid"]], ">=", 1)],
772 "get PID of qemu subprocess",
774 Return the process ID of the qemu subprocess. If there is no
775 qemu subprocess, then this will return an error.
777 This is an internal call used for debugging and testing.");
779 ("version", (RStruct ("version", "version"), []), -1, [],
780 [InitNone, Always, TestOutputStruct (
781 [["version"]], [CompareWithInt ("major", 1)])],
782 "get the library version number",
784 Return the libguestfs version number that the program is linked
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against. You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
792 This call was added in version C<1.0.58>. In previous
793 versions of libguestfs there was no way to get the version
794 number. From C code you can use dynamic linker functions
795 to find out if this symbol exists (if it doesn't, then
796 it's an earlier version).
798 The call returns a structure with four elements. The first
799 three (C<major>, C<minor> and C<release>) are numbers and
800 correspond to the usual version triplet. The fourth element
801 (C<extra>) is a string and is normally empty, but may be
802 used for distro-specific information.
804 To construct the original version string:
805 C<$major.$minor.$release$extra>
807 I<Note:> Don't use this call to test for availability
808 of features. Distro backports makes this unreliable. Use
809 C<guestfs_available> instead.");
811 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
812 [InitNone, Always, TestOutputTrue (
813 [["set_selinux"; "true"];
815 "set SELinux enabled or disabled at appliance boot",
817 This sets the selinux flag that is passed to the appliance
818 at boot time. The default is C<selinux=0> (disabled).
820 Note that if SELinux is enabled, it is always in
821 Permissive mode (C<enforcing=0>).
823 For more information on the architecture of libguestfs,
824 see L<guestfs(3)>.");
826 ("get_selinux", (RBool "selinux", []), -1, [],
828 "get SELinux enabled flag",
830 This returns the current setting of the selinux flag which
831 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
836 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
837 [InitNone, Always, TestOutputFalse (
838 [["set_trace"; "false"];
840 "enable or disable command traces",
842 If the command trace flag is set to 1, then commands are
843 printed on stdout before they are executed in a format
844 which is very similar to the one used by guestfish. In
845 other words, you can run a program with this enabled, and
846 you will get out a script which you can feed to guestfish
847 to perform the same set of actions.
849 If you want to trace C API calls into libguestfs (and
850 other libraries) then possibly a better way is to use
851 the external ltrace(1) command.
853 Command traces are disabled unless the environment variable
854 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
856 ("get_trace", (RBool "trace", []), -1, [],
858 "get command trace enabled flag",
860 Return the command trace flag.");
862 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
863 [InitNone, Always, TestOutputFalse (
864 [["set_direct"; "false"];
866 "enable or disable direct appliance mode",
868 If the direct appliance mode flag is enabled, then stdin and
869 stdout are passed directly through to the appliance once it
872 One consequence of this is that log messages aren't caught
873 by the library and handled by C<guestfs_set_log_message_callback>,
874 but go straight to stdout.
876 You probably don't want to use this unless you know what you
879 The default is disabled.");
881 ("get_direct", (RBool "direct", []), -1, [],
883 "get direct appliance mode flag",
885 Return the direct appliance mode flag.");
887 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
888 [InitNone, Always, TestOutputTrue (
889 [["set_recovery_proc"; "true"];
890 ["get_recovery_proc"]])],
891 "enable or disable the recovery process",
893 If this is called with the parameter C<false> then
894 C<guestfs_launch> does not create a recovery process. The
895 purpose of the recovery process is to stop runaway qemu
896 processes in the case where the main program aborts abruptly.
898 This only has any effect if called before C<guestfs_launch>,
899 and the default is true.
901 About the only time when you would want to disable this is
902 if the main process will fork itself into the background
903 (\"daemonize\" itself). In this case the recovery process
904 thinks that the main program has disappeared and so kills
905 qemu, which is not very helpful.");
907 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
909 "get recovery process enabled flag",
911 Return the recovery process enabled flag.");
913 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
915 "add a drive specifying the QEMU block emulation to use",
917 This is the same as C<guestfs_add_drive> but it allows you
918 to specify the QEMU interface emulation to use at run time.");
920 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
922 "add a drive read-only specifying the QEMU block emulation to use",
924 This is the same as C<guestfs_add_drive_ro> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
929 (* daemon_functions are any functions which cause some action
930 * to take place in the daemon.
933 let daemon_functions = [
934 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
935 [InitEmpty, Always, TestOutput (
936 [["part_disk"; "/dev/sda"; "mbr"];
937 ["mkfs"; "ext2"; "/dev/sda1"];
938 ["mount"; "/dev/sda1"; "/"];
939 ["write_file"; "/new"; "new file contents"; "0"];
940 ["cat"; "/new"]], "new file contents")],
941 "mount a guest disk at a position in the filesystem",
943 Mount a guest disk at a position in the filesystem. Block devices
944 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
945 the guest. If those block devices contain partitions, they will have
946 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
949 The rules are the same as for L<mount(2)>: A filesystem must
950 first be mounted on C</> before others can be mounted. Other
951 filesystems can only be mounted on directories which already
954 The mounted filesystem is writable, if we have sufficient permissions
955 on the underlying device.
958 When you use this call, the filesystem options C<sync> and C<noatime>
959 are set implicitly. This was originally done because we thought it
960 would improve reliability, but it turns out that I<-o sync> has a
961 very large negative performance impact and negligible effect on
962 reliability. Therefore we recommend that you avoid using
963 C<guestfs_mount> in any code that needs performance, and instead
964 use C<guestfs_mount_options> (use an empty string for the first
965 parameter if you don't want any options).");
967 ("sync", (RErr, []), 2, [],
968 [ InitEmpty, Always, TestRun [["sync"]]],
969 "sync disks, writes are flushed through to the disk image",
971 This syncs the disk, so that any writes are flushed through to the
972 underlying disk image.
974 You should always call this if you have modified a disk image, before
975 closing the handle.");
977 ("touch", (RErr, [Pathname "path"]), 3, [],
978 [InitBasicFS, Always, TestOutputTrue (
980 ["exists"; "/new"]])],
981 "update file timestamps or create a new file",
983 Touch acts like the L<touch(1)> command. It can be used to
984 update the timestamps on a file, or, if the file does not exist,
985 to create a new zero-length file.");
987 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
988 [InitISOFS, Always, TestOutput (
989 [["cat"; "/known-2"]], "abcdef\n")],
990 "list the contents of a file",
992 Return the contents of the file named C<path>.
994 Note that this function cannot correctly handle binary files
995 (specifically, files containing C<\\0> character which is treated
996 as end of string). For those you need to use the C<guestfs_read_file>
997 or C<guestfs_download> functions which have a more complex interface.");
999 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1000 [], (* XXX Tricky to test because it depends on the exact format
1001 * of the 'ls -l' command, which changes between F10 and F11.
1003 "list the files in a directory (long format)",
1005 List the files in C<directory> (relative to the root directory,
1006 there is no cwd) in the format of 'ls -la'.
1008 This command is mostly useful for interactive sessions. It
1009 is I<not> intended that you try to parse the output string.");
1011 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1012 [InitBasicFS, Always, TestOutputList (
1014 ["touch"; "/newer"];
1015 ["touch"; "/newest"];
1016 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1017 "list the files in a directory",
1019 List the files in C<directory> (relative to the root directory,
1020 there is no cwd). The '.' and '..' entries are not returned, but
1021 hidden files are shown.
1023 This command is mostly useful for interactive sessions. Programs
1024 should probably use C<guestfs_readdir> instead.");
1026 ("list_devices", (RStringList "devices", []), 7, [],
1027 [InitEmpty, Always, TestOutputListOfDevices (
1028 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1029 "list the block devices",
1031 List all the block devices.
1033 The full block device names are returned, eg. C</dev/sda>");
1035 ("list_partitions", (RStringList "partitions", []), 8, [],
1036 [InitBasicFS, Always, TestOutputListOfDevices (
1037 [["list_partitions"]], ["/dev/sda1"]);
1038 InitEmpty, Always, TestOutputListOfDevices (
1039 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1040 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1041 "list the partitions",
1043 List all the partitions detected on all block devices.
1045 The full partition device names are returned, eg. C</dev/sda1>
1047 This does not return logical volumes. For that you will need to
1048 call C<guestfs_lvs>.");
1050 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1051 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1052 [["pvs"]], ["/dev/sda1"]);
1053 InitEmpty, Always, TestOutputListOfDevices (
1054 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1055 ["pvcreate"; "/dev/sda1"];
1056 ["pvcreate"; "/dev/sda2"];
1057 ["pvcreate"; "/dev/sda3"];
1058 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1059 "list the LVM physical volumes (PVs)",
1061 List all the physical volumes detected. This is the equivalent
1062 of the L<pvs(8)> command.
1064 This returns a list of just the device names that contain
1065 PVs (eg. C</dev/sda2>).
1067 See also C<guestfs_pvs_full>.");
1069 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1070 [InitBasicFSonLVM, Always, TestOutputList (
1072 InitEmpty, Always, TestOutputList (
1073 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1074 ["pvcreate"; "/dev/sda1"];
1075 ["pvcreate"; "/dev/sda2"];
1076 ["pvcreate"; "/dev/sda3"];
1077 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1078 ["vgcreate"; "VG2"; "/dev/sda3"];
1079 ["vgs"]], ["VG1"; "VG2"])],
1080 "list the LVM volume groups (VGs)",
1082 List all the volumes groups detected. This is the equivalent
1083 of the L<vgs(8)> command.
1085 This returns a list of just the volume group names that were
1086 detected (eg. C<VolGroup00>).
1088 See also C<guestfs_vgs_full>.");
1090 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1091 [InitBasicFSonLVM, Always, TestOutputList (
1092 [["lvs"]], ["/dev/VG/LV"]);
1093 InitEmpty, Always, TestOutputList (
1094 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1095 ["pvcreate"; "/dev/sda1"];
1096 ["pvcreate"; "/dev/sda2"];
1097 ["pvcreate"; "/dev/sda3"];
1098 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1099 ["vgcreate"; "VG2"; "/dev/sda3"];
1100 ["lvcreate"; "LV1"; "VG1"; "50"];
1101 ["lvcreate"; "LV2"; "VG1"; "50"];
1102 ["lvcreate"; "LV3"; "VG2"; "50"];
1103 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1104 "list the LVM logical volumes (LVs)",
1106 List all the logical volumes detected. This is the equivalent
1107 of the L<lvs(8)> command.
1109 This returns a list of the logical volume device names
1110 (eg. C</dev/VolGroup00/LogVol00>).
1112 See also C<guestfs_lvs_full>.");
1114 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1115 [], (* XXX how to test? *)
1116 "list the LVM physical volumes (PVs)",
1118 List all the physical volumes detected. This is the equivalent
1119 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1121 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1122 [], (* XXX how to test? *)
1123 "list the LVM volume groups (VGs)",
1125 List all the volumes groups detected. This is the equivalent
1126 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1128 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1129 [], (* XXX how to test? *)
1130 "list the LVM logical volumes (LVs)",
1132 List all the logical volumes detected. This is the equivalent
1133 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1135 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1136 [InitISOFS, Always, TestOutputList (
1137 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1138 InitISOFS, Always, TestOutputList (
1139 [["read_lines"; "/empty"]], [])],
1140 "read file as lines",
1142 Return the contents of the file named C<path>.
1144 The file contents are returned as a list of lines. Trailing
1145 C<LF> and C<CRLF> character sequences are I<not> returned.
1147 Note that this function cannot correctly handle binary files
1148 (specifically, files containing C<\\0> character which is treated
1149 as end of line). For those you need to use the C<guestfs_read_file>
1150 function which has a more complex interface.");
1152 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1153 [], (* XXX Augeas code needs tests. *)
1154 "create a new Augeas handle",
1156 Create a new Augeas handle for editing configuration files.
1157 If there was any previous Augeas handle associated with this
1158 guestfs session, then it is closed.
1160 You must call this before using any other C<guestfs_aug_*>
1163 C<root> is the filesystem root. C<root> must not be NULL,
1166 The flags are the same as the flags defined in
1167 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 =item C<AUG_SAVE_BACKUP> = 1
1174 Keep the original file with a C<.augsave> extension.
1176 =item C<AUG_SAVE_NEWFILE> = 2
1178 Save changes into a file with extension C<.augnew>, and
1179 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1181 =item C<AUG_TYPE_CHECK> = 4
1183 Typecheck lenses (can be expensive).
1185 =item C<AUG_NO_STDINC> = 8
1187 Do not use standard load path for modules.
1189 =item C<AUG_SAVE_NOOP> = 16
1191 Make save a no-op, just record what would have been changed.
1193 =item C<AUG_NO_LOAD> = 32
1195 Do not load the tree in C<guestfs_aug_init>.
1199 To close the handle, you can call C<guestfs_aug_close>.
1201 To find out more about Augeas, see L<http://augeas.net/>.");
1203 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1204 [], (* XXX Augeas code needs tests. *)
1205 "close the current Augeas handle",
1207 Close the current Augeas handle and free up any resources
1208 used by it. After calling this, you have to call
1209 C<guestfs_aug_init> again before you can use any other
1210 Augeas functions.");
1212 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1213 [], (* XXX Augeas code needs tests. *)
1214 "define an Augeas variable",
1216 Defines an Augeas variable C<name> whose value is the result
1217 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1220 On success this returns the number of nodes in C<expr>, or
1221 C<0> if C<expr> evaluates to something which is not a nodeset.");
1223 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1224 [], (* XXX Augeas code needs tests. *)
1225 "define an Augeas node",
1227 Defines a variable C<name> whose value is the result of
1230 If C<expr> evaluates to an empty nodeset, a node is created,
1231 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1232 C<name> will be the nodeset containing that single node.
1234 On success this returns a pair containing the
1235 number of nodes in the nodeset, and a boolean flag
1236 if a node was created.");
1238 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1239 [], (* XXX Augeas code needs tests. *)
1240 "look up the value of an Augeas path",
1242 Look up the value associated with C<path>. If C<path>
1243 matches exactly one node, the C<value> is returned.");
1245 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1246 [], (* XXX Augeas code needs tests. *)
1247 "set Augeas path to value",
1249 Set the value associated with C<path> to C<value>.");
1251 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1252 [], (* XXX Augeas code needs tests. *)
1253 "insert a sibling Augeas node",
1255 Create a new sibling C<label> for C<path>, inserting it into
1256 the tree before or after C<path> (depending on the boolean
1259 C<path> must match exactly one existing node in the tree, and
1260 C<label> must be a label, ie. not contain C</>, C<*> or end
1261 with a bracketed index C<[N]>.");
1263 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1264 [], (* XXX Augeas code needs tests. *)
1265 "remove an Augeas path",
1267 Remove C<path> and all of its children.
1269 On success this returns the number of entries which were removed.");
1271 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1272 [], (* XXX Augeas code needs tests. *)
1275 Move the node C<src> to C<dest>. C<src> must match exactly
1276 one node. C<dest> is overwritten if it exists.");
1278 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1279 [], (* XXX Augeas code needs tests. *)
1280 "return Augeas nodes which match augpath",
1282 Returns a list of paths which match the path expression C<path>.
1283 The returned paths are sufficiently qualified so that they match
1284 exactly one node in the current tree.");
1286 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1287 [], (* XXX Augeas code needs tests. *)
1288 "write all pending Augeas changes to disk",
1290 This writes all pending changes to disk.
1292 The flags which were passed to C<guestfs_aug_init> affect exactly
1293 how files are saved.");
1295 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1296 [], (* XXX Augeas code needs tests. *)
1297 "load files into the tree",
1299 Load files into the tree.
1301 See C<aug_load> in the Augeas documentation for the full gory
1304 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1305 [], (* XXX Augeas code needs tests. *)
1306 "list Augeas nodes under augpath",
1308 This is just a shortcut for listing C<guestfs_aug_match>
1309 C<path/*> and sorting the resulting nodes into alphabetical order.");
1311 ("rm", (RErr, [Pathname "path"]), 29, [],
1312 [InitBasicFS, Always, TestRun
1315 InitBasicFS, Always, TestLastFail
1317 InitBasicFS, Always, TestLastFail
1322 Remove the single file C<path>.");
1324 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1325 [InitBasicFS, Always, TestRun
1328 InitBasicFS, Always, TestLastFail
1329 [["rmdir"; "/new"]];
1330 InitBasicFS, Always, TestLastFail
1332 ["rmdir"; "/new"]]],
1333 "remove a directory",
1335 Remove the single directory C<path>.");
1337 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1338 [InitBasicFS, Always, TestOutputFalse
1340 ["mkdir"; "/new/foo"];
1341 ["touch"; "/new/foo/bar"];
1343 ["exists"; "/new"]]],
1344 "remove a file or directory recursively",
1346 Remove the file or directory C<path>, recursively removing the
1347 contents if its a directory. This is like the C<rm -rf> shell
1350 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1351 [InitBasicFS, Always, TestOutputTrue
1353 ["is_dir"; "/new"]];
1354 InitBasicFS, Always, TestLastFail
1355 [["mkdir"; "/new/foo/bar"]]],
1356 "create a directory",
1358 Create a directory named C<path>.");
1360 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1361 [InitBasicFS, Always, TestOutputTrue
1362 [["mkdir_p"; "/new/foo/bar"];
1363 ["is_dir"; "/new/foo/bar"]];
1364 InitBasicFS, Always, TestOutputTrue
1365 [["mkdir_p"; "/new/foo/bar"];
1366 ["is_dir"; "/new/foo"]];
1367 InitBasicFS, Always, TestOutputTrue
1368 [["mkdir_p"; "/new/foo/bar"];
1369 ["is_dir"; "/new"]];
1370 (* Regression tests for RHBZ#503133: *)
1371 InitBasicFS, Always, TestRun
1373 ["mkdir_p"; "/new"]];
1374 InitBasicFS, Always, TestLastFail
1376 ["mkdir_p"; "/new"]]],
1377 "create a directory and parents",
1379 Create a directory named C<path>, creating any parent directories
1380 as necessary. This is like the C<mkdir -p> shell command.");
1382 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1383 [], (* XXX Need stat command to test *)
1386 Change the mode (permissions) of C<path> to C<mode>. Only
1387 numeric modes are supported.
1389 I<Note>: When using this command from guestfish, C<mode>
1390 by default would be decimal, unless you prefix it with
1391 C<0> to get octal, ie. use C<0700> not C<700>.
1393 The mode actually set is affected by the umask.");
1395 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396 [], (* XXX Need stat command to test *)
1397 "change file owner and group",
1399 Change the file owner to C<owner> and group to C<group>.
1401 Only numeric uid and gid are supported. If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1405 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406 [InitISOFS, Always, TestOutputTrue (
1407 [["exists"; "/empty"]]);
1408 InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/directory"]])],
1410 "test if file or directory exists",
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1417 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418 [InitISOFS, Always, TestOutputTrue (
1419 [["is_file"; "/known-1"]]);
1420 InitISOFS, Always, TestOutputFalse (
1421 [["is_file"; "/directory"]])],
1422 "test if file exists",
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name. Note that it returns false for
1426 other objects like directories.
1428 See also C<guestfs_stat>.");
1430 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431 [InitISOFS, Always, TestOutputFalse (
1432 [["is_dir"; "/known-3"]]);
1433 InitISOFS, Always, TestOutputTrue (
1434 [["is_dir"; "/directory"]])],
1435 "test if file exists",
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name. Note that it returns false for
1439 other objects like files.
1441 See also C<guestfs_stat>.");
1443 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444 [InitEmpty, Always, TestOutputListOfDevices (
1445 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446 ["pvcreate"; "/dev/sda1"];
1447 ["pvcreate"; "/dev/sda2"];
1448 ["pvcreate"; "/dev/sda3"];
1449 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450 "create an LVM physical volume",
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1456 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457 [InitEmpty, Always, TestOutputList (
1458 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459 ["pvcreate"; "/dev/sda1"];
1460 ["pvcreate"; "/dev/sda2"];
1461 ["pvcreate"; "/dev/sda3"];
1462 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463 ["vgcreate"; "VG2"; "/dev/sda3"];
1464 ["vgs"]], ["VG1"; "VG2"])],
1465 "create an LVM volume group",
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1470 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471 [InitEmpty, Always, TestOutputList (
1472 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473 ["pvcreate"; "/dev/sda1"];
1474 ["pvcreate"; "/dev/sda2"];
1475 ["pvcreate"; "/dev/sda3"];
1476 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477 ["vgcreate"; "VG2"; "/dev/sda3"];
1478 ["lvcreate"; "LV1"; "VG1"; "50"];
1479 ["lvcreate"; "LV2"; "VG1"; "50"];
1480 ["lvcreate"; "LV3"; "VG2"; "50"];
1481 ["lvcreate"; "LV4"; "VG2"; "50"];
1482 ["lvcreate"; "LV5"; "VG2"; "50"];
1484 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486 "create an LVM logical volume",
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1491 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492 [InitEmpty, Always, TestOutput (
1493 [["part_disk"; "/dev/sda"; "mbr"];
1494 ["mkfs"; "ext2"; "/dev/sda1"];
1495 ["mount_options"; ""; "/dev/sda1"; "/"];
1496 ["write_file"; "/new"; "new file contents"; "0"];
1497 ["cat"; "/new"]], "new file contents")],
1498 "make a filesystem",
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume). The filesystem type is C<fstype>, for
1504 ("sfdisk", (RErr, [Device "device";
1505 Int "cyls"; Int "heads"; Int "sectors";
1506 StringList "lines"]), 43, [DangerWillRobinson],
1508 "create partitions on a block device",
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1513 C<device> should be a block device, for example C</dev/sda>.
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted. Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1523 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1524 information refer to the L<sfdisk(8)> manpage.
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1533 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534 [InitBasicFS, Always, TestOutput (
1535 [["write_file"; "/new"; "new file contents"; "0"];
1536 ["cat"; "/new"]], "new file contents");
1537 InitBasicFS, Always, TestOutput (
1538 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539 ["cat"; "/new"]], "\nnew file contents\n");
1540 InitBasicFS, Always, TestOutput (
1541 [["write_file"; "/new"; "\n\n"; "0"];
1542 ["cat"; "/new"]], "\n\n");
1543 InitBasicFS, Always, TestOutput (
1544 [["write_file"; "/new"; ""; "0"];
1545 ["cat"; "/new"]], "");
1546 InitBasicFS, Always, TestOutput (
1547 [["write_file"; "/new"; "\n\n\n"; "0"];
1548 ["cat"; "/new"]], "\n\n\n");
1549 InitBasicFS, Always, TestOutput (
1550 [["write_file"; "/new"; "\n"; "0"];
1551 ["cat"; "/new"]], "\n")],
1554 This call creates a file called C<path>. The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version. In the meantime
1565 use C<guestfs_upload>.");
1567 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568 [InitEmpty, Always, TestOutputListOfDevices (
1569 [["part_disk"; "/dev/sda"; "mbr"];
1570 ["mkfs"; "ext2"; "/dev/sda1"];
1571 ["mount_options"; ""; "/dev/sda1"; "/"];
1572 ["mounts"]], ["/dev/sda1"]);
1573 InitEmpty, Always, TestOutputList (
1574 [["part_disk"; "/dev/sda"; "mbr"];
1575 ["mkfs"; "ext2"; "/dev/sda1"];
1576 ["mount_options"; ""; "/dev/sda1"; "/"];
1579 "unmount a filesystem",
1581 This unmounts the given filesystem. The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1585 ("mounts", (RStringList "devices", []), 46, [],
1586 [InitBasicFS, Always, TestOutputListOfDevices (
1587 [["mounts"]], ["/dev/sda1"])],
1588 "show mounted filesystems",
1590 This returns the list of currently mounted filesystems. It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1593 Some internal mounts are not shown.
1595 See also: C<guestfs_mountpoints>");
1597 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598 [InitBasicFS, Always, TestOutputList (
1601 (* check that umount_all can unmount nested mounts correctly: *)
1602 InitEmpty, Always, TestOutputList (
1603 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604 ["mkfs"; "ext2"; "/dev/sda1"];
1605 ["mkfs"; "ext2"; "/dev/sda2"];
1606 ["mkfs"; "ext2"; "/dev/sda3"];
1607 ["mount_options"; ""; "/dev/sda1"; "/"];
1609 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610 ["mkdir"; "/mp1/mp2"];
1611 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612 ["mkdir"; "/mp1/mp2/mp3"];
1615 "unmount all filesystems",
1617 This unmounts all mounted filesystems.
1619 Some internal mounts are not unmounted by this call.");
1621 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1623 "remove all LVM LVs, VGs and PVs",
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1628 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629 [InitISOFS, Always, TestOutput (
1630 [["file"; "/empty"]], "empty");
1631 InitISOFS, Always, TestOutput (
1632 [["file"; "/known-1"]], "ASCII text");
1633 InitISOFS, Always, TestLastFail (
1634 [["file"; "/notexists"]])],
1635 "determine file type",
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file. This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1641 This call will also transparently look inside various types
1644 The exact command which runs is C<file -zbsL path>. Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1648 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649 [InitBasicFS, Always, TestOutput (
1650 [["upload"; "test-command"; "/test-command"];
1651 ["chmod"; "0o755"; "/test-command"];
1652 ["command"; "/test-command 1"]], "Result1");
1653 InitBasicFS, Always, TestOutput (
1654 [["upload"; "test-command"; "/test-command"];
1655 ["chmod"; "0o755"; "/test-command"];
1656 ["command"; "/test-command 2"]], "Result2\n");
1657 InitBasicFS, Always, TestOutput (
1658 [["upload"; "test-command"; "/test-command"];
1659 ["chmod"; "0o755"; "/test-command"];
1660 ["command"; "/test-command 3"]], "\nResult3");
1661 InitBasicFS, Always, TestOutput (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command"; "/test-command 4"]], "\nResult4\n");
1665 InitBasicFS, Always, TestOutput (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command"; "/test-command 5"]], "\nResult5\n\n");
1669 InitBasicFS, Always, TestOutput (
1670 [["upload"; "test-command"; "/test-command"];
1671 ["chmod"; "0o755"; "/test-command"];
1672 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673 InitBasicFS, Always, TestOutput (
1674 [["upload"; "test-command"; "/test-command"];
1675 ["chmod"; "0o755"; "/test-command"];
1676 ["command"; "/test-command 7"]], "");
1677 InitBasicFS, Always, TestOutput (
1678 [["upload"; "test-command"; "/test-command"];
1679 ["chmod"; "0o755"; "/test-command"];
1680 ["command"; "/test-command 8"]], "\n");
1681 InitBasicFS, Always, TestOutput (
1682 [["upload"; "test-command"; "/test-command"];
1683 ["chmod"; "0o755"; "/test-command"];
1684 ["command"; "/test-command 9"]], "\n\n");
1685 InitBasicFS, Always, TestOutput (
1686 [["upload"; "test-command"; "/test-command"];
1687 ["chmod"; "0o755"; "/test-command"];
1688 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689 InitBasicFS, Always, TestOutput (
1690 [["upload"; "test-command"; "/test-command"];
1691 ["chmod"; "0o755"; "/test-command"];
1692 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693 InitBasicFS, Always, TestLastFail (
1694 [["upload"; "test-command"; "/test-command"];
1695 ["chmod"; "0o755"; "/test-command"];
1696 ["command"; "/test-command"]])],
1697 "run a command from the guest filesystem",
1699 This call runs a command from the guest filesystem. The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters. The list must be
1707 non-empty (ie. must contain a program name). Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1711 The return value is anything printed to I<stdout> by
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message. The error message
1716 string is the content of I<stderr> from the command.
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>. If you require a program from
1720 another location, you should provide the full path in the
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places. It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1729 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730 [InitBasicFS, Always, TestOutputList (
1731 [["upload"; "test-command"; "/test-command"];
1732 ["chmod"; "0o755"; "/test-command"];
1733 ["command_lines"; "/test-command 1"]], ["Result1"]);
1734 InitBasicFS, Always, TestOutputList (
1735 [["upload"; "test-command"; "/test-command"];
1736 ["chmod"; "0o755"; "/test-command"];
1737 ["command_lines"; "/test-command 2"]], ["Result2"]);
1738 InitBasicFS, Always, TestOutputList (
1739 [["upload"; "test-command"; "/test-command"];
1740 ["chmod"; "0o755"; "/test-command"];
1741 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742 InitBasicFS, Always, TestOutputList (
1743 [["upload"; "test-command"; "/test-command"];
1744 ["chmod"; "0o755"; "/test-command"];
1745 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746 InitBasicFS, Always, TestOutputList (
1747 [["upload"; "test-command"; "/test-command"];
1748 ["chmod"; "0o755"; "/test-command"];
1749 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750 InitBasicFS, Always, TestOutputList (
1751 [["upload"; "test-command"; "/test-command"];
1752 ["chmod"; "0o755"; "/test-command"];
1753 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754 InitBasicFS, Always, TestOutputList (
1755 [["upload"; "test-command"; "/test-command"];
1756 ["chmod"; "0o755"; "/test-command"];
1757 ["command_lines"; "/test-command 7"]], []);
1758 InitBasicFS, Always, TestOutputList (
1759 [["upload"; "test-command"; "/test-command"];
1760 ["chmod"; "0o755"; "/test-command"];
1761 ["command_lines"; "/test-command 8"]], [""]);
1762 InitBasicFS, Always, TestOutputList (
1763 [["upload"; "test-command"; "/test-command"];
1764 ["chmod"; "0o755"; "/test-command"];
1765 ["command_lines"; "/test-command 9"]], ["";""]);
1766 InitBasicFS, Always, TestOutputList (
1767 [["upload"; "test-command"; "/test-command"];
1768 ["chmod"; "0o755"; "/test-command"];
1769 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770 InitBasicFS, Always, TestOutputList (
1771 [["upload"; "test-command"; "/test-command"];
1772 ["chmod"; "0o755"; "/test-command"];
1773 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774 "run a command, returning lines",
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1779 See also: C<guestfs_sh_lines>");
1781 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782 [InitISOFS, Always, TestOutputStruct (
1783 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784 "get file information",
1786 Returns file information for the given C<path>.
1788 This is the same as the C<stat(2)> system call.");
1790 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791 [InitISOFS, Always, TestOutputStruct (
1792 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793 "get file information for a symbolic link",
1795 Returns file information for the given C<path>.
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1801 This is the same as the C<lstat(2)> system call.");
1803 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804 [InitISOFS, Always, TestOutputStruct (
1805 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806 "get file system statistics",
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1812 This is the same as the C<statvfs(2)> system call.");
1814 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1816 "get ext2/ext3/ext4 superblock details",
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1821 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1822 manpage for more details. The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1826 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827 [InitEmpty, Always, TestOutputTrue (
1828 [["blockdev_setro"; "/dev/sda"];
1829 ["blockdev_getro"; "/dev/sda"]])],
1830 "set block device to read-only",
1832 Sets the block device named C<device> to read-only.
1834 This uses the L<blockdev(8)> command.");
1836 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837 [InitEmpty, Always, TestOutputFalse (
1838 [["blockdev_setrw"; "/dev/sda"];
1839 ["blockdev_getro"; "/dev/sda"]])],
1840 "set block device to read-write",
1842 Sets the block device named C<device> to read-write.
1844 This uses the L<blockdev(8)> command.");
1846 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847 [InitEmpty, Always, TestOutputTrue (
1848 [["blockdev_setro"; "/dev/sda"];
1849 ["blockdev_getro"; "/dev/sda"]])],
1850 "is block device set to read-only",
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1855 This uses the L<blockdev(8)> command.");
1857 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858 [InitEmpty, Always, TestOutputInt (
1859 [["blockdev_getss"; "/dev/sda"]], 512)],
1860 "get sectorsize of block device",
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 This uses the L<blockdev(8)> command.");
1870 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871 [InitEmpty, Always, TestOutputInt (
1872 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873 "get blocksize of block device",
1875 This returns the block size of a device.
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1884 "set blocksize of block device",
1886 This sets the block size of a device.
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1891 This uses the L<blockdev(8)> command.");
1893 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894 [InitEmpty, Always, TestOutputInt (
1895 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896 "get total size of device in 512-byte sectors",
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1905 This uses the L<blockdev(8)> command.");
1907 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908 [InitEmpty, Always, TestOutputInt (
1909 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910 "get total size of device in bytes",
1912 This returns the size of the device in bytes.
1914 See also C<guestfs_blockdev_getsz>.
1916 This uses the L<blockdev(8)> command.");
1918 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919 [InitEmpty, Always, TestRun
1920 [["blockdev_flushbufs"; "/dev/sda"]]],
1921 "flush device buffers",
1923 This tells the kernel to flush internal buffers associated
1926 This uses the L<blockdev(8)> command.");
1928 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929 [InitEmpty, Always, TestRun
1930 [["blockdev_rereadpt"; "/dev/sda"]]],
1931 "reread partition table",
1933 Reread the partition table on C<device>.
1935 This uses the L<blockdev(8)> command.");
1937 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938 [InitBasicFS, Always, TestOutput (
1939 (* Pick a file from cwd which isn't likely to change. *)
1940 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941 ["checksum"; "md5"; "/COPYING.LIB"]],
1942 Digest.to_hex (Digest.file "COPYING.LIB"))],
1943 "upload a file from the local machine",
1945 Upload local file C<filename> to C<remotefilename> on the
1948 C<filename> can also be a named pipe.
1950 See also C<guestfs_download>.");
1952 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953 [InitBasicFS, Always, TestOutput (
1954 (* Pick a file from cwd which isn't likely to change. *)
1955 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957 ["upload"; "testdownload.tmp"; "/upload"];
1958 ["checksum"; "md5"; "/upload"]],
1959 Digest.to_hex (Digest.file "COPYING.LIB"))],
1960 "download a file to the local machine",
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1965 C<filename> can also be a named pipe.
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1969 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970 [InitISOFS, Always, TestOutput (
1971 [["checksum"; "crc"; "/known-3"]], "2891671662");
1972 InitISOFS, Always, TestLastFail (
1973 [["checksum"; "crc"; "/notexists"]]);
1974 InitISOFS, Always, TestOutput (
1975 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986 "compute MD5, SHAx or CRC checksum of file",
1988 This call computes the MD5, SHAx or CRC checksum of the
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2003 Compute the MD5 hash (using the C<md5sum> program).
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2027 The checksum is returned as a printable string.");
2029 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030 [InitBasicFS, Always, TestOutput (
2031 [["tar_in"; "../images/helloworld.tar"; "/"];
2032 ["cat"; "/hello"]], "hello\n")],
2033 "unpack tarfile to directory",
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2038 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2040 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042 "pack directory into tarfile",
2044 This command packs the contents of C<directory> and downloads
2045 it to local file C<tarfile>.
2047 To download a compressed tarball, use C<guestfs_tgz_out>.");
2049 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2050 [InitBasicFS, Always, TestOutput (
2051 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2052 ["cat"; "/hello"]], "hello\n")],
2053 "unpack compressed tarball to directory",
2055 This command uploads and unpacks local file C<tarball> (a
2056 I<gzip compressed> tar file) into C<directory>.
2058 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2060 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2062 "pack directory into compressed tarball",
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarball>.
2067 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2069 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2070 [InitBasicFS, Always, TestLastFail (
2072 ["mount_ro"; "/dev/sda1"; "/"];
2073 ["touch"; "/new"]]);
2074 InitBasicFS, Always, TestOutput (
2075 [["write_file"; "/new"; "data"; "0"];
2077 ["mount_ro"; "/dev/sda1"; "/"];
2078 ["cat"; "/new"]], "data")],
2079 "mount a guest disk, read-only",
2081 This is the same as the C<guestfs_mount> command, but it
2082 mounts the filesystem with the read-only (I<-o ro>) flag.");
2084 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2086 "mount a guest disk with mount options",
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set the mount options as for the
2090 L<mount(8)> I<-o> flag.
2092 If the C<options> parameter is an empty string, then
2093 no options are passed (all options default to whatever
2094 the filesystem uses).");
2096 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2098 "mount a guest disk with mount options and vfstype",
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2104 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2106 "debugging and internals",
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2112 There is no comprehensive help for this command. You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2116 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117 [InitEmpty, Always, TestOutputList (
2118 [["part_disk"; "/dev/sda"; "mbr"];
2119 ["pvcreate"; "/dev/sda1"];
2120 ["vgcreate"; "VG"; "/dev/sda1"];
2121 ["lvcreate"; "LV1"; "VG"; "50"];
2122 ["lvcreate"; "LV2"; "VG"; "50"];
2123 ["lvremove"; "/dev/VG/LV1"];
2124 ["lvs"]], ["/dev/VG/LV2"]);
2125 InitEmpty, Always, TestOutputList (
2126 [["part_disk"; "/dev/sda"; "mbr"];
2127 ["pvcreate"; "/dev/sda1"];
2128 ["vgcreate"; "VG"; "/dev/sda1"];
2129 ["lvcreate"; "LV1"; "VG"; "50"];
2130 ["lvcreate"; "LV2"; "VG"; "50"];
2131 ["lvremove"; "/dev/VG"];
2133 InitEmpty, Always, TestOutputList (
2134 [["part_disk"; "/dev/sda"; "mbr"];
2135 ["pvcreate"; "/dev/sda1"];
2136 ["vgcreate"; "VG"; "/dev/sda1"];
2137 ["lvcreate"; "LV1"; "VG"; "50"];
2138 ["lvcreate"; "LV2"; "VG"; "50"];
2139 ["lvremove"; "/dev/VG"];
2141 "remove an LVM logical volume",
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2149 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150 [InitEmpty, Always, TestOutputList (
2151 [["part_disk"; "/dev/sda"; "mbr"];
2152 ["pvcreate"; "/dev/sda1"];
2153 ["vgcreate"; "VG"; "/dev/sda1"];
2154 ["lvcreate"; "LV1"; "VG"; "50"];
2155 ["lvcreate"; "LV2"; "VG"; "50"];
2158 InitEmpty, Always, TestOutputList (
2159 [["part_disk"; "/dev/sda"; "mbr"];
2160 ["pvcreate"; "/dev/sda1"];
2161 ["vgcreate"; "VG"; "/dev/sda1"];
2162 ["lvcreate"; "LV1"; "VG"; "50"];
2163 ["lvcreate"; "LV2"; "VG"; "50"];
2166 "remove an LVM volume group",
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2170 This also forcibly removes all logical volumes in the volume
2173 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174 [InitEmpty, Always, TestOutputListOfDevices (
2175 [["part_disk"; "/dev/sda"; "mbr"];
2176 ["pvcreate"; "/dev/sda1"];
2177 ["vgcreate"; "VG"; "/dev/sda1"];
2178 ["lvcreate"; "LV1"; "VG"; "50"];
2179 ["lvcreate"; "LV2"; "VG"; "50"];
2181 ["pvremove"; "/dev/sda1"];
2183 InitEmpty, Always, TestOutputListOfDevices (
2184 [["part_disk"; "/dev/sda"; "mbr"];
2185 ["pvcreate"; "/dev/sda1"];
2186 ["vgcreate"; "VG"; "/dev/sda1"];
2187 ["lvcreate"; "LV1"; "VG"; "50"];
2188 ["lvcreate"; "LV2"; "VG"; "50"];
2190 ["pvremove"; "/dev/sda1"];
2192 InitEmpty, Always, TestOutputListOfDevices (
2193 [["part_disk"; "/dev/sda"; "mbr"];
2194 ["pvcreate"; "/dev/sda1"];
2195 ["vgcreate"; "VG"; "/dev/sda1"];
2196 ["lvcreate"; "LV1"; "VG"; "50"];
2197 ["lvcreate"; "LV2"; "VG"; "50"];
2199 ["pvremove"; "/dev/sda1"];
2201 "remove an LVM physical volume",
2203 This wipes a physical volume C<device> so that LVM will no longer
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2210 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211 [InitBasicFS, Always, TestOutput (
2212 [["set_e2label"; "/dev/sda1"; "testlabel"];
2213 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214 "set the ext2/3/4 filesystem label",
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>. Filesystem labels are limited to
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2223 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2225 "get the ext2/3/4 filesystem label",
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2230 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231 (let uuid = uuidgen () in
2232 [InitBasicFS, Always, TestOutput (
2233 [["set_e2uuid"; "/dev/sda1"; uuid];
2234 ["get_e2uuid"; "/dev/sda1"]], uuid);
2235 InitBasicFS, Always, TestOutput (
2236 [["set_e2uuid"; "/dev/sda1"; "clear"];
2237 ["get_e2uuid"; "/dev/sda1"]], "");
2238 (* We can't predict what UUIDs will be, so just check the commands run. *)
2239 InitBasicFS, Always, TestRun (
2240 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241 InitBasicFS, Always, TestRun (
2242 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243 "set the ext2/3/4 filesystem UUID",
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>. The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2253 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2255 "get the ext2/3/4 filesystem UUID",
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2261 [InitBasicFS, Always, TestOutputInt (
2262 [["umount"; "/dev/sda1"];
2263 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264 InitBasicFS, Always, TestOutputInt (
2265 [["umount"; "/dev/sda1"];
2266 ["zero"; "/dev/sda1"];
2267 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268 "run the filesystem checker",
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2273 The returned integer is the status. See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2282 Multiple status codes can be summed together.
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2291 Checking or repairing NTFS volumes is not supported
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2298 ("zero", (RErr, [Device "device"]), 85, [],
2299 [InitBasicFS, Always, TestOutput (
2300 [["umount"; "/dev/sda1"];
2301 ["zero"; "/dev/sda1"];
2302 ["file"; "/dev/sda1"]], "data")],
2303 "write zeroes to the device",
2305 This command writes zeroes over the first few blocks of C<device>.
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device). It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2311 See also: C<guestfs_scrub_device>.");
2313 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314 (* Test disabled because grub-install incompatible with virtio-blk driver.
2315 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2317 [InitBasicFS, Disabled, TestOutputTrue (
2318 [["grub_install"; "/"; "/dev/sda1"];
2319 ["is_dir"; "/boot"]])],
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2325 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326 [InitBasicFS, Always, TestOutput (
2327 [["write_file"; "/old"; "file content"; "0"];
2328 ["cp"; "/old"; "/new"];
2329 ["cat"; "/new"]], "file content");
2330 InitBasicFS, Always, TestOutputTrue (
2331 [["write_file"; "/old"; "file content"; "0"];
2332 ["cp"; "/old"; "/new"];
2333 ["is_file"; "/old"]]);
2334 InitBasicFS, Always, TestOutput (
2335 [["write_file"; "/old"; "file content"; "0"];
2337 ["cp"; "/old"; "/dir/new"];
2338 ["cat"; "/dir/new"]], "file content")],
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2344 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345 [InitBasicFS, Always, TestOutput (
2346 [["mkdir"; "/olddir"];
2347 ["mkdir"; "/newdir"];
2348 ["write_file"; "/olddir/file"; "file content"; "0"];
2349 ["cp_a"; "/olddir"; "/newdir"];
2350 ["cat"; "/newdir/olddir/file"]], "file content")],
2351 "copy a file or directory recursively",
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2356 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357 [InitBasicFS, Always, TestOutput (
2358 [["write_file"; "/old"; "file content"; "0"];
2359 ["mv"; "/old"; "/new"];
2360 ["cat"; "/new"]], "file content");
2361 InitBasicFS, Always, TestOutputFalse (
2362 [["write_file"; "/old"; "file content"; "0"];
2363 ["mv"; "/old"; "/new"];
2364 ["is_file"; "/old"]])],
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2370 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371 [InitEmpty, Always, TestRun (
2372 [["drop_caches"; "3"]])],
2373 "drop kernel page cache, dentries and inodes",
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches. The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2380 Setting C<whattodrop> to 3 should drop everything.
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2385 ("dmesg", (RString "kmsgs", []), 91, [],
2386 [InitEmpty, Always, TestRun (
2388 "return kernel messages",
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel. This is sometimes useful for extended
2392 debugging of problems.
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2399 ("ping_daemon", (RErr, []), 92, [],
2400 [InitEmpty, Always, TestRun (
2401 [["ping_daemon"]])],
2402 "ping the guest daemon",
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess. Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2409 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410 [InitBasicFS, Always, TestOutputTrue (
2411 [["write_file"; "/file1"; "contents of a file"; "0"];
2412 ["cp"; "/file1"; "/file2"];
2413 ["equal"; "/file1"; "/file2"]]);
2414 InitBasicFS, Always, TestOutputFalse (
2415 [["write_file"; "/file1"; "contents of a file"; "0"];
2416 ["write_file"; "/file2"; "contents of another file"; "0"];
2417 ["equal"; "/file1"; "/file2"]]);
2418 InitBasicFS, Always, TestLastFail (
2419 [["equal"; "/file1"; "/file2"]])],
2420 "test if two files have equal contents",
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2425 The external L<cmp(1)> program is used for the comparison.");
2427 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428 [InitISOFS, Always, TestOutputList (
2429 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430 InitISOFS, Always, TestOutputList (
2431 [["strings"; "/empty"]], [])],
2432 "print the printable strings in a file",
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2437 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438 [InitISOFS, Always, TestOutputList (
2439 [["strings_e"; "b"; "/known-5"]], []);
2440 InitBasicFS, Disabled, TestOutputList (
2441 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443 "print the printable strings in a file",
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding of strings that are looked for in
2447 the source file C<path>.
2449 Allowed encodings are:
2455 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2456 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2460 Single 8-bit-byte characters.
2464 16-bit big endian strings such as those encoded in
2465 UTF-16BE or UCS-2BE.
2467 =item l (lower case letter L)
2469 16-bit little endian such as UTF-16LE and UCS-2LE.
2470 This is useful for examining binaries in Windows guests.
2474 32-bit big endian such as UCS-4BE.
2478 32-bit little endian such as UCS-4LE.
2482 The returned strings are transcoded to UTF-8.");
2484 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2485 [InitISOFS, Always, TestOutput (
2486 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2487 (* Test for RHBZ#501888c2 regression which caused large hexdump
2488 * commands to segfault.
2490 InitISOFS, Always, TestRun (
2491 [["hexdump"; "/100krandom"]])],
2492 "dump a file in hexadecimal",
2494 This runs C<hexdump -C> on the given C<path>. The result is
2495 the human-readable, canonical hex dump of the file.");
2497 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2498 [InitNone, Always, TestOutput (
2499 [["part_disk"; "/dev/sda"; "mbr"];
2500 ["mkfs"; "ext3"; "/dev/sda1"];
2501 ["mount_options"; ""; "/dev/sda1"; "/"];
2502 ["write_file"; "/new"; "test file"; "0"];
2503 ["umount"; "/dev/sda1"];
2504 ["zerofree"; "/dev/sda1"];
2505 ["mount_options"; ""; "/dev/sda1"; "/"];
2506 ["cat"; "/new"]], "test file")],
2507 "zero unused inodes and disk blocks on ext2/3 filesystem",
2509 This runs the I<zerofree> program on C<device>. This program
2510 claims to zero unused inodes and disk blocks on an ext2/3
2511 filesystem, thus making it possible to compress the filesystem
2514 You should B<not> run this program if the filesystem is
2517 It is possible that using this program can damage the filesystem
2518 or data on the filesystem.");
2520 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2522 "resize an LVM physical volume",
2524 This resizes (expands or shrinks) an existing LVM physical
2525 volume to match the new size of the underlying device.");
2527 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2528 Int "cyls"; Int "heads"; Int "sectors";
2529 String "line"]), 99, [DangerWillRobinson],
2531 "modify a single partition on a block device",
2533 This runs L<sfdisk(8)> option to modify just the single
2534 partition C<n> (note: C<n> counts from 1).
2536 For other parameters, see C<guestfs_sfdisk>. You should usually
2537 pass C<0> for the cyls/heads/sectors parameters.
2539 See also: C<guestfs_part_add>");
2541 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2543 "display the partition table",
2545 This displays the partition table on C<device>, in the
2546 human-readable output of the L<sfdisk(8)> command. It is
2547 not intended to be parsed.
2549 See also: C<guestfs_part_list>");
2551 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2553 "display the kernel geometry",
2555 This displays the kernel's idea of the geometry of C<device>.
2557 The result is in human-readable format, and not designed to
2560 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2562 "display the disk geometry from the partition table",
2564 This displays the disk geometry of C<device> read from the
2565 partition table. Especially in the case where the underlying
2566 block device has been resized, this can be different from the
2567 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2569 The result is in human-readable format, and not designed to
2572 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2574 "activate or deactivate all volume groups",
2576 This command activates or (if C<activate> is false) deactivates
2577 all logical volumes in all volume groups.
2578 If activated, then they are made known to the
2579 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2580 then those devices disappear.
2582 This command is the same as running C<vgchange -a y|n>");
2584 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2586 "activate or deactivate some volume groups",
2588 This command activates or (if C<activate> is false) deactivates
2589 all logical volumes in the listed volume groups C<volgroups>.
2590 If activated, then they are made known to the
2591 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2592 then those devices disappear.
2594 This command is the same as running C<vgchange -a y|n volgroups...>
2596 Note that if C<volgroups> is an empty list then B<all> volume groups
2597 are activated or deactivated.");
2599 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2600 [InitNone, Always, TestOutput (
2601 [["part_disk"; "/dev/sda"; "mbr"];
2602 ["pvcreate"; "/dev/sda1"];
2603 ["vgcreate"; "VG"; "/dev/sda1"];
2604 ["lvcreate"; "LV"; "VG"; "10"];
2605 ["mkfs"; "ext2"; "/dev/VG/LV"];
2606 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2607 ["write_file"; "/new"; "test content"; "0"];
2609 ["lvresize"; "/dev/VG/LV"; "20"];
2610 ["e2fsck_f"; "/dev/VG/LV"];
2611 ["resize2fs"; "/dev/VG/LV"];
2612 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2613 ["cat"; "/new"]], "test content");
2614 InitNone, Always, TestRun (
2615 (* Make an LV smaller to test RHBZ#587484. *)
2616 [["part_disk"; "/dev/sda"; "mbr"];
2617 ["pvcreate"; "/dev/sda1"];
2618 ["vgcreate"; "VG"; "/dev/sda1"];
2619 ["lvcreate"; "LV"; "VG"; "20"];
2620 ["lvresize"; "/dev/VG/LV"; "10"]])],
2621 "resize an LVM logical volume",
2623 This resizes (expands or shrinks) an existing LVM logical
2624 volume to C<mbytes>. When reducing, data in the reduced part
2627 ("resize2fs", (RErr, [Device "device"]), 106, [],
2628 [], (* lvresize tests this *)
2629 "resize an ext2/ext3 filesystem",
2631 This resizes an ext2 or ext3 filesystem to match the size of
2632 the underlying device.
2634 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2635 on the C<device> before calling this command. For unknown reasons
2636 C<resize2fs> sometimes gives an error about this and sometimes not.
2637 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2638 calling this function.");
2640 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2641 [InitBasicFS, Always, TestOutputList (
2642 [["find"; "/"]], ["lost+found"]);
2643 InitBasicFS, Always, TestOutputList (
2647 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2648 InitBasicFS, Always, TestOutputList (
2649 [["mkdir_p"; "/a/b/c"];
2650 ["touch"; "/a/b/c/d"];
2651 ["find"; "/a/b/"]], ["c"; "c/d"])],
2652 "find all files and directories",
2654 This command lists out all files and directories, recursively,
2655 starting at C<directory>. It is essentially equivalent to
2656 running the shell command C<find directory -print> but some
2657 post-processing happens on the output, described below.
2659 This returns a list of strings I<without any prefix>. Thus
2660 if the directory structure was:
2666 then the returned list from C<guestfs_find> C</tmp> would be
2674 If C<directory> is not a directory, then this command returns
2677 The returned list is sorted.
2679 See also C<guestfs_find0>.");
2681 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2682 [], (* lvresize tests this *)
2683 "check an ext2/ext3 filesystem",
2685 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2686 filesystem checker on C<device>, noninteractively (C<-p>),
2687 even if the filesystem appears to be clean (C<-f>).
2689 This command is only needed because of C<guestfs_resize2fs>
2690 (q.v.). Normally you should use C<guestfs_fsck>.");
2692 ("sleep", (RErr, [Int "secs"]), 109, [],
2693 [InitNone, Always, TestRun (
2695 "sleep for some seconds",
2697 Sleep for C<secs> seconds.");
2699 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2700 [InitNone, Always, TestOutputInt (
2701 [["part_disk"; "/dev/sda"; "mbr"];
2702 ["mkfs"; "ntfs"; "/dev/sda1"];
2703 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2704 InitNone, Always, TestOutputInt (
2705 [["part_disk"; "/dev/sda"; "mbr"];
2706 ["mkfs"; "ext2"; "/dev/sda1"];
2707 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2708 "probe NTFS volume",
2710 This command runs the L<ntfs-3g.probe(8)> command which probes
2711 an NTFS C<device> for mountability. (Not all NTFS volumes can
2712 be mounted read-write, and some cannot be mounted at all).
2714 C<rw> is a boolean flag. Set it to true if you want to test
2715 if the volume can be mounted read-write. Set it to false if
2716 you want to test if the volume can be mounted read-only.
2718 The return value is an integer which C<0> if the operation
2719 would succeed, or some non-zero value documented in the
2720 L<ntfs-3g.probe(8)> manual page.");
2722 ("sh", (RString "output", [String "command"]), 111, [],
2723 [], (* XXX needs tests *)
2724 "run a command via the shell",
2726 This call runs a command from the guest filesystem via the
2729 This is like C<guestfs_command>, but passes the command to:
2731 /bin/sh -c \"command\"
2733 Depending on the guest's shell, this usually results in
2734 wildcards being expanded, shell expressions being interpolated
2737 All the provisos about C<guestfs_command> apply to this call.");
2739 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2740 [], (* XXX needs tests *)
2741 "run a command via the shell returning lines",
2743 This is the same as C<guestfs_sh>, but splits the result
2744 into a list of lines.
2746 See also: C<guestfs_command_lines>");
2748 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2749 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2750 * code in stubs.c, since all valid glob patterns must start with "/".
2751 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2753 [InitBasicFS, Always, TestOutputList (
2754 [["mkdir_p"; "/a/b/c"];
2755 ["touch"; "/a/b/c/d"];
2756 ["touch"; "/a/b/c/e"];
2757 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758 InitBasicFS, Always, TestOutputList (
2759 [["mkdir_p"; "/a/b/c"];
2760 ["touch"; "/a/b/c/d"];
2761 ["touch"; "/a/b/c/e"];
2762 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2763 InitBasicFS, Always, TestOutputList (
2764 [["mkdir_p"; "/a/b/c"];
2765 ["touch"; "/a/b/c/d"];
2766 ["touch"; "/a/b/c/e"];
2767 ["glob_expand"; "/a/*/x/*"]], [])],
2768 "expand a wildcard path",
2770 This command searches for all the pathnames matching
2771 C<pattern> according to the wildcard expansion rules
2774 If no paths match, then this returns an empty list
2775 (note: not an error).
2777 It is just a wrapper around the C L<glob(3)> function
2778 with flags C<GLOB_MARK|GLOB_BRACE>.
2779 See that manual page for more details.");
2781 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2782 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2783 [["scrub_device"; "/dev/sdc"]])],
2784 "scrub (securely wipe) a device",
2786 This command writes patterns over C<device> to make data retrieval
2789 It is an interface to the L<scrub(1)> program. See that
2790 manual page for more details.");
2792 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2793 [InitBasicFS, Always, TestRun (
2794 [["write_file"; "/file"; "content"; "0"];
2795 ["scrub_file"; "/file"]])],
2796 "scrub (securely wipe) a file",
2798 This command writes patterns over a file to make data retrieval
2801 The file is I<removed> after scrubbing.
2803 It is an interface to the L<scrub(1)> program. See that
2804 manual page for more details.");
2806 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2807 [], (* XXX needs testing *)
2808 "scrub (securely wipe) free space",
2810 This command creates the directory C<dir> and then fills it
2811 with files until the filesystem is full, and scrubs the files
2812 as for C<guestfs_scrub_file>, and deletes them.
2813 The intention is to scrub any free space on the partition
2816 It is an interface to the L<scrub(1)> program. See that
2817 manual page for more details.");
2819 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2820 [InitBasicFS, Always, TestRun (
2822 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2823 "create a temporary directory",
2825 This command creates a temporary directory. The
2826 C<template> parameter should be a full pathname for the
2827 temporary directory name with the final six characters being
2830 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2831 the second one being suitable for Windows filesystems.
2833 The name of the temporary directory that was created
2836 The temporary directory is created with mode 0700
2837 and is owned by root.
2839 The caller is responsible for deleting the temporary
2840 directory and its contents after use.
2842 See also: L<mkdtemp(3)>");
2844 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2845 [InitISOFS, Always, TestOutputInt (
2846 [["wc_l"; "/10klines"]], 10000)],
2847 "count lines in a file",
2849 This command counts the lines in a file, using the
2850 C<wc -l> external command.");
2852 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2853 [InitISOFS, Always, TestOutputInt (
2854 [["wc_w"; "/10klines"]], 10000)],
2855 "count words in a file",
2857 This command counts the words in a file, using the
2858 C<wc -w> external command.");
2860 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2861 [InitISOFS, Always, TestOutputInt (
2862 [["wc_c"; "/100kallspaces"]], 102400)],
2863 "count characters in a file",
2865 This command counts the characters in a file, using the
2866 C<wc -c> external command.");
2868 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2869 [InitISOFS, Always, TestOutputList (
2870 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2871 "return first 10 lines of a file",
2873 This command returns up to the first 10 lines of a file as
2874 a list of strings.");
2876 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2877 [InitISOFS, Always, TestOutputList (
2878 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2879 InitISOFS, Always, TestOutputList (
2880 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881 InitISOFS, Always, TestOutputList (
2882 [["head_n"; "0"; "/10klines"]], [])],
2883 "return first N lines of a file",
2885 If the parameter C<nrlines> is a positive number, this returns the first
2886 C<nrlines> lines of the file C<path>.
2888 If the parameter C<nrlines> is a negative number, this returns lines
2889 from the file C<path>, excluding the last C<nrlines> lines.
2891 If the parameter C<nrlines> is zero, this returns an empty list.");
2893 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2894 [InitISOFS, Always, TestOutputList (
2895 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2896 "return last 10 lines of a file",
2898 This command returns up to the last 10 lines of a file as
2899 a list of strings.");
2901 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2902 [InitISOFS, Always, TestOutputList (
2903 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2904 InitISOFS, Always, TestOutputList (
2905 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906 InitISOFS, Always, TestOutputList (
2907 [["tail_n"; "0"; "/10klines"]], [])],
2908 "return last N lines of a file",
2910 If the parameter C<nrlines> is a positive number, this returns the last
2911 C<nrlines> lines of the file C<path>.
2913 If the parameter C<nrlines> is a negative number, this returns lines
2914 from the file C<path>, starting with the C<-nrlines>th line.
2916 If the parameter C<nrlines> is zero, this returns an empty list.");
2918 ("df", (RString "output", []), 125, [],
2919 [], (* XXX Tricky to test because it depends on the exact format
2920 * of the 'df' command and other imponderables.
2922 "report file system disk space usage",
2924 This command runs the C<df> command to report disk space used.
2926 This command is mostly useful for interactive sessions. It
2927 is I<not> intended that you try to parse the output string.
2928 Use C<statvfs> from programs.");
2930 ("df_h", (RString "output", []), 126, [],
2931 [], (* XXX Tricky to test because it depends on the exact format
2932 * of the 'df' command and other imponderables.
2934 "report file system disk space usage (human readable)",
2936 This command runs the C<df -h> command to report disk space used
2937 in human-readable format.
2939 This command is mostly useful for interactive sessions. It
2940 is I<not> intended that you try to parse the output string.
2941 Use C<statvfs> from programs.");
2943 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2944 [InitISOFS, Always, TestOutputInt (
2945 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2946 "estimate file space usage",
2948 This command runs the C<du -s> command to estimate file space
2951 C<path> can be a file or a directory. If C<path> is a directory
2952 then the estimate includes the contents of the directory and all
2953 subdirectories (recursively).
2955 The result is the estimated size in I<kilobytes>
2956 (ie. units of 1024 bytes).");
2958 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2959 [InitISOFS, Always, TestOutputList (
2960 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2961 "list files in an initrd",
2963 This command lists out files contained in an initrd.
2965 The files are listed without any initial C</> character. The
2966 files are listed in the order they appear (not necessarily
2967 alphabetical). Directory names are listed as separate items.
2969 Old Linux kernels (2.4 and earlier) used a compressed ext2
2970 filesystem as initrd. We I<only> support the newer initramfs
2971 format (compressed cpio files).");
2973 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2975 "mount a file using the loop device",
2977 This command lets you mount C<file> (a filesystem image
2978 in a file) on a mount point. It is entirely equivalent to
2979 the command C<mount -o loop file mountpoint>.");
2981 ("mkswap", (RErr, [Device "device"]), 130, [],
2982 [InitEmpty, Always, TestRun (
2983 [["part_disk"; "/dev/sda"; "mbr"];
2984 ["mkswap"; "/dev/sda1"]])],
2985 "create a swap partition",
2987 Create a swap partition on C<device>.");
2989 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2990 [InitEmpty, Always, TestRun (
2991 [["part_disk"; "/dev/sda"; "mbr"];
2992 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2993 "create a swap partition with a label",
2995 Create a swap partition on C<device> with label C<label>.
2997 Note that you cannot attach a swap label to a block device
2998 (eg. C</dev/sda>), just to a partition. This appears to be
2999 a limitation of the kernel or swap tools.");
3001 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3002 (let uuid = uuidgen () in
3003 [InitEmpty, Always, TestRun (
3004 [["part_disk"; "/dev/sda"; "mbr"];
3005 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3006 "create a swap partition with an explicit UUID",
3008 Create a swap partition on C<device> with UUID C<uuid>.");
3010 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3011 [InitBasicFS, Always, TestOutputStruct (
3012 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3013 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3014 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3015 InitBasicFS, Always, TestOutputStruct (
3016 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3017 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3018 "make block, character or FIFO devices",
3020 This call creates block or character special devices, or
3021 named pipes (FIFOs).
3023 The C<mode> parameter should be the mode, using the standard
3024 constants. C<devmajor> and C<devminor> are the
3025 device major and minor numbers, only used when creating block
3026 and character special devices.
3028 Note that, just like L<mknod(2)>, the mode must be bitwise
3029 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3030 just creates a regular file). These constants are
3031 available in the standard Linux header files, or you can use
3032 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3033 which are wrappers around this command which bitwise OR
3034 in the appropriate constant for you.
3036 The mode actually set is affected by the umask.");
3038 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3039 [InitBasicFS, Always, TestOutputStruct (
3040 [["mkfifo"; "0o777"; "/node"];
3041 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3042 "make FIFO (named pipe)",
3044 This call creates a FIFO (named pipe) called C<path> with
3045 mode C<mode>. It is just a convenient wrapper around
3048 The mode actually set is affected by the umask.");
3050 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3051 [InitBasicFS, Always, TestOutputStruct (
3052 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3053 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3054 "make block device node",
3056 This call creates a block device node called C<path> with
3057 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3058 It is just a convenient wrapper around C<guestfs_mknod>.
3060 The mode actually set is affected by the umask.");
3062 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3063 [InitBasicFS, Always, TestOutputStruct (
3064 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3065 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3066 "make char device node",
3068 This call creates a char device node called C<path> with
3069 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3070 It is just a convenient wrapper around C<guestfs_mknod>.
3072 The mode actually set is affected by the umask.");
3074 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3075 [InitEmpty, Always, TestOutputInt (
3076 [["umask"; "0o22"]], 0o22)],
3077 "set file mode creation mask (umask)",
3079 This function sets the mask used for creating new files and
3080 device nodes to C<mask & 0777>.
3082 Typical umask values would be C<022> which creates new files
3083 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3084 C<002> which creates new files with permissions like
3085 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3087 The default umask is C<022>. This is important because it
3088 means that directories and device nodes will be created with
3089 C<0644> or C<0755> mode even if you specify C<0777>.
3091 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3093 This call returns the previous umask.");
3095 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3097 "read directories entries",
3099 This returns the list of directory entries in directory C<dir>.
3101 All entries in the directory are returned, including C<.> and
3102 C<..>. The entries are I<not> sorted, but returned in the same
3103 order as the underlying filesystem.
3105 Also this call returns basic file type information about each
3106 file. The C<ftyp> field will contain one of the following characters:
3144 The L<readdir(3)> call returned a C<d_type> field with an
3149 This function is primarily intended for use by programs. To
3150 get a simple list of names, use C<guestfs_ls>. To get a printable
3151 directory for human consumption, use C<guestfs_ll>.");
3153 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3155 "create partitions on a block device",
3157 This is a simplified interface to the C<guestfs_sfdisk>
3158 command, where partition sizes are specified in megabytes
3159 only (rounded to the nearest cylinder) and you don't need
3160 to specify the cyls, heads and sectors parameters which
3161 were rarely if ever used anyway.
3163 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3164 and C<guestfs_part_disk>");
3166 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3168 "determine file type inside a compressed file",
3170 This command runs C<file> after first decompressing C<path>
3173 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3175 Since 1.0.63, use C<guestfs_file> instead which can now
3176 process compressed files.");
3178 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3180 "list extended attributes of a file or directory",
3182 This call lists the extended attributes of the file or directory
3185 At the system call level, this is a combination of the
3186 L<listxattr(2)> and L<getxattr(2)> calls.
3188 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3190 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3192 "list extended attributes of a file or directory",
3194 This is the same as C<guestfs_getxattrs>, but if C<path>
3195 is a symbolic link, then it returns the extended attributes
3196 of the link itself.");
3198 ("setxattr", (RErr, [String "xattr";
3199 String "val"; Int "vallen"; (* will be BufferIn *)
3200 Pathname "path"]), 143, [Optional "linuxxattrs"],
3202 "set extended attribute of a file or directory",
3204 This call sets the extended attribute named C<xattr>
3205 of the file C<path> to the value C<val> (of length C<vallen>).
3206 The value is arbitrary 8 bit data.
3208 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3210 ("lsetxattr", (RErr, [String "xattr";
3211 String "val"; Int "vallen"; (* will be BufferIn *)
3212 Pathname "path"]), 144, [Optional "linuxxattrs"],
3214 "set extended attribute of a file or directory",
3216 This is the same as C<guestfs_setxattr>, but if C<path>
3217 is a symbolic link, then it sets an extended attribute
3218 of the link itself.");
3220 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3222 "remove extended attribute of a file or directory",
3224 This call removes the extended attribute named C<xattr>
3225 of the file C<path>.
3227 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3229 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3231 "remove extended attribute of a file or directory",
3233 This is the same as C<guestfs_removexattr>, but if C<path>
3234 is a symbolic link, then it removes an extended attribute
3235 of the link itself.");
3237 ("mountpoints", (RHashtable "mps", []), 147, [],
3241 This call is similar to C<guestfs_mounts>. That call returns
3242 a list of devices. This one returns a hash table (map) of
3243 device name to directory where the device is mounted.");
3245 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3246 (* This is a special case: while you would expect a parameter
3247 * of type "Pathname", that doesn't work, because it implies
3248 * NEED_ROOT in the generated calling code in stubs.c, and
3249 * this function cannot use NEED_ROOT.
3252 "create a mountpoint",
3254 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3255 specialized calls that can be used to create extra mountpoints
3256 before mounting the first filesystem.
3258 These calls are I<only> necessary in some very limited circumstances,
3259 mainly the case where you want to mount a mix of unrelated and/or
3260 read-only filesystems together.
3262 For example, live CDs often contain a \"Russian doll\" nest of
3263 filesystems, an ISO outer layer, with a squashfs image inside, with
3264 an ext2/3 image inside that. You can unpack this as follows
3267 add-ro Fedora-11-i686-Live.iso
3270 mkmountpoint /squash
3273 mount-loop /cd/LiveOS/squashfs.img /squash
3274 mount-loop /squash/LiveOS/ext3fs.img /ext3
3276 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3278 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3280 "remove a mountpoint",
3282 This calls removes a mountpoint that was previously created
3283 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3284 for full details.");
3286 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3287 [InitISOFS, Always, TestOutputBuffer (
3288 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3289 (* Test various near large, large and too large files (RHBZ#589039). *)
3290 InitBasicFS, Always, TestLastFail (
3292 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3293 ["read_file"; "/a"]]);
3294 InitBasicFS, Always, TestLastFail (
3296 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3297 ["read_file"; "/a"]]);
3298 InitBasicFS, Always, TestLastFail (
3300 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3301 ["read_file"; "/a"]])],
3304 This calls returns the contents of the file C<path> as a
3307 Unlike C<guestfs_cat>, this function can correctly
3308 handle files that contain embedded ASCII NUL characters.
3309 However unlike C<guestfs_download>, this function is limited
3310 in the total size of file that can be handled.");
3312 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3313 [InitISOFS, Always, TestOutputList (
3314 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3315 InitISOFS, Always, TestOutputList (
3316 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3317 "return lines matching a pattern",
3319 This calls the external C<grep> program and returns the
3322 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3323 [InitISOFS, Always, TestOutputList (
3324 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3325 "return lines matching a pattern",
3327 This calls the external C<egrep> program and returns the
3330 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3331 [InitISOFS, Always, TestOutputList (
3332 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3333 "return lines matching a pattern",
3335 This calls the external C<fgrep> program and returns the
3338 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3339 [InitISOFS, Always, TestOutputList (
3340 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3341 "return lines matching a pattern",
3343 This calls the external C<grep -i> program and returns the
3346 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3347 [InitISOFS, Always, TestOutputList (
3348 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3349 "return lines matching a pattern",
3351 This calls the external C<egrep -i> program and returns the
3354 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3355 [InitISOFS, Always, TestOutputList (
3356 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3357 "return lines matching a pattern",
3359 This calls the external C<fgrep -i> program and returns the
3362 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3363 [InitISOFS, Always, TestOutputList (
3364 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3365 "return lines matching a pattern",
3367 This calls the external C<zgrep> program and returns the
3370 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3371 [InitISOFS, Always, TestOutputList (
3372 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3373 "return lines matching a pattern",
3375 This calls the external C<zegrep> program and returns the
3378 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3379 [InitISOFS, Always, TestOutputList (
3380 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3381 "return lines matching a pattern",
3383 This calls the external C<zfgrep> program and returns the
3386 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3387 [InitISOFS, Always, TestOutputList (
3388 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3389 "return lines matching a pattern",
3391 This calls the external C<zgrep -i> program and returns the
3394 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3395 [InitISOFS, Always, TestOutputList (
3396 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3397 "return lines matching a pattern",
3399 This calls the external C<zegrep -i> program and returns the
3402 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3403 [InitISOFS, Always, TestOutputList (
3404 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3405 "return lines matching a pattern",
3407 This calls the external C<zfgrep -i> program and returns the
3410 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3411 [InitISOFS, Always, TestOutput (
3412 [["realpath"; "/../directory"]], "/directory")],
3413 "canonicalized absolute pathname",
3415 Return the canonicalized absolute pathname of C<path>. The
3416 returned path has no C<.>, C<..> or symbolic link path elements.");
3418 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3419 [InitBasicFS, Always, TestOutputStruct (
3422 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3423 "create a hard link",
3425 This command creates a hard link using the C<ln> command.");
3427 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3428 [InitBasicFS, Always, TestOutputStruct (
3431 ["ln_f"; "/a"; "/b"];
3432 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3433 "create a hard link",
3435 This command creates a hard link using the C<ln -f> command.
3436 The C<-f> option removes the link (C<linkname>) if it exists already.");
3438 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3439 [InitBasicFS, Always, TestOutputStruct (
3441 ["ln_s"; "a"; "/b"];
3442 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3443 "create a symbolic link",
3445 This command creates a symbolic link using the C<ln -s> command.");
3447 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3448 [InitBasicFS, Always, TestOutput (
3449 [["mkdir_p"; "/a/b"];
3450 ["touch"; "/a/b/c"];
3451 ["ln_sf"; "../d"; "/a/b/c"];
3452 ["readlink"; "/a/b/c"]], "../d")],
3453 "create a symbolic link",
3455 This command creates a symbolic link using the C<ln -sf> command,
3456 The C<-f> option removes the link (C<linkname>) if it exists already.");
3458 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3459 [] (* XXX tested above *),
3460 "read the target of a symbolic link",
3462 This command reads the target of a symbolic link.");
3464 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3465 [InitBasicFS, Always, TestOutputStruct (
3466 [["fallocate"; "/a"; "1000000"];
3467 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3468 "preallocate a file in the guest filesystem",
3470 This command preallocates a file (containing zero bytes) named
3471 C<path> of size C<len> bytes. If the file exists already, it
3474 Do not confuse this with the guestfish-specific
3475 C<alloc> command which allocates a file in the host and
3476 attaches it as a device.");
3478 ("swapon_device", (RErr, [Device "device"]), 170, [],
3479 [InitPartition, Always, TestRun (
3480 [["mkswap"; "/dev/sda1"];
3481 ["swapon_device"; "/dev/sda1"];
3482 ["swapoff_device"; "/dev/sda1"]])],
3483 "enable swap on device",
3485 This command enables the libguestfs appliance to use the
3486 swap device or partition named C<device>. The increased
3487 memory is made available for all commands, for example
3488 those run using C<guestfs_command> or C<guestfs_sh>.
3490 Note that you should not swap to existing guest swap
3491 partitions unless you know what you are doing. They may
3492 contain hibernation information, or other information that
3493 the guest doesn't want you to trash. You also risk leaking
3494 information about the host to the guest this way. Instead,
3495 attach a new host device to the guest and swap on that.");
3497 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3498 [], (* XXX tested by swapon_device *)
3499 "disable swap on device",
3501 This command disables the libguestfs appliance swap
3502 device or partition named C<device>.
3503 See C<guestfs_swapon_device>.");
3505 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3506 [InitBasicFS, Always, TestRun (
3507 [["fallocate"; "/swap"; "8388608"];
3508 ["mkswap_file"; "/swap"];
3509 ["swapon_file"; "/swap"];
3510 ["swapoff_file"; "/swap"]])],
3511 "enable swap on file",
3513 This command enables swap to a file.
3514 See C<guestfs_swapon_device> for other notes.");
3516 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3517 [], (* XXX tested by swapon_file *)
3518 "disable swap on file",
3520 This command disables the libguestfs appliance swap on file.");
3522 ("swapon_label", (RErr, [String "label"]), 174, [],
3523 [InitEmpty, Always, TestRun (
3524 [["part_disk"; "/dev/sdb"; "mbr"];
3525 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3526 ["swapon_label"; "swapit"];
3527 ["swapoff_label"; "swapit"];
3528 ["zero"; "/dev/sdb"];
3529 ["blockdev_rereadpt"; "/dev/sdb"]])],
3530 "enable swap on labeled swap partition",
3532 This command enables swap to a labeled swap partition.
3533 See C<guestfs_swapon_device> for other notes.");
3535 ("swapoff_label", (RErr, [String "label"]), 175, [],
3536 [], (* XXX tested by swapon_label *)
3537 "disable swap on labeled swap partition",
3539 This command disables the libguestfs appliance swap on
3540 labeled swap partition.");
3542 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3543 (let uuid = uuidgen () in
3544 [InitEmpty, Always, TestRun (
3545 [["mkswap_U"; uuid; "/dev/sdb"];
3546 ["swapon_uuid"; uuid];
3547 ["swapoff_uuid"; uuid]])]),
3548 "enable swap on swap partition by UUID",
3550 This command enables swap to a swap partition with the given UUID.
3551 See C<guestfs_swapon_device> for other notes.");
3553 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3554 [], (* XXX tested by swapon_uuid *)
3555 "disable swap on swap partition by UUID",
3557 This command disables the libguestfs appliance swap partition
3558 with the given UUID.");
3560 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3561 [InitBasicFS, Always, TestRun (
3562 [["fallocate"; "/swap"; "8388608"];
3563 ["mkswap_file"; "/swap"]])],
3564 "create a swap file",
3568 This command just writes a swap file signature to an existing
3569 file. To create the file itself, use something like C<guestfs_fallocate>.");
3571 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3572 [InitISOFS, Always, TestRun (
3573 [["inotify_init"; "0"]])],
3574 "create an inotify handle",
3576 This command creates a new inotify handle.
3577 The inotify subsystem can be used to notify events which happen to
3578 objects in the guest filesystem.
3580 C<maxevents> is the maximum number of events which will be
3581 queued up between calls to C<guestfs_inotify_read> or
3582 C<guestfs_inotify_files>.
3583 If this is passed as C<0>, then the kernel (or previously set)
3584 default is used. For Linux 2.6.29 the default was 16384 events.
3585 Beyond this limit, the kernel throws away events, but records
3586 the fact that it threw them away by setting a flag
3587 C<IN_Q_OVERFLOW> in the returned structure list (see
3588 C<guestfs_inotify_read>).
3590 Before any events are generated, you have to add some
3591 watches to the internal watch list. See:
3592 C<guestfs_inotify_add_watch>,
3593 C<guestfs_inotify_rm_watch> and
3594 C<guestfs_inotify_watch_all>.
3596 Queued up events should be read periodically by calling
3597 C<guestfs_inotify_read>
3598 (or C<guestfs_inotify_files> which is just a helpful
3599 wrapper around C<guestfs_inotify_read>). If you don't
3600 read the events out often enough then you risk the internal
3603 The handle should be closed after use by calling
3604 C<guestfs_inotify_close>. This also removes any
3605 watches automatically.
3607 See also L<inotify(7)> for an overview of the inotify interface
3608 as exposed by the Linux kernel, which is roughly what we expose
3609 via libguestfs. Note that there is one global inotify handle
3610 per libguestfs instance.");
3612 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3613 [InitBasicFS, Always, TestOutputList (
3614 [["inotify_init"; "0"];
3615 ["inotify_add_watch"; "/"; "1073741823"];
3618 ["inotify_files"]], ["a"; "b"])],
3619 "add an inotify watch",
3621 Watch C<path> for the events listed in C<mask>.
3623 Note that if C<path> is a directory then events within that
3624 directory are watched, but this does I<not> happen recursively
3625 (in subdirectories).
3627 Note for non-C or non-Linux callers: the inotify events are
3628 defined by the Linux kernel ABI and are listed in
3629 C</usr/include/sys/inotify.h>.");
3631 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3633 "remove an inotify watch",
3635 Remove a previously defined inotify watch.
3636 See C<guestfs_inotify_add_watch>.");
3638 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3640 "return list of inotify events",
3642 Return the complete queue of events that have happened
3643 since the previous read call.
3645 If no events have happened, this returns an empty list.
3647 I<Note>: In order to make sure that all events have been
3648 read, you must call this function repeatedly until it
3649 returns an empty list. The reason is that the call will
3650 read events up to the maximum appliance-to-host message
3651 size and leave remaining events in the queue.");
3653 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3655 "return list of watched files that had events",
3657 This function is a helpful wrapper around C<guestfs_inotify_read>
3658 which just returns a list of pathnames of objects that were
3659 touched. The returned pathnames are sorted and deduplicated.");
3661 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3663 "close the inotify handle",
3665 This closes the inotify handle which was previously
3666 opened by inotify_init. It removes all watches, throws
3667 away any pending events, and deallocates all resources.");
3669 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3671 "set SELinux security context",
3673 This sets the SELinux security context of the daemon
3674 to the string C<context>.
3676 See the documentation about SELINUX in L<guestfs(3)>.");
3678 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3680 "get SELinux security context",
3682 This gets the SELinux security context of the daemon.
3684 See the documentation about SELINUX in L<guestfs(3)>,
3685 and C<guestfs_setcon>");
3687 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3688 [InitEmpty, Always, TestOutput (
3689 [["part_disk"; "/dev/sda"; "mbr"];
3690 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3691 ["mount_options"; ""; "/dev/sda1"; "/"];
3692 ["write_file"; "/new"; "new file contents"; "0"];
3693 ["cat"; "/new"]], "new file contents")],
3694 "make a filesystem with block size",
3696 This call is similar to C<guestfs_mkfs>, but it allows you to
3697 control the block size of the resulting filesystem. Supported
3698 block sizes depend on the filesystem type, but typically they
3699 are C<1024>, C<2048> or C<4096> only.");
3701 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3702 [InitEmpty, Always, TestOutput (
3703 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3704 ["mke2journal"; "4096"; "/dev/sda1"];
3705 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3706 ["mount_options"; ""; "/dev/sda2"; "/"];
3707 ["write_file"; "/new"; "new file contents"; "0"];
3708 ["cat"; "/new"]], "new file contents")],
3709 "make ext2/3/4 external journal",
3711 This creates an ext2 external journal on C<device>. It is equivalent
3714 mke2fs -O journal_dev -b blocksize device");
3716 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3717 [InitEmpty, Always, TestOutput (
3718 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3719 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3720 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3721 ["mount_options"; ""; "/dev/sda2"; "/"];
3722 ["write_file"; "/new"; "new file contents"; "0"];
3723 ["cat"; "/new"]], "new file contents")],
3724 "make ext2/3/4 external journal with label",
3726 This creates an ext2 external journal on C<device> with label C<label>.");
3728 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3729 (let uuid = uuidgen () in
3730 [InitEmpty, Always, TestOutput (
3731 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3732 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3733 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3734 ["mount_options"; ""; "/dev/sda2"; "/"];
3735 ["write_file"; "/new"; "new file contents"; "0"];
3736 ["cat"; "/new"]], "new file contents")]),
3737 "make ext2/3/4 external journal with UUID",
3739 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3741 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3743 "make ext2/3/4 filesystem with external journal",
3745 This creates an ext2/3/4 filesystem on C<device> with
3746 an external journal on C<journal>. It is equivalent
3749 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3751 See also C<guestfs_mke2journal>.");
3753 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3755 "make ext2/3/4 filesystem with external journal",
3757 This creates an ext2/3/4 filesystem on C<device> with
3758 an external journal on the journal labeled C<label>.
3760 See also C<guestfs_mke2journal_L>.");
3762 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3764 "make ext2/3/4 filesystem with external journal",
3766 This creates an ext2/3/4 filesystem on C<device> with
3767 an external journal on the journal with UUID C<uuid>.
3769 See also C<guestfs_mke2journal_U>.");
3771 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3772 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3773 "load a kernel module",
3775 This loads a kernel module in the appliance.
3777 The kernel module must have been whitelisted when libguestfs
3778 was built (see C<appliance/kmod.whitelist.in> in the source).");
3780 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3781 [InitNone, Always, TestOutput (
3782 [["echo_daemon"; "This is a test"]], "This is a test"
3784 "echo arguments back to the client",
3786 This command concatenates the list of C<words> passed with single spaces
3787 between them and returns the resulting string.
3789 You can use this command to test the connection through to the daemon.
3791 See also C<guestfs_ping_daemon>.");
3793 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3794 [], (* There is a regression test for this. *)
3795 "find all files and directories, returning NUL-separated list",
3797 This command lists out all files and directories, recursively,
3798 starting at C<directory>, placing the resulting list in the
3799 external file called C<files>.
3801 This command works the same way as C<guestfs_find> with the
3802 following exceptions:
3808 The resulting list is written to an external file.
3812 Items (filenames) in the result are separated
3813 by C<\\0> characters. See L<find(1)> option I<-print0>.
3817 This command is not limited in the number of names that it
3822 The result list is not sorted.
3826 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3827 [InitISOFS, Always, TestOutput (
3828 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3829 InitISOFS, Always, TestOutput (
3830 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3831 InitISOFS, Always, TestOutput (
3832 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3833 InitISOFS, Always, TestLastFail (
3834 [["case_sensitive_path"; "/Known-1/"]]);
3835 InitBasicFS, Always, TestOutput (
3837 ["mkdir"; "/a/bbb"];
3838 ["touch"; "/a/bbb/c"];
3839 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3840 InitBasicFS, Always, TestOutput (
3842 ["mkdir"; "/a/bbb"];
3843 ["touch"; "/a/bbb/c"];
3844 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3845 InitBasicFS, Always, TestLastFail (
3847 ["mkdir"; "/a/bbb"];
3848 ["touch"; "/a/bbb/c"];
3849 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3850 "return true path on case-insensitive filesystem",
3852 This can be used to resolve case insensitive paths on
3853 a filesystem which is case sensitive. The use case is
3854 to resolve paths which you have read from Windows configuration
3855 files or the Windows Registry, to the true path.
3857 The command handles a peculiarity of the Linux ntfs-3g
3858 filesystem driver (and probably others), which is that although
3859 the underlying filesystem is case-insensitive, the driver
3860 exports the filesystem to Linux as case-sensitive.
3862 One consequence of this is that special directories such
3863 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3864 (or other things) depending on the precise details of how
3865 they were created. In Windows itself this would not be
3868 Bug or feature? You decide:
3869 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3871 This function resolves the true case of each element in the
3872 path and returns the case-sensitive path.
3874 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3875 might return C<\"/WINDOWS/system32\"> (the exact return value
3876 would depend on details of how the directories were originally
3877 created under Windows).
3880 This function does not handle drive names, backslashes etc.
3882 See also C<guestfs_realpath>.");
3884 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3885 [InitBasicFS, Always, TestOutput (
3886 [["vfs_type"; "/dev/sda1"]], "ext2")],
3887 "get the Linux VFS type corresponding to a mounted device",
3889 This command gets the block device type corresponding to
3890 a mounted device called C<device>.
3892 Usually the result is the name of the Linux VFS module that
3893 is used to mount this device (probably determined automatically
3894 if you used the C<guestfs_mount> call).");
3896 ("truncate", (RErr, [Pathname "path"]), 199, [],
3897 [InitBasicFS, Always, TestOutputStruct (
3898 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3899 ["truncate"; "/test"];
3900 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3901 "truncate a file to zero size",
3903 This command truncates C<path> to a zero-length file. The
3904 file must exist already.");
3906 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3907 [InitBasicFS, Always, TestOutputStruct (
3908 [["touch"; "/test"];
3909 ["truncate_size"; "/test"; "1000"];
3910 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3911 "truncate a file to a particular size",
3913 This command truncates C<path> to size C<size> bytes. The file
3916 If the current file size is less than C<size> then
3917 the file is extended to the required size with zero bytes.
3918 This creates a sparse file (ie. disk blocks are not allocated
3919 for the file until you write to it). To create a non-sparse
3920 file of zeroes, use C<guestfs_fallocate64> instead.");
3922 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3923 [InitBasicFS, Always, TestOutputStruct (
3924 [["touch"; "/test"];
3925 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3926 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3927 "set timestamp of a file with nanosecond precision",
3929 This command sets the timestamps of a file with nanosecond
3932 C<atsecs, atnsecs> are the last access time (atime) in secs and
3933 nanoseconds from the epoch.
3935 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3936 secs and nanoseconds from the epoch.
3938 If the C<*nsecs> field contains the special value C<-1> then
3939 the corresponding timestamp is set to the current time. (The
3940 C<*secs> field is ignored in this case).
3942 If the C<*nsecs> field contains the special value C<-2> then
3943 the corresponding timestamp is left unchanged. (The
3944 C<*secs> field is ignored in this case).");
3946 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3947 [InitBasicFS, Always, TestOutputStruct (
3948 [["mkdir_mode"; "/test"; "0o111"];
3949 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3950 "create a directory with a particular mode",
3952 This command creates a directory, setting the initial permissions
3953 of the directory to C<mode>.
3955 For common Linux filesystems, the actual mode which is set will
3956 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3957 interpret the mode in other ways.
3959 See also C<guestfs_mkdir>, C<guestfs_umask>");
3961 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3963 "change file owner and group",
3965 Change the file owner to C<owner> and group to C<group>.
3966 This is like C<guestfs_chown> but if C<path> is a symlink then
3967 the link itself is changed, not the target.
3969 Only numeric uid and gid are supported. If you want to use
3970 names, you will need to locate and parse the password file
3971 yourself (Augeas support makes this relatively easy).");
3973 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3975 "lstat on multiple files",
3977 This call allows you to perform the C<guestfs_lstat> operation
3978 on multiple files, where all files are in the directory C<path>.
3979 C<names> is the list of files from this directory.
3981 On return you get a list of stat structs, with a one-to-one
3982 correspondence to the C<names> list. If any name did not exist
3983 or could not be lstat'd, then the C<ino> field of that structure
3986 This call is intended for programs that want to efficiently
3987 list a directory contents without making many round-trips.
3988 See also C<guestfs_lxattrlist> for a similarly efficient call
3989 for getting extended attributes. Very long directory listings
3990 might cause the protocol message size to be exceeded, causing
3991 this call to fail. The caller must split up such requests
3992 into smaller groups of names.");
3994 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3996 "lgetxattr on multiple files",
3998 This call allows you to get the extended attributes
3999 of multiple files, where all files are in the directory C<path>.
4000 C<names> is the list of files from this directory.
4002 On return you get a flat list of xattr structs which must be
4003 interpreted sequentially. The first xattr struct always has a zero-length
4004 C<attrname>. C<attrval> in this struct is zero-length
4005 to indicate there was an error doing C<lgetxattr> for this
4006 file, I<or> is a C string which is a decimal number
4007 (the number of following attributes for this file, which could
4008 be C<\"0\">). Then after the first xattr struct are the
4009 zero or more attributes for the first named file.
4010 This repeats for the second and subsequent files.
4012 This call is intended for programs that want to efficiently
4013 list a directory contents without making many round-trips.
4014 See also C<guestfs_lstatlist> for a similarly efficient call
4015 for getting standard stats. Very long directory listings
4016 might cause the protocol message size to be exceeded, causing
4017 this call to fail. The caller must split up such requests
4018 into smaller groups of names.");
4020 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4022 "readlink on multiple files",
4024 This call allows you to do a C<readlink> operation
4025 on multiple files, where all files are in the directory C<path>.
4026 C<names> is the list of files from this directory.
4028 On return you get a list of strings, with a one-to-one
4029 correspondence to the C<names> list. Each string is the
4030 value of the symbolic link.
4032 If the C<readlink(2)> operation fails on any name, then
4033 the corresponding result string is the empty string C<\"\">.
4034 However the whole operation is completed even if there
4035 were C<readlink(2)> errors, and so you can call this
4036 function with names where you don't know if they are
4037 symbolic links already (albeit slightly less efficient).
4039 This call is intended for programs that want to efficiently
4040 list a directory contents without making many round-trips.
4041 Very long directory listings might cause the protocol
4042 message size to be exceeded, causing
4043 this call to fail. The caller must split up such requests
4044 into smaller groups of names.");
4046 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4047 [InitISOFS, Always, TestOutputBuffer (
4048 [["pread"; "/known-4"; "1"; "3"]], "\n");
4049 InitISOFS, Always, TestOutputBuffer (
4050 [["pread"; "/empty"; "0"; "100"]], "")],
4051 "read part of a file",
4053 This command lets you read part of a file. It reads C<count>
4054 bytes of the file, starting at C<offset>, from file C<path>.
4056 This may read fewer bytes than requested. For further details
4057 see the L<pread(2)> system call.");
4059 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4060 [InitEmpty, Always, TestRun (
4061 [["part_init"; "/dev/sda"; "gpt"]])],
4062 "create an empty partition table",
4064 This creates an empty partition table on C<device> of one of the
4065 partition types listed below. Usually C<parttype> should be
4066 either C<msdos> or C<gpt> (for large disks).
4068 Initially there are no partitions. Following this, you should
4069 call C<guestfs_part_add> for each partition required.
4071 Possible values for C<parttype> are:
4075 =item B<efi> | B<gpt>
4077 Intel EFI / GPT partition table.
4079 This is recommended for >= 2 TB partitions that will be accessed
4080 from Linux and Intel-based Mac OS X. It also has limited backwards
4081 compatibility with the C<mbr> format.
4083 =item B<mbr> | B<msdos>
4085 The standard PC \"Master Boot Record\" (MBR) format used
4086 by MS-DOS and Windows. This partition type will B<only> work
4087 for device sizes up to 2 TB. For large disks we recommend
4092 Other partition table types that may work but are not
4101 =item B<amiga> | B<rdb>
4103 Amiga \"Rigid Disk Block\" format.
4111 DASD, used on IBM mainframes.
4119 Old Mac partition format. Modern Macs use C<gpt>.
4123 NEC PC-98 format, common in Japan apparently.
4131 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4132 [InitEmpty, Always, TestRun (
4133 [["part_init"; "/dev/sda"; "mbr"];
4134 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4135 InitEmpty, Always, TestRun (
4136 [["part_init"; "/dev/sda"; "gpt"];
4137 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4138 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4139 InitEmpty, Always, TestRun (
4140 [["part_init"; "/dev/sda"; "mbr"];
4141 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4142 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4143 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4144 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4145 "add a partition to the device",
4147 This command adds a partition to C<device>. If there is no partition
4148 table on the device, call C<guestfs_part_init> first.
4150 The C<prlogex> parameter is the type of partition. Normally you
4151 should pass C<p> or C<primary> here, but MBR partition tables also
4152 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4155 C<startsect> and C<endsect> are the start and end of the partition
4156 in I<sectors>. C<endsect> may be negative, which means it counts
4157 backwards from the end of the disk (C<-1> is the last sector).
4159 Creating a partition which covers the whole disk is not so easy.
4160 Use C<guestfs_part_disk> to do that.");
4162 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4163 [InitEmpty, Always, TestRun (
4164 [["part_disk"; "/dev/sda"; "mbr"]]);
4165 InitEmpty, Always, TestRun (
4166 [["part_disk"; "/dev/sda"; "gpt"]])],
4167 "partition whole disk with a single primary partition",
4169 This command is simply a combination of C<guestfs_part_init>
4170 followed by C<guestfs_part_add> to create a single primary partition
4171 covering the whole disk.
4173 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4174 but other possible values are described in C<guestfs_part_init>.");
4176 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4177 [InitEmpty, Always, TestRun (
4178 [["part_disk"; "/dev/sda"; "mbr"];
4179 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4180 "make a partition bootable",
4182 This sets the bootable flag on partition numbered C<partnum> on
4183 device C<device>. Note that partitions are numbered from 1.
4185 The bootable flag is used by some operating systems (notably
4186 Windows) to determine which partition to boot from. It is by
4187 no means universally recognized.");
4189 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4190 [InitEmpty, Always, TestRun (
4191 [["part_disk"; "/dev/sda"; "gpt"];
4192 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4193 "set partition name",
4195 This sets the partition name on partition numbered C<partnum> on
4196 device C<device>. Note that partitions are numbered from 1.
4198 The partition name can only be set on certain types of partition
4199 table. This works on C<gpt> but not on C<mbr> partitions.");
4201 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4202 [], (* XXX Add a regression test for this. *)
4203 "list partitions on a device",
4205 This command parses the partition table on C<device> and
4206 returns the list of partitions found.
4208 The fields in the returned structure are:
4214 Partition number, counting from 1.
4218 Start of the partition I<in bytes>. To get sectors you have to
4219 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4223 End of the partition in bytes.
4227 Size of the partition in bytes.
4231 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4232 [InitEmpty, Always, TestOutput (
4233 [["part_disk"; "/dev/sda"; "gpt"];
4234 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4235 "get the partition table type",
4237 This command examines the partition table on C<device> and
4238 returns the partition table type (format) being used.
4240 Common return values include: C<msdos> (a DOS/Windows style MBR
4241 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4242 values are possible, although unusual. See C<guestfs_part_init>
4245 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4246 [InitBasicFS, Always, TestOutputBuffer (
4247 [["fill"; "0x63"; "10"; "/test"];
4248 ["read_file"; "/test"]], "cccccccccc")],
4249 "fill a file with octets",
4251 This command creates a new file called C<path>. The initial
4252 content of the file is C<len> octets of C<c>, where C<c>
4253 must be a number in the range C<[0..255]>.
4255 To fill a file with zero bytes (sparsely), it is
4256 much more efficient to use C<guestfs_truncate_size>.");
4258 ("available", (RErr, [StringList "groups"]), 216, [],
4259 [InitNone, Always, TestRun [["available"; ""]]],
4260 "test availability of some parts of the API",
4262 This command is used to check the availability of some
4263 groups of functionality in the appliance, which not all builds of
4264 the libguestfs appliance will be able to provide.
4266 The libguestfs groups, and the functions that those
4267 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4269 The argument C<groups> is a list of group names, eg:
4270 C<[\"inotify\", \"augeas\"]> would check for the availability of
4271 the Linux inotify functions and Augeas (configuration file
4274 The command returns no error if I<all> requested groups are available.
4276 It fails with an error if one or more of the requested
4277 groups is unavailable in the appliance.
4279 If an unknown group name is included in the
4280 list of groups then an error is always returned.
4288 You must call C<guestfs_launch> before calling this function.
4290 The reason is because we don't know what groups are
4291 supported by the appliance/daemon until it is running and can
4296 If a group of functions is available, this does not necessarily
4297 mean that they will work. You still have to check for errors
4298 when calling individual API functions even if they are
4303 It is usually the job of distro packagers to build
4304 complete functionality into the libguestfs appliance.
4305 Upstream libguestfs, if built from source with all
4306 requirements satisfied, will support everything.
4310 This call was added in version C<1.0.80>. In previous
4311 versions of libguestfs all you could do would be to speculatively
4312 execute a command to find out if the daemon implemented it.
4313 See also C<guestfs_version>.
4317 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4318 [InitBasicFS, Always, TestOutputBuffer (
4319 [["write_file"; "/src"; "hello, world"; "0"];
4320 ["dd"; "/src"; "/dest"];
4321 ["read_file"; "/dest"]], "hello, world")],
4322 "copy from source to destination using dd",
4324 This command copies from one source device or file C<src>
4325 to another destination device or file C<dest>. Normally you
4326 would use this to copy to or from a device or partition, for
4327 example to duplicate a filesystem.
4329 If the destination is a device, it must be as large or larger
4330 than the source file or device, otherwise the copy will fail.
4331 This command cannot do partial copies (see C<guestfs_copy_size>).");
4333 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4334 [InitBasicFS, Always, TestOutputInt (
4335 [["write_file"; "/file"; "hello, world"; "0"];
4336 ["filesize"; "/file"]], 12)],
4337 "return the size of the file in bytes",
4339 This command returns the size of C<file> in bytes.
4341 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4342 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4343 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4345 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4346 [InitBasicFSonLVM, Always, TestOutputList (
4347 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4348 ["lvs"]], ["/dev/VG/LV2"])],
4349 "rename an LVM logical volume",
4351 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4353 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4354 [InitBasicFSonLVM, Always, TestOutputList (
4356 ["vg_activate"; "false"; "VG"];
4357 ["vgrename"; "VG"; "VG2"];
4358 ["vg_activate"; "true"; "VG2"];
4359 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4360 ["vgs"]], ["VG2"])],
4361 "rename an LVM volume group",
4363 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4365 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4366 [InitISOFS, Always, TestOutputBuffer (
4367 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4368 "list the contents of a single file in an initrd",
4370 This command unpacks the file C<filename> from the initrd file
4371 called C<initrdpath>. The filename must be given I<without> the
4372 initial C</> character.
4374 For example, in guestfish you could use the following command
4375 to examine the boot script (usually called C</init>)
4376 contained in a Linux initrd or initramfs image:
4378 initrd-cat /boot/initrd-<version>.img init
4380 See also C<guestfs_initrd_list>.");
4382 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4384 "get the UUID of a physical volume",
4386 This command returns the UUID of the LVM PV C<device>.");
4388 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4390 "get the UUID of a volume group",
4392 This command returns the UUID of the LVM VG named C<vgname>.");
4394 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4396 "get the UUID of a logical volume",
4398 This command returns the UUID of the LVM LV C<device>.");
4400 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4402 "get the PV UUIDs containing the volume group",
4404 Given a VG called C<vgname>, this returns the UUIDs of all
4405 the physical volumes that this volume group resides on.
4407 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4408 calls to associate physical volumes and volume groups.
4410 See also C<guestfs_vglvuuids>.");
4412 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4414 "get the LV UUIDs of all LVs in the volume group",
4416 Given a VG called C<vgname>, this returns the UUIDs of all
4417 the logical volumes created in this volume group.
4419 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4420 calls to associate logical volumes and volume groups.
4422 See also C<guestfs_vgpvuuids>.");
4424 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4425 [InitBasicFS, Always, TestOutputBuffer (
4426 [["write_file"; "/src"; "hello, world"; "0"];
4427 ["copy_size"; "/src"; "/dest"; "5"];
4428 ["read_file"; "/dest"]], "hello")],
4429 "copy size bytes from source to destination using dd",
4431 This command copies exactly C<size> bytes from one source device
4432 or file C<src> to another destination device or file C<dest>.
4434 Note this will fail if the source is too short or if the destination
4435 is not large enough.");
4437 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4438 [InitEmpty, Always, TestRun (
4439 [["part_init"; "/dev/sda"; "mbr"];
4440 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4441 ["part_del"; "/dev/sda"; "1"]])],
4442 "delete a partition",
4444 This command deletes the partition numbered C<partnum> on C<device>.
4446 Note that in the case of MBR partitioning, deleting an
4447 extended partition also deletes any logical partitions
4450 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4451 [InitEmpty, Always, TestOutputTrue (
4452 [["part_init"; "/dev/sda"; "mbr"];
4453 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4454 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4455 ["part_get_bootable"; "/dev/sda"; "1"]])],
4456 "return true if a partition is bootable",
4458 This command returns true if the partition C<partnum> on
4459 C<device> has the bootable flag set.
4461 See also C<guestfs_part_set_bootable>.");
4463 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4464 [InitEmpty, Always, TestOutputInt (
4465 [["part_init"; "/dev/sda"; "mbr"];
4466 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4467 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4468 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4469 "get the MBR type byte (ID byte) from a partition",
4471 Returns the MBR type byte (also known as the ID byte) from
4472 the numbered partition C<partnum>.
4474 Note that only MBR (old DOS-style) partitions have type bytes.
4475 You will get undefined results for other partition table
4476 types (see C<guestfs_part_get_parttype>).");
4478 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4479 [], (* tested by part_get_mbr_id *)
4480 "set the MBR type byte (ID byte) of a partition",
4482 Sets the MBR type byte (also known as the ID byte) of
4483 the numbered partition C<partnum> to C<idbyte>. Note
4484 that the type bytes quoted in most documentation are
4485 in fact hexadecimal numbers, but usually documented
4486 without any leading \"0x\" which might be confusing.
4488 Note that only MBR (old DOS-style) partitions have type bytes.
4489 You will get undefined results for other partition table
4490 types (see C<guestfs_part_get_parttype>).");
4494 let all_functions = non_daemon_functions @ daemon_functions
4496 (* In some places we want the functions to be displayed sorted
4497 * alphabetically, so this is useful:
4499 let all_functions_sorted =
4500 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4501 compare n1 n2) all_functions
4503 (* Field types for structures. *)
4505 | FChar (* C 'char' (really, a 7 bit byte). *)
4506 | FString (* nul-terminated ASCII string, NOT NULL. *)
4507 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4512 | FBytes (* Any int measure that counts bytes. *)
4513 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4514 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4516 (* Because we generate extra parsing code for LVM command line tools,
4517 * we have to pull out the LVM columns separately here.
4527 "pv_attr", FString (* XXX *);
4528 "pv_pe_count", FInt64;
4529 "pv_pe_alloc_count", FInt64;
4532 "pv_mda_count", FInt64;
4533 "pv_mda_free", FBytes;
4534 (* Not in Fedora 10:
4535 "pv_mda_size", FBytes;
4542 "vg_attr", FString (* XXX *);
4545 "vg_sysid", FString;
4546 "vg_extent_size", FBytes;
4547 "vg_extent_count", FInt64;
4548 "vg_free_count", FInt64;
4553 "snap_count", FInt64;
4556 "vg_mda_count", FInt64;
4557 "vg_mda_free", FBytes;
4558 (* Not in Fedora 10:
4559 "vg_mda_size", FBytes;
4565 "lv_attr", FString (* XXX *);
4568 "lv_kernel_major", FInt64;
4569 "lv_kernel_minor", FInt64;
4571 "seg_count", FInt64;
4573 "snap_percent", FOptPercent;
4574 "copy_percent", FOptPercent;
4577 "mirror_log", FString;
4581 (* Names and fields in all structures (in RStruct and RStructList)
4585 (* The old RIntBool return type, only ever used for aug_defnode. Do
4586 * not use this struct in any new code.
4589 "i", FInt32; (* for historical compatibility *)
4590 "b", FInt32; (* for historical compatibility *)
4593 (* LVM PVs, VGs, LVs. *)
4594 "lvm_pv", lvm_pv_cols;
4595 "lvm_vg", lvm_vg_cols;
4596 "lvm_lv", lvm_lv_cols;
4598 (* Column names and types from stat structures.
4599 * NB. Can't use things like 'st_atime' because glibc header files
4600 * define some of these as macros. Ugh.
4631 (* Column names in dirent structure. *)
4634 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4639 (* Version numbers. *)
4647 (* Extended attribute. *)
4649 "attrname", FString;
4653 (* Inotify events. *)
4657 "in_cookie", FUInt32;
4661 (* Partition table entry. *)
4664 "part_start", FBytes;
4666 "part_size", FBytes;
4668 ] (* end of structs *)
4670 (* Ugh, Java has to be different ..
4671 * These names are also used by the Haskell bindings.
4673 let java_structs = [
4674 "int_bool", "IntBool";
4679 "statvfs", "StatVFS";
4681 "version", "Version";
4683 "inotify_event", "INotifyEvent";
4684 "partition", "Partition";
4687 (* What structs are actually returned. *)
4688 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4690 (* Returns a list of RStruct/RStructList structs that are returned
4691 * by any function. Each element of returned list is a pair:
4693 * (structname, RStructOnly)
4694 * == there exists function which returns RStruct (_, structname)
4695 * (structname, RStructListOnly)
4696 * == there exists function which returns RStructList (_, structname)
4697 * (structname, RStructAndList)
4698 * == there are functions returning both RStruct (_, structname)
4699 * and RStructList (_, structname)
4701 let rstructs_used_by functions =
4702 (* ||| is a "logical OR" for rstructs_used_t *)
4706 | _, RStructAndList -> RStructAndList
4707 | RStructOnly, RStructListOnly
4708 | RStructListOnly, RStructOnly -> RStructAndList
4709 | RStructOnly, RStructOnly -> RStructOnly
4710 | RStructListOnly, RStructListOnly -> RStructListOnly
4713 let h = Hashtbl.create 13 in
4715 (* if elem->oldv exists, update entry using ||| operator,
4716 * else just add elem->newv to the hash
4718 let update elem newv =
4719 try let oldv = Hashtbl.find h elem in
4720 Hashtbl.replace h elem (newv ||| oldv)
4721 with Not_found -> Hashtbl.add h elem newv
4725 fun (_, style, _, _, _, _, _) ->
4726 match fst style with
4727 | RStruct (_, structname) -> update structname RStructOnly
4728 | RStructList (_, structname) -> update structname RStructListOnly
4732 (* return key->values as a list of (key,value) *)
4733 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4735 (* Used for testing language bindings. *)
4737 | CallString of string
4738 | CallOptString of string option
4739 | CallStringList of string list
4741 | CallInt64 of int64
4744 (* Used to memoize the result of pod2text. *)
4745 let pod2text_memo_filename = "src/.pod2text.data"
4746 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4748 let chan = open_in pod2text_memo_filename in
4749 let v = input_value chan in
4753 _ -> Hashtbl.create 13
4754 let pod2text_memo_updated () =
4755 let chan = open_out pod2text_memo_filename in
4756 output_value chan pod2text_memo;
4759 (* Useful functions.
4760 * Note we don't want to use any external OCaml libraries which
4761 * makes this a bit harder than it should be.
4763 module StringMap = Map.Make (String)
4765 let failwithf fs = ksprintf failwith fs
4767 let unique = let i = ref 0 in fun () -> incr i; !i
4769 let replace_char s c1 c2 =
4770 let s2 = String.copy s in
4771 let r = ref false in
4772 for i = 0 to String.length s2 - 1 do
4773 if String.unsafe_get s2 i = c1 then (
4774 String.unsafe_set s2 i c2;
4778 if not !r then s else s2
4782 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4784 let triml ?(test = isspace) str =
4786 let n = ref (String.length str) in
4787 while !n > 0 && test str.[!i]; do
4792 else String.sub str !i !n
4794 let trimr ?(test = isspace) str =
4795 let n = ref (String.length str) in
4796 while !n > 0 && test str.[!n-1]; do
4799 if !n = String.length str then str
4800 else String.sub str 0 !n
4802 let trim ?(test = isspace) str =
4803 trimr ~test (triml ~test str)
4805 let rec find s sub =
4806 let len = String.length s in
4807 let sublen = String.length sub in
4809 if i <= len-sublen then (
4811 if j < sublen then (
4812 if s.[i+j] = sub.[j] then loop2 (j+1)
4818 if r = -1 then loop (i+1) else r
4824 let rec replace_str s s1 s2 =
4825 let len = String.length s in
4826 let sublen = String.length s1 in
4827 let i = find s s1 in
4830 let s' = String.sub s 0 i in
4831 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4832 s' ^ s2 ^ replace_str s'' s1 s2
4835 let rec string_split sep str =
4836 let len = String.length str in
4837 let seplen = String.length sep in
4838 let i = find str sep in
4839 if i = -1 then [str]
4841 let s' = String.sub str 0 i in
4842 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4843 s' :: string_split sep s''
4846 let files_equal n1 n2 =
4847 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4848 match Sys.command cmd with
4851 | i -> failwithf "%s: failed with error code %d" cmd i
4853 let rec filter_map f = function
4857 | Some y -> y :: filter_map f xs
4858 | None -> filter_map f xs
4860 let rec find_map f = function
4861 | [] -> raise Not_found
4865 | None -> find_map f xs
4868 let rec loop i = function
4870 | x :: xs -> f i x; loop (i+1) xs
4875 let rec loop i = function
4877 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4881 let count_chars c str =
4882 let count = ref 0 in
4883 for i = 0 to String.length str - 1 do
4884 if c = String.unsafe_get str i then incr count
4888 let name_of_argt = function
4889 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4890 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4891 | FileIn n | FileOut n -> n
4893 let java_name_of_struct typ =
4894 try List.assoc typ java_structs
4897 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4899 let cols_of_struct typ =
4900 try List.assoc typ structs
4902 failwithf "cols_of_struct: unknown struct %s" typ
4904 let seq_of_test = function
4905 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4906 | TestOutputListOfDevices (s, _)
4907 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4908 | TestOutputTrue s | TestOutputFalse s
4909 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4910 | TestOutputStruct (s, _)
4911 | TestLastFail s -> s
4913 (* Handling for function flags. *)
4914 let protocol_limit_warning =
4915 "Because of the message protocol, there is a transfer limit
4916 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4918 let danger_will_robinson =
4919 "B<This command is dangerous. Without careful use you
4920 can easily destroy all your data>."
4922 let deprecation_notice flags =
4925 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4927 sprintf "This function is deprecated.
4928 In new code, use the C<%s> call instead.
4930 Deprecated functions will not be removed from the API, but the
4931 fact that they are deprecated indicates that there are problems
4932 with correct use of these functions." alt in
4937 (* Create list of optional groups. *)
4939 let h = Hashtbl.create 13 in
4941 fun (name, _, _, flags, _, _, _) ->
4945 let names = try Hashtbl.find h group with Not_found -> [] in
4946 Hashtbl.replace h group (name :: names)
4950 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4953 fun group -> group, List.sort compare (Hashtbl.find h group)
4955 List.sort (fun x y -> compare (fst x) (fst y)) groups
4957 (* Check function names etc. for consistency. *)
4958 let check_functions () =
4959 let contains_uppercase str =
4960 let len = String.length str in
4962 if i >= len then false
4965 if c >= 'A' && c <= 'Z' then true
4972 (* Check function names. *)
4974 fun (name, _, _, _, _, _, _) ->
4975 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4976 failwithf "function name %s does not need 'guestfs' prefix" name;
4978 failwithf "function name is empty";
4979 if name.[0] < 'a' || name.[0] > 'z' then
4980 failwithf "function name %s must start with lowercase a-z" name;
4981 if String.contains name '-' then
4982 failwithf "function name %s should not contain '-', use '_' instead."
4986 (* Check function parameter/return names. *)
4988 fun (name, style, _, _, _, _, _) ->
4989 let check_arg_ret_name n =
4990 if contains_uppercase n then
4991 failwithf "%s param/ret %s should not contain uppercase chars"
4993 if String.contains n '-' || String.contains n '_' then
4994 failwithf "%s param/ret %s should not contain '-' or '_'"
4997 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;
4998 if n = "int" || n = "char" || n = "short" || n = "long" then
4999 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5000 if n = "i" || n = "n" then
5001 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5002 if n = "argv" || n = "args" then
5003 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5005 (* List Haskell, OCaml and C keywords here.
5006 * http://www.haskell.org/haskellwiki/Keywords
5007 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5008 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5009 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5010 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5011 * Omitting _-containing words, since they're handled above.
5012 * Omitting the OCaml reserved word, "val", is ok,
5013 * and saves us from renaming several parameters.
5016 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5017 "char"; "class"; "const"; "constraint"; "continue"; "data";
5018 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5019 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5020 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5021 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5022 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5024 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5025 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5026 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5027 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5028 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5029 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5030 "volatile"; "when"; "where"; "while";
5032 if List.mem n reserved then
5033 failwithf "%s has param/ret using reserved word %s" name n;
5036 (match fst style with
5038 | RInt n | RInt64 n | RBool n
5039 | RConstString n | RConstOptString n | RString n
5040 | RStringList n | RStruct (n, _) | RStructList (n, _)
5041 | RHashtable n | RBufferOut n ->
5042 check_arg_ret_name n
5044 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5047 (* Check short descriptions. *)
5049 fun (name, _, _, _, _, shortdesc, _) ->
5050 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5051 failwithf "short description of %s should begin with lowercase." name;
5052 let c = shortdesc.[String.length shortdesc-1] in
5053 if c = '\n' || c = '.' then
5054 failwithf "short description of %s should not end with . or \\n." name
5057 (* Check long descriptions. *)
5059 fun (name, _, _, _, _, _, longdesc) ->
5060 if longdesc.[String.length longdesc-1] = '\n' then
5061 failwithf "long description of %s should not end with \\n." name
5064 (* Check proc_nrs. *)
5066 fun (name, _, proc_nr, _, _, _, _) ->
5067 if proc_nr <= 0 then
5068 failwithf "daemon function %s should have proc_nr > 0" name
5072 fun (name, _, proc_nr, _, _, _, _) ->
5073 if proc_nr <> -1 then
5074 failwithf "non-daemon function %s should have proc_nr -1" name
5075 ) non_daemon_functions;
5078 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5081 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5082 let rec loop = function
5085 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5087 | (name1,nr1) :: (name2,nr2) :: _ ->
5088 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5096 (* Ignore functions that have no tests. We generate a
5097 * warning when the user does 'make check' instead.
5099 | name, _, _, _, [], _, _ -> ()
5100 | name, _, _, _, tests, _, _ ->
5104 match seq_of_test test with
5106 failwithf "%s has a test containing an empty sequence" name
5107 | cmds -> List.map List.hd cmds
5109 let funcs = List.flatten funcs in
5111 let tested = List.mem name funcs in
5114 failwithf "function %s has tests but does not test itself" name
5117 (* 'pr' prints to the current output file. *)
5118 let chan = ref Pervasives.stdout
5123 let i = count_chars '\n' str in
5124 lines := !lines + i;
5125 output_string !chan str
5128 let copyright_years =
5129 let this_year = 1900 + (localtime (time ())).tm_year in
5130 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5132 (* Generate a header block in a number of standard styles. *)
5133 type comment_style =
5134 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5135 type license = GPLv2plus | LGPLv2plus
5137 let generate_header ?(extra_inputs = []) comment license =
5138 let inputs = "src/generator.ml" :: extra_inputs in
5139 let c = match comment with
5140 | CStyle -> pr "/* "; " *"
5141 | CPlusPlusStyle -> pr "// "; "//"
5142 | HashStyle -> pr "# "; "#"
5143 | OCamlStyle -> pr "(* "; " *"
5144 | HaskellStyle -> pr "{- "; " " in
5145 pr "libguestfs generated file\n";
5146 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5147 List.iter (pr "%s %s\n" c) inputs;
5148 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5150 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5154 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5155 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5156 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5157 pr "%s (at your option) any later version.\n" c;
5159 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5160 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5161 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5162 pr "%s GNU General Public License for more details.\n" c;
5164 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5165 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5166 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5169 pr "%s This library is free software; you can redistribute it and/or\n" c;
5170 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5171 pr "%s License as published by the Free Software Foundation; either\n" c;
5172 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5174 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5175 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5176 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5177 pr "%s Lesser General Public License for more details.\n" c;
5179 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5180 pr "%s License along with this library; if not, write to the Free Software\n" c;
5181 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5184 | CStyle -> pr " */\n"
5187 | OCamlStyle -> pr " *)\n"
5188 | HaskellStyle -> pr "-}\n"
5192 (* Start of main code generation functions below this line. *)
5194 (* Generate the pod documentation for the C API. *)
5195 let rec generate_actions_pod () =
5197 fun (shortname, style, _, flags, _, _, longdesc) ->
5198 if not (List.mem NotInDocs flags) then (
5199 let name = "guestfs_" ^ shortname in
5200 pr "=head2 %s\n\n" name;
5202 generate_prototype ~extern:false ~handle:"g" name style;
5204 pr "%s\n\n" longdesc;
5205 (match fst style with
5207 pr "This function returns 0 on success or -1 on error.\n\n"
5209 pr "On error this function returns -1.\n\n"
5211 pr "On error this function returns -1.\n\n"
5213 pr "This function returns a C truth value on success or -1 on error.\n\n"
5215 pr "This function returns a string, or NULL on error.
5216 The string is owned by the guest handle and must I<not> be freed.\n\n"
5217 | RConstOptString _ ->
5218 pr "This function returns a string which may be NULL.
5219 There is way to return an error from this function.
5220 The string is owned by the guest handle and must I<not> be freed.\n\n"
5222 pr "This function returns a string, or NULL on error.
5223 I<The caller must free the returned string after use>.\n\n"
5225 pr "This function returns a NULL-terminated array of strings
5226 (like L<environ(3)>), or NULL if there was an error.
5227 I<The caller must free the strings and the array after use>.\n\n"
5228 | RStruct (_, typ) ->
5229 pr "This function returns a C<struct guestfs_%s *>,
5230 or NULL if there was an error.
5231 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5232 | RStructList (_, typ) ->
5233 pr "This function returns a C<struct guestfs_%s_list *>
5234 (see E<lt>guestfs-structs.hE<gt>),
5235 or NULL if there was an error.
5236 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5238 pr "This function returns a NULL-terminated array of
5239 strings, or NULL if there was an error.
5240 The array of strings will always have length C<2n+1>, where
5241 C<n> keys and values alternate, followed by the trailing NULL entry.
5242 I<The caller must free the strings and the array after use>.\n\n"
5244 pr "This function returns a buffer, or NULL on error.
5245 The size of the returned buffer is written to C<*size_r>.
5246 I<The caller must free the returned buffer after use>.\n\n"
5248 if List.mem ProtocolLimitWarning flags then
5249 pr "%s\n\n" protocol_limit_warning;
5250 if List.mem DangerWillRobinson flags then
5251 pr "%s\n\n" danger_will_robinson;
5252 match deprecation_notice flags with
5254 | Some txt -> pr "%s\n\n" txt
5256 ) all_functions_sorted
5258 and generate_structs_pod () =
5259 (* Structs documentation. *)
5262 pr "=head2 guestfs_%s\n" typ;
5264 pr " struct guestfs_%s {\n" typ;
5267 | name, FChar -> pr " char %s;\n" name
5268 | name, FUInt32 -> pr " uint32_t %s;\n" name
5269 | name, FInt32 -> pr " int32_t %s;\n" name
5270 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5271 | name, FInt64 -> pr " int64_t %s;\n" name
5272 | name, FString -> pr " char *%s;\n" name
5274 pr " /* The next two fields describe a byte array. */\n";
5275 pr " uint32_t %s_len;\n" name;
5276 pr " char *%s;\n" name
5278 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5279 pr " char %s[32];\n" name
5280 | name, FOptPercent ->
5281 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5282 pr " float %s;\n" name
5286 pr " struct guestfs_%s_list {\n" typ;
5287 pr " uint32_t len; /* Number of elements in list. */\n";
5288 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5291 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5292 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5297 and generate_availability_pod () =
5298 (* Availability documentation. *)
5302 fun (group, functions) ->
5303 pr "=item B<%s>\n" group;
5305 pr "The following functions:\n";
5306 List.iter (pr "L</guestfs_%s>\n") functions;
5312 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5313 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5315 * We have to use an underscore instead of a dash because otherwise
5316 * rpcgen generates incorrect code.
5318 * This header is NOT exported to clients, but see also generate_structs_h.
5320 and generate_xdr () =
5321 generate_header CStyle LGPLv2plus;
5323 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5324 pr "typedef string str<>;\n";
5327 (* Internal structures. *)
5331 pr "struct guestfs_int_%s {\n" typ;
5333 | name, FChar -> pr " char %s;\n" name
5334 | name, FString -> pr " string %s<>;\n" name
5335 | name, FBuffer -> pr " opaque %s<>;\n" name
5336 | name, FUUID -> pr " opaque %s[32];\n" name
5337 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5338 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5339 | name, FOptPercent -> pr " float %s;\n" name
5343 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5348 fun (shortname, style, _, _, _, _, _) ->
5349 let name = "guestfs_" ^ shortname in
5351 (match snd style with
5354 pr "struct %s_args {\n" name;
5357 | Pathname n | Device n | Dev_or_Path n | String n ->
5358 pr " string %s<>;\n" n
5359 | OptString n -> pr " str *%s;\n" n
5360 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5361 | Bool n -> pr " bool %s;\n" n
5362 | Int n -> pr " int %s;\n" n
5363 | Int64 n -> pr " hyper %s;\n" n
5364 | FileIn _ | FileOut _ -> ()
5368 (match fst style with
5371 pr "struct %s_ret {\n" name;
5375 pr "struct %s_ret {\n" name;
5376 pr " hyper %s;\n" n;
5379 pr "struct %s_ret {\n" name;
5382 | RConstString _ | RConstOptString _ ->
5383 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5385 pr "struct %s_ret {\n" name;
5386 pr " string %s<>;\n" n;
5389 pr "struct %s_ret {\n" name;
5390 pr " str %s<>;\n" n;
5392 | RStruct (n, typ) ->
5393 pr "struct %s_ret {\n" name;
5394 pr " guestfs_int_%s %s;\n" typ n;
5396 | RStructList (n, typ) ->
5397 pr "struct %s_ret {\n" name;
5398 pr " guestfs_int_%s_list %s;\n" typ n;
5401 pr "struct %s_ret {\n" name;
5402 pr " str %s<>;\n" n;
5405 pr "struct %s_ret {\n" name;
5406 pr " opaque %s<>;\n" n;
5411 (* Table of procedure numbers. *)
5412 pr "enum guestfs_procedure {\n";
5414 fun (shortname, _, proc_nr, _, _, _, _) ->
5415 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5417 pr " GUESTFS_PROC_NR_PROCS\n";
5421 (* Having to choose a maximum message size is annoying for several
5422 * reasons (it limits what we can do in the API), but it (a) makes
5423 * the protocol a lot simpler, and (b) provides a bound on the size
5424 * of the daemon which operates in limited memory space.
5426 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5429 (* Message header, etc. *)
5431 /* The communication protocol is now documented in the guestfs(3)
5435 const GUESTFS_PROGRAM = 0x2000F5F5;
5436 const GUESTFS_PROTOCOL_VERSION = 1;
5438 /* These constants must be larger than any possible message length. */
5439 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5440 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5442 enum guestfs_message_direction {
5443 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5444 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5447 enum guestfs_message_status {
5448 GUESTFS_STATUS_OK = 0,
5449 GUESTFS_STATUS_ERROR = 1
5452 const GUESTFS_ERROR_LEN = 256;
5454 struct guestfs_message_error {
5455 string error_message<GUESTFS_ERROR_LEN>;
5458 struct guestfs_message_header {
5459 unsigned prog; /* GUESTFS_PROGRAM */
5460 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5461 guestfs_procedure proc; /* GUESTFS_PROC_x */
5462 guestfs_message_direction direction;
5463 unsigned serial; /* message serial number */
5464 guestfs_message_status status;
5467 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5469 struct guestfs_chunk {
5470 int cancel; /* if non-zero, transfer is cancelled */
5471 /* data size is 0 bytes if the transfer has finished successfully */
5472 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5476 (* Generate the guestfs-structs.h file. *)
5477 and generate_structs_h () =
5478 generate_header CStyle LGPLv2plus;
5480 (* This is a public exported header file containing various
5481 * structures. The structures are carefully written to have
5482 * exactly the same in-memory format as the XDR structures that
5483 * we use on the wire to the daemon. The reason for creating
5484 * copies of these structures here is just so we don't have to
5485 * export the whole of guestfs_protocol.h (which includes much
5486 * unrelated and XDR-dependent stuff that we don't want to be
5487 * public, or required by clients).
5489 * To reiterate, we will pass these structures to and from the
5490 * client with a simple assignment or memcpy, so the format
5491 * must be identical to what rpcgen / the RFC defines.
5494 (* Public structures. *)
5497 pr "struct guestfs_%s {\n" typ;
5500 | name, FChar -> pr " char %s;\n" name
5501 | name, FString -> pr " char *%s;\n" name
5503 pr " uint32_t %s_len;\n" name;
5504 pr " char *%s;\n" name
5505 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5506 | name, FUInt32 -> pr " uint32_t %s;\n" name
5507 | name, FInt32 -> pr " int32_t %s;\n" name
5508 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5509 | name, FInt64 -> pr " int64_t %s;\n" name
5510 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5514 pr "struct guestfs_%s_list {\n" typ;
5515 pr " uint32_t len;\n";
5516 pr " struct guestfs_%s *val;\n" typ;
5519 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5520 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5524 (* Generate the guestfs-actions.h file. *)
5525 and generate_actions_h () =
5526 generate_header CStyle LGPLv2plus;
5528 fun (shortname, style, _, _, _, _, _) ->
5529 let name = "guestfs_" ^ shortname in
5530 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5534 (* Generate the guestfs-internal-actions.h file. *)
5535 and generate_internal_actions_h () =
5536 generate_header CStyle LGPLv2plus;
5538 fun (shortname, style, _, _, _, _, _) ->
5539 let name = "guestfs__" ^ shortname in
5540 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5542 ) non_daemon_functions
5544 (* Generate the client-side dispatch stubs. *)
5545 and generate_client_actions () =
5546 generate_header CStyle LGPLv2plus;
5553 #include <inttypes.h>
5555 #include \"guestfs.h\"
5556 #include \"guestfs-internal.h\"
5557 #include \"guestfs-internal-actions.h\"
5558 #include \"guestfs_protocol.h\"
5560 #define error guestfs_error
5561 //#define perrorf guestfs_perrorf
5562 #define safe_malloc guestfs_safe_malloc
5563 #define safe_realloc guestfs_safe_realloc
5564 //#define safe_strdup guestfs_safe_strdup
5565 #define safe_memdup guestfs_safe_memdup
5567 /* Check the return message from a call for validity. */
5569 check_reply_header (guestfs_h *g,
5570 const struct guestfs_message_header *hdr,
5571 unsigned int proc_nr, unsigned int serial)
5573 if (hdr->prog != GUESTFS_PROGRAM) {
5574 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5577 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5578 error (g, \"wrong protocol version (%%d/%%d)\",
5579 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5582 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5583 error (g, \"unexpected message direction (%%d/%%d)\",
5584 hdr->direction, GUESTFS_DIRECTION_REPLY);
5587 if (hdr->proc != proc_nr) {
5588 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5591 if (hdr->serial != serial) {
5592 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5599 /* Check we are in the right state to run a high-level action. */
5601 check_state (guestfs_h *g, const char *caller)
5603 if (!guestfs__is_ready (g)) {
5604 if (guestfs__is_config (g) || guestfs__is_launching (g))
5605 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5608 error (g, \"%%s called from the wrong state, %%d != READY\",
5609 caller, guestfs__get_state (g));
5617 (* Generate code to generate guestfish call traces. *)
5618 let trace_call shortname style =
5619 pr " if (guestfs__get_trace (g)) {\n";
5622 List.exists (function
5623 | StringList _ | DeviceList _ -> true
5624 | _ -> false) (snd style) in
5630 pr " printf (\"%s\");\n" shortname;
5633 | String n (* strings *)
5639 (* guestfish doesn't support string escaping, so neither do we *)
5640 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5641 | OptString n -> (* string option *)
5642 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5643 pr " else printf (\" null\");\n"
5645 | DeviceList n -> (* string list *)
5646 pr " putchar (' ');\n";
5647 pr " putchar ('\"');\n";
5648 pr " for (i = 0; %s[i]; ++i) {\n" n;
5649 pr " if (i > 0) putchar (' ');\n";
5650 pr " fputs (%s[i], stdout);\n" n;
5652 pr " putchar ('\"');\n";
5653 | Bool n -> (* boolean *)
5654 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5655 | Int n -> (* int *)
5656 pr " printf (\" %%d\", %s);\n" n
5658 pr " printf (\" %%\" PRIi64, %s);\n" n
5660 pr " putchar ('\\n');\n";
5665 (* For non-daemon functions, generate a wrapper around each function. *)
5667 fun (shortname, style, _, _, _, _, _) ->
5668 let name = "guestfs_" ^ shortname in
5670 generate_prototype ~extern:false ~semicolon:false ~newline:true
5671 ~handle:"g" name style;
5673 trace_call shortname style;
5674 pr " return guestfs__%s " shortname;
5675 generate_c_call_args ~handle:"g" style;
5679 ) non_daemon_functions;
5681 (* Client-side stubs for each function. *)
5683 fun (shortname, style, _, _, _, _, _) ->
5684 let name = "guestfs_" ^ shortname in
5686 (* Generate the action stub. *)
5687 generate_prototype ~extern:false ~semicolon:false ~newline:true
5688 ~handle:"g" name style;
5691 match fst style with
5692 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5693 | RConstString _ | RConstOptString _ ->
5694 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5695 | RString _ | RStringList _
5696 | RStruct _ | RStructList _
5697 | RHashtable _ | RBufferOut _ ->
5702 (match snd style with
5704 | _ -> pr " struct %s_args args;\n" name
5707 pr " guestfs_message_header hdr;\n";
5708 pr " guestfs_message_error err;\n";
5710 match fst style with
5712 | RConstString _ | RConstOptString _ ->
5713 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5715 | RBool _ | RString _ | RStringList _
5716 | RStruct _ | RStructList _
5717 | RHashtable _ | RBufferOut _ ->
5718 pr " struct %s_ret ret;\n" name;
5721 pr " int serial;\n";
5724 trace_call shortname style;
5725 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5726 pr " guestfs___set_busy (g);\n";
5729 (* Send the main header and arguments. *)
5730 (match snd style with
5732 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5733 (String.uppercase shortname)
5737 | Pathname n | Device n | Dev_or_Path n | String n ->
5738 pr " args.%s = (char *) %s;\n" n n
5740 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5741 | StringList n | DeviceList n ->
5742 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5743 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5745 pr " args.%s = %s;\n" n n
5747 pr " args.%s = %s;\n" n n
5749 pr " args.%s = %s;\n" n n
5750 | FileIn _ | FileOut _ -> ()
5752 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5753 (String.uppercase shortname);
5754 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5757 pr " if (serial == -1) {\n";
5758 pr " guestfs___end_busy (g);\n";
5759 pr " return %s;\n" error_code;
5763 (* Send any additional files (FileIn) requested. *)
5764 let need_read_reply_label = ref false in
5768 pr " r = guestfs___send_file (g, %s);\n" n;
5769 pr " if (r == -1) {\n";
5770 pr " guestfs___end_busy (g);\n";
5771 pr " return %s;\n" error_code;
5773 pr " if (r == -2) /* daemon cancelled */\n";
5774 pr " goto read_reply;\n";
5775 need_read_reply_label := true;
5780 (* Wait for the reply from the remote end. *)
5781 if !need_read_reply_label then pr " read_reply:\n";
5782 pr " memset (&hdr, 0, sizeof hdr);\n";
5783 pr " memset (&err, 0, sizeof err);\n";
5784 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5786 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5790 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5793 pr " if (r == -1) {\n";
5794 pr " guestfs___end_busy (g);\n";
5795 pr " return %s;\n" error_code;
5799 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5800 (String.uppercase shortname);
5801 pr " guestfs___end_busy (g);\n";
5802 pr " return %s;\n" error_code;
5806 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5807 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5808 pr " free (err.error_message);\n";
5809 pr " guestfs___end_busy (g);\n";
5810 pr " return %s;\n" error_code;
5814 (* Expecting to receive further files (FileOut)? *)
5818 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5819 pr " guestfs___end_busy (g);\n";
5820 pr " return %s;\n" error_code;
5826 pr " guestfs___end_busy (g);\n";
5828 (match fst style with
5829 | RErr -> pr " return 0;\n"
5830 | RInt n | RInt64 n | RBool n ->
5831 pr " return ret.%s;\n" n
5832 | RConstString _ | RConstOptString _ ->
5833 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5835 pr " return ret.%s; /* caller will free */\n" n
5836 | RStringList n | RHashtable n ->
5837 pr " /* caller will free this, but we need to add a NULL entry */\n";
5838 pr " ret.%s.%s_val =\n" n n;
5839 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5840 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5842 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5843 pr " return ret.%s.%s_val;\n" n n
5845 pr " /* caller will free this */\n";
5846 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5847 | RStructList (n, _) ->
5848 pr " /* caller will free this */\n";
5849 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5851 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5852 pr " * _val might be NULL here. To make the API saner for\n";
5853 pr " * callers, we turn this case into a unique pointer (using\n";
5854 pr " * malloc(1)).\n";
5856 pr " if (ret.%s.%s_len > 0) {\n" n n;
5857 pr " *size_r = ret.%s.%s_len;\n" n n;
5858 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5860 pr " free (ret.%s.%s_val);\n" n n;
5861 pr " char *p = safe_malloc (g, 1);\n";
5862 pr " *size_r = ret.%s.%s_len;\n" n n;
5870 (* Functions to free structures. *)
5871 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5872 pr " * structure format is identical to the XDR format. See note in\n";
5873 pr " * generator.ml.\n";
5880 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5882 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5888 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5890 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5897 (* Generate daemon/actions.h. *)
5898 and generate_daemon_actions_h () =
5899 generate_header CStyle GPLv2plus;
5901 pr "#include \"../src/guestfs_protocol.h\"\n";
5905 fun (name, style, _, _, _, _, _) ->
5907 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5911 (* Generate the linker script which controls the visibility of
5912 * symbols in the public ABI and ensures no other symbols get
5913 * exported accidentally.
5915 and generate_linker_script () =
5916 generate_header HashStyle GPLv2plus;
5921 "guestfs_get_error_handler";
5922 "guestfs_get_out_of_memory_handler";
5923 "guestfs_last_error";
5924 "guestfs_set_error_handler";
5925 "guestfs_set_launch_done_callback";
5926 "guestfs_set_log_message_callback";
5927 "guestfs_set_out_of_memory_handler";
5928 "guestfs_set_subprocess_quit_callback";
5930 (* Unofficial parts of the API: the bindings code use these
5931 * functions, so it is useful to export them.
5933 "guestfs_safe_calloc";
5934 "guestfs_safe_malloc";
5937 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5941 List.map (fun (typ, _) ->
5942 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5945 let globals = List.sort compare (globals @ functions @ structs) in
5949 List.iter (pr " %s;\n") globals;
5956 (* Generate the server-side stubs. *)
5957 and generate_daemon_actions () =
5958 generate_header CStyle GPLv2plus;
5960 pr "#include <config.h>\n";
5962 pr "#include <stdio.h>\n";
5963 pr "#include <stdlib.h>\n";
5964 pr "#include <string.h>\n";
5965 pr "#include <inttypes.h>\n";
5966 pr "#include <rpc/types.h>\n";
5967 pr "#include <rpc/xdr.h>\n";
5969 pr "#include \"daemon.h\"\n";
5970 pr "#include \"c-ctype.h\"\n";
5971 pr "#include \"../src/guestfs_protocol.h\"\n";
5972 pr "#include \"actions.h\"\n";
5976 fun (name, style, _, _, _, _, _) ->
5977 (* Generate server-side stubs. *)
5978 pr "static void %s_stub (XDR *xdr_in)\n" name;
5981 match fst style with
5982 | RErr | RInt _ -> pr " int r;\n"; "-1"
5983 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5984 | RBool _ -> pr " int r;\n"; "-1"
5985 | RConstString _ | RConstOptString _ ->
5986 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5987 | RString _ -> pr " char *r;\n"; "NULL"
5988 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5989 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5990 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5992 pr " size_t size = 1;\n";
5996 (match snd style with
5999 pr " struct guestfs_%s_args args;\n" name;
6002 | Device n | Dev_or_Path n
6005 | OptString n -> pr " char *%s;\n" n
6006 | StringList n | DeviceList n -> pr " char **%s;\n" n
6007 | Bool n -> pr " int %s;\n" n
6008 | Int n -> pr " int %s;\n" n
6009 | Int64 n -> pr " int64_t %s;\n" n
6010 | FileIn _ | FileOut _ -> ()
6015 (match snd style with
6018 pr " memset (&args, 0, sizeof args);\n";
6020 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6021 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6025 pr " char *%s = args.%s;\n" n n
6027 let pr_list_handling_code n =
6028 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6029 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6030 pr " if (%s == NULL) {\n" n;
6031 pr " reply_with_perror (\"realloc\");\n";
6034 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6035 pr " args.%s.%s_val = %s;\n" n n n;
6041 pr " ABS_PATH (%s, goto done);\n" n;
6044 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6047 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6048 | String n -> pr_args n
6049 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6051 pr_list_handling_code n;
6053 pr_list_handling_code n;
6054 pr " /* Ensure that each is a device,\n";
6055 pr " * and perform device name translation. */\n";
6056 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6057 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6059 | Bool n -> pr " %s = args.%s;\n" n n
6060 | Int n -> pr " %s = args.%s;\n" n n
6061 | Int64 n -> pr " %s = args.%s;\n" n n
6062 | FileIn _ | FileOut _ -> ()
6068 (* this is used at least for do_equal *)
6069 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6070 (* Emit NEED_ROOT just once, even when there are two or
6071 more Pathname args *)
6072 pr " NEED_ROOT (goto done);\n";
6075 (* Don't want to call the impl with any FileIn or FileOut
6076 * parameters, since these go "outside" the RPC protocol.
6079 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6081 pr " r = do_%s " name;
6082 generate_c_call_args (fst style, args');
6085 (match fst style with
6086 | RErr | RInt _ | RInt64 _ | RBool _
6087 | RConstString _ | RConstOptString _
6088 | RString _ | RStringList _ | RHashtable _
6089 | RStruct (_, _) | RStructList (_, _) ->
6090 pr " if (r == %s)\n" error_code;
6091 pr " /* do_%s has already called reply_with_error */\n" name;
6095 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6096 pr " * an ordinary zero-length buffer), so be careful ...\n";
6098 pr " if (size == 1 && r == %s)\n" error_code;
6099 pr " /* do_%s has already called reply_with_error */\n" name;
6104 (* If there are any FileOut parameters, then the impl must
6105 * send its own reply.
6108 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6110 pr " /* do_%s has already sent a reply */\n" name
6112 match fst style with
6113 | RErr -> pr " reply (NULL, NULL);\n"
6114 | RInt n | RInt64 n | RBool n ->
6115 pr " struct guestfs_%s_ret ret;\n" name;
6116 pr " ret.%s = r;\n" n;
6117 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6119 | RConstString _ | RConstOptString _ ->
6120 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6122 pr " struct guestfs_%s_ret ret;\n" name;
6123 pr " ret.%s = r;\n" n;
6124 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6127 | RStringList n | RHashtable n ->
6128 pr " struct guestfs_%s_ret ret;\n" name;
6129 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6130 pr " ret.%s.%s_val = r;\n" n n;
6131 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6133 pr " free_strings (r);\n"
6135 pr " struct guestfs_%s_ret ret;\n" name;
6136 pr " ret.%s = *r;\n" n;
6137 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6139 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6141 | RStructList (n, _) ->
6142 pr " struct guestfs_%s_ret ret;\n" name;
6143 pr " ret.%s = *r;\n" n;
6144 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6146 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6149 pr " struct guestfs_%s_ret ret;\n" name;
6150 pr " ret.%s.%s_val = r;\n" n n;
6151 pr " ret.%s.%s_len = size;\n" n n;
6152 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6157 (* Free the args. *)
6158 (match snd style with
6163 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6170 (* Dispatch function. *)
6171 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6173 pr " switch (proc_nr) {\n";
6176 fun (name, style, _, _, _, _, _) ->
6177 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6178 pr " %s_stub (xdr_in);\n" name;
6183 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";
6188 (* LVM columns and tokenization functions. *)
6189 (* XXX This generates crap code. We should rethink how we
6195 pr "static const char *lvm_%s_cols = \"%s\";\n"
6196 typ (String.concat "," (List.map fst cols));
6199 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6201 pr " char *tok, *p, *next;\n";
6205 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6208 pr " if (!str) {\n";
6209 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6212 pr " if (!*str || c_isspace (*str)) {\n";
6213 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6218 fun (name, coltype) ->
6219 pr " if (!tok) {\n";
6220 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6223 pr " p = strchrnul (tok, ',');\n";
6224 pr " if (*p) next = p+1; else next = NULL;\n";
6225 pr " *p = '\\0';\n";
6228 pr " r->%s = strdup (tok);\n" name;
6229 pr " if (r->%s == NULL) {\n" name;
6230 pr " perror (\"strdup\");\n";
6234 pr " for (i = j = 0; i < 32; ++j) {\n";
6235 pr " if (tok[j] == '\\0') {\n";
6236 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6238 pr " } else if (tok[j] != '-')\n";
6239 pr " r->%s[i++] = tok[j];\n" name;
6242 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6243 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6247 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6248 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6252 pr " if (tok[0] == '\\0')\n";
6253 pr " r->%s = -1;\n" name;
6254 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6255 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6258 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6259 assert false (* can never be an LVM column *)
6261 pr " tok = next;\n";
6264 pr " if (tok != NULL) {\n";
6265 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6272 pr "guestfs_int_lvm_%s_list *\n" typ;
6273 pr "parse_command_line_%ss (void)\n" typ;
6275 pr " char *out, *err;\n";
6276 pr " char *p, *pend;\n";
6278 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6279 pr " void *newp;\n";
6281 pr " ret = malloc (sizeof *ret);\n";
6282 pr " if (!ret) {\n";
6283 pr " reply_with_perror (\"malloc\");\n";
6284 pr " return NULL;\n";
6287 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6288 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6290 pr " r = command (&out, &err,\n";
6291 pr " \"lvm\", \"%ss\",\n" typ;
6292 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6293 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6294 pr " if (r == -1) {\n";
6295 pr " reply_with_error (\"%%s\", err);\n";
6296 pr " free (out);\n";
6297 pr " free (err);\n";
6298 pr " free (ret);\n";
6299 pr " return NULL;\n";
6302 pr " free (err);\n";
6304 pr " /* Tokenize each line of the output. */\n";
6307 pr " while (p) {\n";
6308 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6309 pr " if (pend) {\n";
6310 pr " *pend = '\\0';\n";
6314 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6317 pr " if (!*p) { /* Empty line? Skip it. */\n";
6322 pr " /* Allocate some space to store this next entry. */\n";
6323 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6324 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6325 pr " if (newp == NULL) {\n";
6326 pr " reply_with_perror (\"realloc\");\n";
6327 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6328 pr " free (ret);\n";
6329 pr " free (out);\n";
6330 pr " return NULL;\n";
6332 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6334 pr " /* Tokenize the next entry. */\n";
6335 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6336 pr " if (r == -1) {\n";
6337 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6338 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6339 pr " free (ret);\n";
6340 pr " free (out);\n";
6341 pr " return NULL;\n";
6348 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6350 pr " free (out);\n";
6351 pr " return ret;\n";
6354 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6356 (* Generate a list of function names, for debugging in the daemon.. *)
6357 and generate_daemon_names () =
6358 generate_header CStyle GPLv2plus;
6360 pr "#include <config.h>\n";
6362 pr "#include \"daemon.h\"\n";
6365 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6366 pr "const char *function_names[] = {\n";
6368 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6372 (* Generate the optional groups for the daemon to implement
6373 * guestfs_available.
6375 and generate_daemon_optgroups_c () =
6376 generate_header CStyle GPLv2plus;
6378 pr "#include <config.h>\n";
6380 pr "#include \"daemon.h\"\n";
6381 pr "#include \"optgroups.h\"\n";
6384 pr "struct optgroup optgroups[] = {\n";
6387 pr " { \"%s\", optgroup_%s_available },\n" group group
6389 pr " { NULL, NULL }\n";
6392 and generate_daemon_optgroups_h () =
6393 generate_header CStyle GPLv2plus;
6397 pr "extern int optgroup_%s_available (void);\n" group
6400 (* Generate the tests. *)
6401 and generate_tests () =
6402 generate_header CStyle GPLv2plus;
6409 #include <sys/types.h>
6412 #include \"guestfs.h\"
6413 #include \"guestfs-internal.h\"
6415 static guestfs_h *g;
6416 static int suppress_error = 0;
6418 static void print_error (guestfs_h *g, void *data, const char *msg)
6420 if (!suppress_error)
6421 fprintf (stderr, \"%%s\\n\", msg);
6424 /* FIXME: nearly identical code appears in fish.c */
6425 static void print_strings (char *const *argv)
6429 for (argc = 0; argv[argc] != NULL; ++argc)
6430 printf (\"\\t%%s\\n\", argv[argc]);
6434 static void print_table (char const *const *argv)
6438 for (i = 0; argv[i] != NULL; i += 2)
6439 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6445 (* Generate a list of commands which are not tested anywhere. *)
6446 pr "static void no_test_warnings (void)\n";
6449 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6451 fun (_, _, _, _, tests, _, _) ->
6452 let tests = filter_map (
6454 | (_, (Always|If _|Unless _), test) -> Some test
6455 | (_, Disabled, _) -> None
6457 let seq = List.concat (List.map seq_of_test tests) in
6458 let cmds_tested = List.map List.hd seq in
6459 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6463 fun (name, _, _, _, _, _, _) ->
6464 if not (Hashtbl.mem hash name) then
6465 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6471 (* Generate the actual tests. Note that we generate the tests
6472 * in reverse order, deliberately, so that (in general) the
6473 * newest tests run first. This makes it quicker and easier to
6478 fun (name, _, _, flags, tests, _, _) ->
6479 mapi (generate_one_test name flags) tests
6480 ) (List.rev all_functions) in
6481 let test_names = List.concat test_names in
6482 let nr_tests = List.length test_names in
6485 int main (int argc, char *argv[])
6488 unsigned long int n_failed = 0;
6489 const char *filename;
6491 int nr_tests, test_num = 0;
6493 setbuf (stdout, NULL);
6495 no_test_warnings ();
6497 g = guestfs_create ();
6499 printf (\"guestfs_create FAILED\\n\");
6500 exit (EXIT_FAILURE);
6503 guestfs_set_error_handler (g, print_error, NULL);
6505 guestfs_set_path (g, \"../appliance\");
6507 filename = \"test1.img\";
6508 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6511 exit (EXIT_FAILURE);
6513 if (lseek (fd, %d, SEEK_SET) == -1) {
6517 exit (EXIT_FAILURE);
6519 if (write (fd, &c, 1) == -1) {
6523 exit (EXIT_FAILURE);
6525 if (close (fd) == -1) {
6528 exit (EXIT_FAILURE);
6530 if (guestfs_add_drive (g, filename) == -1) {
6531 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6532 exit (EXIT_FAILURE);
6535 filename = \"test2.img\";
6536 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6539 exit (EXIT_FAILURE);
6541 if (lseek (fd, %d, SEEK_SET) == -1) {
6545 exit (EXIT_FAILURE);
6547 if (write (fd, &c, 1) == -1) {
6551 exit (EXIT_FAILURE);
6553 if (close (fd) == -1) {
6556 exit (EXIT_FAILURE);
6558 if (guestfs_add_drive (g, filename) == -1) {
6559 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6560 exit (EXIT_FAILURE);
6563 filename = \"test3.img\";
6564 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6567 exit (EXIT_FAILURE);
6569 if (lseek (fd, %d, SEEK_SET) == -1) {
6573 exit (EXIT_FAILURE);
6575 if (write (fd, &c, 1) == -1) {
6579 exit (EXIT_FAILURE);
6581 if (close (fd) == -1) {
6584 exit (EXIT_FAILURE);
6586 if (guestfs_add_drive (g, filename) == -1) {
6587 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6588 exit (EXIT_FAILURE);
6591 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6592 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6593 exit (EXIT_FAILURE);
6596 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6599 if (guestfs_launch (g) == -1) {
6600 printf (\"guestfs_launch FAILED\\n\");
6601 exit (EXIT_FAILURE);
6604 /* Cancel previous alarm. */
6609 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6613 pr " test_num++;\n";
6614 pr " if (guestfs_get_verbose (g))\n";
6615 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6616 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6617 pr " if (%s () == -1) {\n" test_name;
6618 pr " printf (\"%s FAILED\\n\");\n" test_name;
6619 pr " n_failed++;\n";
6624 pr " guestfs_close (g);\n";
6625 pr " unlink (\"test1.img\");\n";
6626 pr " unlink (\"test2.img\");\n";
6627 pr " unlink (\"test3.img\");\n";
6630 pr " if (n_failed > 0) {\n";
6631 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6632 pr " exit (EXIT_FAILURE);\n";
6636 pr " exit (EXIT_SUCCESS);\n";
6639 and generate_one_test name flags i (init, prereq, test) =
6640 let test_name = sprintf "test_%s_%d" name i in
6643 static int %s_skip (void)
6647 str = getenv (\"TEST_ONLY\");
6649 return strstr (str, \"%s\") == NULL;
6650 str = getenv (\"SKIP_%s\");
6651 if (str && STREQ (str, \"1\")) return 1;
6652 str = getenv (\"SKIP_TEST_%s\");
6653 if (str && STREQ (str, \"1\")) return 1;
6657 " test_name name (String.uppercase test_name) (String.uppercase name);
6660 | Disabled | Always -> ()
6661 | If code | Unless code ->
6662 pr "static int %s_prereq (void)\n" test_name;
6670 static int %s (void)
6673 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6677 " test_name test_name test_name;
6679 (* Optional functions should only be tested if the relevant
6680 * support is available in the daemon.
6686 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6688 pr " suppress_error = 1;\n";
6689 pr " r = guestfs_available (g, (char **) groups);\n";
6690 pr " suppress_error = 0;\n";
6691 pr " if (r == -1) {\n";
6692 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6701 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6703 pr " if (! %s_prereq ()) {\n" test_name;
6704 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6708 generate_one_test_body name i test_name init test;
6710 pr " if (%s_prereq ()) {\n" test_name;
6711 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6715 generate_one_test_body name i test_name init test;
6717 generate_one_test_body name i test_name init test
6725 and generate_one_test_body name i test_name init test =
6727 | InitNone (* XXX at some point, InitNone and InitEmpty became
6728 * folded together as the same thing. Really we should
6729 * make InitNone do nothing at all, but the tests may
6730 * need to be checked to make sure this is OK.
6733 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6734 List.iter (generate_test_command_call test_name)
6735 [["blockdev_setrw"; "/dev/sda"];
6739 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6740 List.iter (generate_test_command_call test_name)
6741 [["blockdev_setrw"; "/dev/sda"];
6744 ["part_disk"; "/dev/sda"; "mbr"]]
6746 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6747 List.iter (generate_test_command_call test_name)
6748 [["blockdev_setrw"; "/dev/sda"];
6751 ["part_disk"; "/dev/sda"; "mbr"];
6752 ["mkfs"; "ext2"; "/dev/sda1"];
6753 ["mount_options"; ""; "/dev/sda1"; "/"]]
6754 | InitBasicFSonLVM ->
6755 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6757 List.iter (generate_test_command_call test_name)
6758 [["blockdev_setrw"; "/dev/sda"];
6761 ["part_disk"; "/dev/sda"; "mbr"];
6762 ["pvcreate"; "/dev/sda1"];
6763 ["vgcreate"; "VG"; "/dev/sda1"];
6764 ["lvcreate"; "LV"; "VG"; "8"];
6765 ["mkfs"; "ext2"; "/dev/VG/LV"];
6766 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6768 pr " /* InitISOFS for %s */\n" test_name;
6769 List.iter (generate_test_command_call test_name)
6770 [["blockdev_setrw"; "/dev/sda"];
6773 ["mount_ro"; "/dev/sdd"; "/"]]
6776 let get_seq_last = function
6778 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6781 let seq = List.rev seq in
6782 List.rev (List.tl seq), List.hd seq
6787 pr " /* TestRun for %s (%d) */\n" name i;
6788 List.iter (generate_test_command_call test_name) seq
6789 | TestOutput (seq, expected) ->
6790 pr " /* TestOutput for %s (%d) */\n" name i;
6791 pr " const char *expected = \"%s\";\n" (c_quote expected);
6792 let seq, last = get_seq_last seq in
6794 pr " if (STRNEQ (r, expected)) {\n";
6795 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6799 List.iter (generate_test_command_call test_name) seq;
6800 generate_test_command_call ~test test_name last
6801 | TestOutputList (seq, expected) ->
6802 pr " /* TestOutputList for %s (%d) */\n" name i;
6803 let seq, last = get_seq_last seq in
6807 pr " if (!r[%d]) {\n" i;
6808 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6809 pr " print_strings (r);\n";
6813 pr " const char *expected = \"%s\";\n" (c_quote str);
6814 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6815 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6820 pr " if (r[%d] != NULL) {\n" (List.length expected);
6821 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6823 pr " print_strings (r);\n";
6827 List.iter (generate_test_command_call test_name) seq;
6828 generate_test_command_call ~test test_name last
6829 | TestOutputListOfDevices (seq, expected) ->
6830 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6831 let seq, last = get_seq_last seq in
6835 pr " if (!r[%d]) {\n" i;
6836 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6837 pr " print_strings (r);\n";
6841 pr " const char *expected = \"%s\";\n" (c_quote str);
6842 pr " r[%d][5] = 's';\n" i;
6843 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6844 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6849 pr " if (r[%d] != NULL) {\n" (List.length expected);
6850 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6852 pr " print_strings (r);\n";
6856 List.iter (generate_test_command_call test_name) seq;
6857 generate_test_command_call ~test test_name last
6858 | TestOutputInt (seq, expected) ->
6859 pr " /* TestOutputInt for %s (%d) */\n" name i;
6860 let seq, last = get_seq_last seq in
6862 pr " if (r != %d) {\n" expected;
6863 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6869 List.iter (generate_test_command_call test_name) seq;
6870 generate_test_command_call ~test test_name last
6871 | TestOutputIntOp (seq, op, expected) ->
6872 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6873 let seq, last = get_seq_last seq in
6875 pr " if (! (r %s %d)) {\n" op expected;
6876 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6877 test_name op expected;
6882 List.iter (generate_test_command_call test_name) seq;
6883 generate_test_command_call ~test test_name last
6884 | TestOutputTrue seq ->
6885 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6886 let seq, last = get_seq_last seq in
6889 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6894 List.iter (generate_test_command_call test_name) seq;
6895 generate_test_command_call ~test test_name last
6896 | TestOutputFalse seq ->
6897 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6898 let seq, last = get_seq_last seq in
6901 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6906 List.iter (generate_test_command_call test_name) seq;
6907 generate_test_command_call ~test test_name last
6908 | TestOutputLength (seq, expected) ->
6909 pr " /* TestOutputLength for %s (%d) */\n" name i;
6910 let seq, last = get_seq_last seq in
6913 pr " for (j = 0; j < %d; ++j)\n" expected;
6914 pr " if (r[j] == NULL) {\n";
6915 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6917 pr " print_strings (r);\n";
6920 pr " if (r[j] != NULL) {\n";
6921 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6923 pr " print_strings (r);\n";
6927 List.iter (generate_test_command_call test_name) seq;
6928 generate_test_command_call ~test test_name last
6929 | TestOutputBuffer (seq, expected) ->
6930 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6931 pr " const char *expected = \"%s\";\n" (c_quote expected);
6932 let seq, last = get_seq_last seq in
6933 let len = String.length expected in
6935 pr " if (size != %d) {\n" len;
6936 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6939 pr " if (STRNEQLEN (r, expected, size)) {\n";
6940 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6944 List.iter (generate_test_command_call test_name) seq;
6945 generate_test_command_call ~test test_name last
6946 | TestOutputStruct (seq, checks) ->
6947 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6948 let seq, last = get_seq_last seq in
6952 | CompareWithInt (field, expected) ->
6953 pr " if (r->%s != %d) {\n" field expected;
6954 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6955 test_name field expected;
6956 pr " (int) r->%s);\n" field;
6959 | CompareWithIntOp (field, op, expected) ->
6960 pr " if (!(r->%s %s %d)) {\n" field op expected;
6961 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6962 test_name field op expected;
6963 pr " (int) r->%s);\n" field;
6966 | CompareWithString (field, expected) ->
6967 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6968 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6969 test_name field expected;
6970 pr " r->%s);\n" field;
6973 | CompareFieldsIntEq (field1, field2) ->
6974 pr " if (r->%s != r->%s) {\n" field1 field2;
6975 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6976 test_name field1 field2;
6977 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6980 | CompareFieldsStrEq (field1, field2) ->
6981 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6982 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6983 test_name field1 field2;
6984 pr " r->%s, r->%s);\n" field1 field2;
6989 List.iter (generate_test_command_call test_name) seq;
6990 generate_test_command_call ~test test_name last
6991 | TestLastFail seq ->
6992 pr " /* TestLastFail for %s (%d) */\n" name i;
6993 let seq, last = get_seq_last seq in
6994 List.iter (generate_test_command_call test_name) seq;
6995 generate_test_command_call test_name ~expect_error:true last
6997 (* Generate the code to run a command, leaving the result in 'r'.
6998 * If you expect to get an error then you should set expect_error:true.
7000 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7002 | [] -> assert false
7004 (* Look up the command to find out what args/ret it has. *)
7007 let _, style, _, _, _, _, _ =
7008 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7011 failwithf "%s: in test, command %s was not found" test_name name in
7013 if List.length (snd style) <> List.length args then
7014 failwithf "%s: in test, wrong number of args given to %s"
7021 | OptString n, "NULL" -> ()
7024 | Dev_or_Path n, arg
7026 | OptString n, arg ->
7027 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7031 | FileIn _, _ | FileOut _, _ -> ()
7032 | StringList n, "" | DeviceList n, "" ->
7033 pr " const char *const %s[1] = { NULL };\n" n
7034 | StringList n, arg | DeviceList n, arg ->
7035 let strs = string_split " " arg in
7038 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7040 pr " const char *const %s[] = {\n" n;
7042 fun i _ -> pr " %s_%d,\n" n i
7046 ) (List.combine (snd style) args);
7049 match fst style with
7050 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7051 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7052 | RConstString _ | RConstOptString _ ->
7053 pr " const char *r;\n"; "NULL"
7054 | RString _ -> pr " char *r;\n"; "NULL"
7055 | RStringList _ | RHashtable _ ->
7059 | RStruct (_, typ) ->
7060 pr " struct guestfs_%s *r;\n" typ; "NULL"
7061 | RStructList (_, typ) ->
7062 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7065 pr " size_t size;\n";
7068 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7069 pr " r = guestfs_%s (g" name;
7071 (* Generate the parameters. *)
7074 | OptString _, "NULL" -> pr ", NULL"
7076 | Device n, _ | Dev_or_Path n, _
7080 | FileIn _, arg | FileOut _, arg ->
7081 pr ", \"%s\"" (c_quote arg)
7082 | StringList n, _ | DeviceList n, _ ->
7083 pr ", (char **) %s" n
7086 try int_of_string arg
7087 with Failure "int_of_string" ->
7088 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7092 try Int64.of_string arg
7093 with Failure "int_of_string" ->
7094 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7097 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7098 ) (List.combine (snd style) args);
7100 (match fst style with
7101 | RBufferOut _ -> pr ", &size"
7107 if not expect_error then
7108 pr " if (r == %s)\n" error_code
7110 pr " if (r != %s)\n" error_code;
7113 (* Insert the test code. *)
7119 (match fst style with
7120 | RErr | RInt _ | RInt64 _ | RBool _
7121 | RConstString _ | RConstOptString _ -> ()
7122 | RString _ | RBufferOut _ -> pr " free (r);\n"
7123 | RStringList _ | RHashtable _ ->
7124 pr " for (i = 0; r[i] != NULL; ++i)\n";
7125 pr " free (r[i]);\n";
7127 | RStruct (_, typ) ->
7128 pr " guestfs_free_%s (r);\n" typ
7129 | RStructList (_, typ) ->
7130 pr " guestfs_free_%s_list (r);\n" typ
7136 let str = replace_str str "\r" "\\r" in
7137 let str = replace_str str "\n" "\\n" in
7138 let str = replace_str str "\t" "\\t" in
7139 let str = replace_str str "\000" "\\0" in
7142 (* Generate a lot of different functions for guestfish. *)
7143 and generate_fish_cmds () =
7144 generate_header CStyle GPLv2plus;
7148 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7150 let all_functions_sorted =
7152 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7153 ) all_functions_sorted in
7155 pr "#include <config.h>\n";
7157 pr "#include <stdio.h>\n";
7158 pr "#include <stdlib.h>\n";
7159 pr "#include <string.h>\n";
7160 pr "#include <inttypes.h>\n";
7162 pr "#include <guestfs.h>\n";
7163 pr "#include \"c-ctype.h\"\n";
7164 pr "#include \"full-write.h\"\n";
7165 pr "#include \"xstrtol.h\"\n";
7166 pr "#include \"fish.h\"\n";
7169 (* list_commands function, which implements guestfish -h *)
7170 pr "void list_commands (void)\n";
7172 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7173 pr " list_builtin_commands ();\n";
7175 fun (name, _, _, flags, _, shortdesc, _) ->
7176 let name = replace_char name '_' '-' in
7177 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7179 ) all_functions_sorted;
7180 pr " printf (\" %%s\\n\",";
7181 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7185 (* display_command function, which implements guestfish -h cmd *)
7186 pr "void display_command (const char *cmd)\n";
7189 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7190 let name2 = replace_char name '_' '-' in
7192 try find_map (function FishAlias n -> Some n | _ -> None) flags
7193 with Not_found -> name in
7194 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7196 match snd style with
7200 name2 (String.concat " " (List.map name_of_argt args)) in
7203 if List.mem ProtocolLimitWarning flags then
7204 ("\n\n" ^ protocol_limit_warning)
7207 (* For DangerWillRobinson commands, we should probably have
7208 * guestfish prompt before allowing you to use them (especially
7209 * in interactive mode). XXX
7213 if List.mem DangerWillRobinson flags then
7214 ("\n\n" ^ danger_will_robinson)
7219 match deprecation_notice flags with
7221 | Some txt -> "\n\n" ^ txt in
7223 let describe_alias =
7224 if name <> alias then
7225 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7229 pr "STRCASEEQ (cmd, \"%s\")" name;
7230 if name <> name2 then
7231 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7232 if name <> alias then
7233 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7235 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7237 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7238 "=head1 DESCRIPTION\n\n" ^
7239 longdesc ^ warnings ^ describe_alias);
7242 pr " display_builtin_command (cmd);\n";
7246 let emit_print_list_function typ =
7247 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7250 pr " unsigned int i;\n";
7252 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7253 pr " printf (\"[%%d] = {\\n\", i);\n";
7254 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7255 pr " printf (\"}\\n\");\n";
7261 (* print_* functions *)
7265 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7267 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7270 pr " unsigned int i;\n";
7276 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7278 pr " printf (\"%%s%s: \", indent);\n" name;
7279 pr " for (i = 0; i < 32; ++i)\n";
7280 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7281 pr " printf (\"\\n\");\n"
7283 pr " printf (\"%%s%s: \", indent);\n" name;
7284 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7285 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7286 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7288 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7289 pr " printf (\"\\n\");\n"
7290 | name, (FUInt64|FBytes) ->
7291 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7294 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7297 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7300 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7303 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7305 | name, FOptPercent ->
7306 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7307 typ name name typ name;
7308 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7314 (* Emit a print_TYPE_list function definition only if that function is used. *)
7317 | typ, (RStructListOnly | RStructAndList) ->
7318 (* generate the function for typ *)
7319 emit_print_list_function typ
7320 | typ, _ -> () (* empty *)
7321 ) (rstructs_used_by all_functions);
7323 (* Emit a print_TYPE function definition only if that function is used. *)
7326 | typ, (RStructOnly | RStructAndList) ->
7327 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7329 pr " print_%s_indent (%s, \"\");\n" typ typ;
7332 | typ, _ -> () (* empty *)
7333 ) (rstructs_used_by all_functions);
7335 (* run_<action> actions *)
7337 fun (name, style, _, flags, _, _, _) ->
7338 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7340 (match fst style with
7343 | RBool _ -> pr " int r;\n"
7344 | RInt64 _ -> pr " int64_t r;\n"
7345 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7346 | RString _ -> pr " char *r;\n"
7347 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7348 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7349 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7352 pr " size_t size;\n";
7360 | FileOut n -> pr " const char *%s;\n" n
7362 | Dev_or_Path n -> pr " char *%s;\n" n
7363 | StringList n | DeviceList n -> pr " char **%s;\n" n
7364 | Bool n -> pr " int %s;\n" n
7365 | Int n -> pr " int %s;\n" n
7366 | Int64 n -> pr " int64_t %s;\n" n
7369 (* Check and convert parameters. *)
7370 let argc_expected = List.length (snd style) in
7371 pr " if (argc != %d) {\n" argc_expected;
7372 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7374 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7378 let parse_integer fn fntyp rtyp range name i =
7380 pr " strtol_error xerr;\n";
7381 pr " %s r;\n" fntyp;
7383 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7384 pr " if (xerr != LONGINT_OK) {\n";
7385 pr " fprintf (stderr,\n";
7386 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7387 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7392 | Some (min, max, comment) ->
7393 pr " /* %s */\n" comment;
7394 pr " if (r < %s || r > %s) {\n" min max;
7395 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7399 pr " /* The check above should ensure this assignment does not overflow. */\n";
7401 pr " %s = r;\n" name;
7410 pr " %s = argv[%d];\n" name i
7412 | Dev_or_Path name ->
7413 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7414 pr " if (%s == NULL) return -1;\n" name
7416 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7419 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7422 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7424 | StringList name | DeviceList name ->
7425 pr " %s = parse_string_list (argv[%d]);\n" name i;
7426 pr " if (%s == NULL) return -1;\n" name;
7428 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7431 let min = "(-(2LL<<30))"
7432 and max = "((2LL<<30)-1)"
7434 "The Int type in the generator is a signed 31 bit int." in
7435 Some (min, max, comment) in
7436 parse_integer "xstrtoll" "long long" "int" range name i
7438 parse_integer "xstrtoll" "long long" "int64_t" None name i
7441 (* Call C API function. *)
7443 try find_map (function FishAction n -> Some n | _ -> None) flags
7444 with Not_found -> sprintf "guestfs_%s" name in
7446 generate_c_call_args ~handle:"g" style;
7451 | Device name | String name
7452 | OptString name | FileIn name | FileOut name | Bool name
7453 | Int name | Int64 name -> ()
7454 | Pathname name | Dev_or_Path name ->
7455 pr " free (%s);\n" name
7456 | StringList name | DeviceList name ->
7457 pr " free_strings (%s);\n" name
7460 (* Check return value for errors and display command results. *)
7461 (match fst style with
7462 | RErr -> pr " return r;\n"
7464 pr " if (r == -1) return -1;\n";
7465 pr " printf (\"%%d\\n\", r);\n";
7468 pr " if (r == -1) return -1;\n";
7469 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7472 pr " if (r == -1) return -1;\n";
7473 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7476 pr " if (r == NULL) return -1;\n";
7477 pr " printf (\"%%s\\n\", r);\n";
7479 | RConstOptString _ ->
7480 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7483 pr " if (r == NULL) return -1;\n";
7484 pr " printf (\"%%s\\n\", r);\n";
7488 pr " if (r == NULL) return -1;\n";
7489 pr " print_strings (r);\n";
7490 pr " free_strings (r);\n";
7492 | RStruct (_, typ) ->
7493 pr " if (r == NULL) return -1;\n";
7494 pr " print_%s (r);\n" typ;
7495 pr " guestfs_free_%s (r);\n" typ;
7497 | RStructList (_, typ) ->
7498 pr " if (r == NULL) return -1;\n";
7499 pr " print_%s_list (r);\n" typ;
7500 pr " guestfs_free_%s_list (r);\n" typ;
7503 pr " if (r == NULL) return -1;\n";
7504 pr " print_table (r);\n";
7505 pr " free_strings (r);\n";
7508 pr " if (r == NULL) return -1;\n";
7509 pr " if (full_write (1, r, size) != size) {\n";
7510 pr " perror (\"write\");\n";
7521 (* run_action function *)
7522 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7525 fun (name, _, _, flags, _, _, _) ->
7526 let name2 = replace_char name '_' '-' in
7528 try find_map (function FishAlias n -> Some n | _ -> None) flags
7529 with Not_found -> name in
7531 pr "STRCASEEQ (cmd, \"%s\")" name;
7532 if name <> name2 then
7533 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7534 if name <> alias then
7535 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7537 pr " return run_%s (cmd, argc, argv);\n" name;
7541 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7542 pr " if (command_num == 1)\n";
7543 pr " extended_help_message ();\n";
7550 (* Readline completion for guestfish. *)
7551 and generate_fish_completion () =
7552 generate_header CStyle GPLv2plus;
7556 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7566 #ifdef HAVE_LIBREADLINE
7567 #include <readline/readline.h>
7572 #ifdef HAVE_LIBREADLINE
7574 static const char *const commands[] = {
7575 BUILTIN_COMMANDS_FOR_COMPLETION,
7578 (* Get the commands, including the aliases. They don't need to be
7579 * sorted - the generator() function just does a dumb linear search.
7583 fun (name, _, _, flags, _, _, _) ->
7584 let name2 = replace_char name '_' '-' in
7586 try find_map (function FishAlias n -> Some n | _ -> None) flags
7587 with Not_found -> name in
7589 if name <> alias then [name2; alias] else [name2]
7591 let commands = List.flatten commands in
7593 List.iter (pr " \"%s\",\n") commands;
7599 generator (const char *text, int state)
7601 static int index, len;
7606 len = strlen (text);
7609 rl_attempted_completion_over = 1;
7611 while ((name = commands[index]) != NULL) {
7613 if (STRCASEEQLEN (name, text, len))
7614 return strdup (name);
7620 #endif /* HAVE_LIBREADLINE */
7622 #ifdef HAVE_RL_COMPLETION_MATCHES
7623 #define RL_COMPLETION_MATCHES rl_completion_matches
7625 #ifdef HAVE_COMPLETION_MATCHES
7626 #define RL_COMPLETION_MATCHES completion_matches
7628 #endif /* else just fail if we don't have either symbol */
7631 do_completion (const char *text, int start, int end)
7633 char **matches = NULL;
7635 #ifdef HAVE_LIBREADLINE
7636 rl_completion_append_character = ' ';
7639 matches = RL_COMPLETION_MATCHES (text, generator);
7640 else if (complete_dest_paths)
7641 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7648 (* Generate the POD documentation for guestfish. *)
7649 and generate_fish_actions_pod () =
7650 let all_functions_sorted =
7652 fun (_, _, _, flags, _, _, _) ->
7653 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7654 ) all_functions_sorted in
7656 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7659 fun (name, style, _, flags, _, _, longdesc) ->
7661 Str.global_substitute rex (
7664 try Str.matched_group 1 s
7666 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7667 "C<" ^ replace_char sub '_' '-' ^ ">"
7669 let name = replace_char name '_' '-' in
7671 try find_map (function FishAlias n -> Some n | _ -> None) flags
7672 with Not_found -> name in
7674 pr "=head2 %s" name;
7675 if name <> alias then
7682 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7683 | OptString n -> pr " %s" n
7684 | StringList n | DeviceList n -> pr " '%s ...'" n
7685 | Bool _ -> pr " true|false"
7686 | Int n -> pr " %s" n
7687 | Int64 n -> pr " %s" n
7688 | FileIn n | FileOut n -> pr " (%s|-)" n
7692 pr "%s\n\n" longdesc;
7694 if List.exists (function FileIn _ | FileOut _ -> true
7695 | _ -> false) (snd style) then
7696 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7698 if List.mem ProtocolLimitWarning flags then
7699 pr "%s\n\n" protocol_limit_warning;
7701 if List.mem DangerWillRobinson flags then
7702 pr "%s\n\n" danger_will_robinson;
7704 match deprecation_notice flags with
7706 | Some txt -> pr "%s\n\n" txt
7707 ) all_functions_sorted
7709 (* Generate a C function prototype. *)
7710 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7711 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7713 ?handle name style =
7714 if extern then pr "extern ";
7715 if static then pr "static ";
7716 (match fst style with
7718 | RInt _ -> pr "int "
7719 | RInt64 _ -> pr "int64_t "
7720 | RBool _ -> pr "int "
7721 | RConstString _ | RConstOptString _ -> pr "const char *"
7722 | RString _ | RBufferOut _ -> pr "char *"
7723 | RStringList _ | RHashtable _ -> pr "char **"
7724 | RStruct (_, typ) ->
7725 if not in_daemon then pr "struct guestfs_%s *" typ
7726 else pr "guestfs_int_%s *" typ
7727 | RStructList (_, typ) ->
7728 if not in_daemon then pr "struct guestfs_%s_list *" typ
7729 else pr "guestfs_int_%s_list *" typ
7731 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7732 pr "%s%s (" prefix name;
7733 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7736 let comma = ref false in
7739 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7743 if single_line then pr ", " else pr ",\n\t\t"
7750 | Device n | Dev_or_Path n
7754 pr "const char *%s" n
7755 | StringList n | DeviceList n ->
7757 pr "char *const *%s" n
7758 | Bool n -> next (); pr "int %s" n
7759 | Int n -> next (); pr "int %s" n
7760 | Int64 n -> next (); pr "int64_t %s" n
7763 if not in_daemon then (next (); pr "const char *%s" n)
7765 if is_RBufferOut then (next (); pr "size_t *size_r");
7768 if semicolon then pr ";";
7769 if newline then pr "\n"
7771 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7772 and generate_c_call_args ?handle ?(decl = false) style =
7774 let comma = ref false in
7776 if !comma then pr ", ";
7781 | Some handle -> pr "%s" handle; comma := true
7786 pr "%s" (name_of_argt arg)
7788 (* For RBufferOut calls, add implicit &size parameter. *)
7790 match fst style with
7798 (* Generate the OCaml bindings interface. *)
7799 and generate_ocaml_mli () =
7800 generate_header OCamlStyle LGPLv2plus;
7803 (** For API documentation you should refer to the C API
7804 in the guestfs(3) manual page. The OCaml API uses almost
7805 exactly the same calls. *)
7808 (** A [guestfs_h] handle. *)
7810 exception Error of string
7811 (** This exception is raised when there is an error. *)
7813 exception Handle_closed of string
7814 (** This exception is raised if you use a {!Guestfs.t} handle
7815 after calling {!close} on it. The string is the name of
7818 val create : unit -> t
7819 (** Create a {!Guestfs.t} handle. *)
7821 val close : t -> unit
7822 (** Close the {!Guestfs.t} handle and free up all resources used
7825 Handles are closed by the garbage collector when they become
7826 unreferenced, but callers can call this in order to provide
7827 predictable cleanup. *)
7830 generate_ocaml_structure_decls ();
7834 fun (name, style, _, _, _, shortdesc, _) ->
7835 generate_ocaml_prototype name style;
7836 pr "(** %s *)\n" shortdesc;
7838 ) all_functions_sorted
7840 (* Generate the OCaml bindings implementation. *)
7841 and generate_ocaml_ml () =
7842 generate_header OCamlStyle LGPLv2plus;
7847 exception Error of string
7848 exception Handle_closed of string
7850 external create : unit -> t = \"ocaml_guestfs_create\"
7851 external close : t -> unit = \"ocaml_guestfs_close\"
7853 (* Give the exceptions names, so they can be raised from the C code. *)
7855 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7856 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7860 generate_ocaml_structure_decls ();
7864 fun (name, style, _, _, _, shortdesc, _) ->
7865 generate_ocaml_prototype ~is_external:true name style;
7866 ) all_functions_sorted
7868 (* Generate the OCaml bindings C implementation. *)
7869 and generate_ocaml_c () =
7870 generate_header CStyle LGPLv2plus;
7877 #include <caml/config.h>
7878 #include <caml/alloc.h>
7879 #include <caml/callback.h>
7880 #include <caml/fail.h>
7881 #include <caml/memory.h>
7882 #include <caml/mlvalues.h>
7883 #include <caml/signals.h>
7885 #include <guestfs.h>
7887 #include \"guestfs_c.h\"
7889 /* Copy a hashtable of string pairs into an assoc-list. We return
7890 * the list in reverse order, but hashtables aren't supposed to be
7893 static CAMLprim value
7894 copy_table (char * const * argv)
7897 CAMLlocal5 (rv, pairv, kv, vv, cons);
7901 for (i = 0; argv[i] != NULL; i += 2) {
7902 kv = caml_copy_string (argv[i]);
7903 vv = caml_copy_string (argv[i+1]);
7904 pairv = caml_alloc (2, 0);
7905 Store_field (pairv, 0, kv);
7906 Store_field (pairv, 1, vv);
7907 cons = caml_alloc (2, 0);
7908 Store_field (cons, 1, rv);
7910 Store_field (cons, 0, pairv);
7918 (* Struct copy functions. *)
7920 let emit_ocaml_copy_list_function typ =
7921 pr "static CAMLprim value\n";
7922 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7924 pr " CAMLparam0 ();\n";
7925 pr " CAMLlocal2 (rv, v);\n";
7926 pr " unsigned int i;\n";
7928 pr " if (%ss->len == 0)\n" typ;
7929 pr " CAMLreturn (Atom (0));\n";
7931 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7932 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7933 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7934 pr " caml_modify (&Field (rv, i), v);\n";
7936 pr " CAMLreturn (rv);\n";
7944 let has_optpercent_col =
7945 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7947 pr "static CAMLprim value\n";
7948 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7950 pr " CAMLparam0 ();\n";
7951 if has_optpercent_col then
7952 pr " CAMLlocal3 (rv, v, v2);\n"
7954 pr " CAMLlocal2 (rv, v);\n";
7956 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7961 pr " v = caml_copy_string (%s->%s);\n" typ name
7963 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7964 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7967 pr " v = caml_alloc_string (32);\n";
7968 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7969 | name, (FBytes|FInt64|FUInt64) ->
7970 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7971 | name, (FInt32|FUInt32) ->
7972 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7973 | name, FOptPercent ->
7974 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7975 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7976 pr " v = caml_alloc (1, 0);\n";
7977 pr " Store_field (v, 0, v2);\n";
7978 pr " } else /* None */\n";
7979 pr " v = Val_int (0);\n";
7981 pr " v = Val_int (%s->%s);\n" typ name
7983 pr " Store_field (rv, %d, v);\n" i
7985 pr " CAMLreturn (rv);\n";
7990 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7993 | typ, (RStructListOnly | RStructAndList) ->
7994 (* generate the function for typ *)
7995 emit_ocaml_copy_list_function typ
7996 | typ, _ -> () (* empty *)
7997 ) (rstructs_used_by all_functions);
8001 fun (name, style, _, _, _, _, _) ->
8002 pr "/* Automatically generated wrapper for function\n";
8004 generate_ocaml_prototype name style;
8009 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8011 let needs_extra_vs =
8012 match fst style with RConstOptString _ -> true | _ -> false in
8014 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8015 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8016 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8019 pr "CAMLprim value\n";
8020 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8021 List.iter (pr ", value %s") (List.tl params);
8026 | [p1; p2; p3; p4; p5] ->
8027 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8028 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8029 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8030 pr " CAMLxparam%d (%s);\n"
8031 (List.length rest) (String.concat ", " rest)
8033 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8035 if not needs_extra_vs then
8036 pr " CAMLlocal1 (rv);\n"
8038 pr " CAMLlocal3 (rv, v, v2);\n";
8041 pr " guestfs_h *g = Guestfs_val (gv);\n";
8042 pr " if (g == NULL)\n";
8043 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8049 | Device n | Dev_or_Path n
8053 pr " const char *%s = String_val (%sv);\n" n n
8055 pr " const char *%s =\n" n;
8056 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8058 | StringList n | DeviceList n ->
8059 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8061 pr " int %s = Bool_val (%sv);\n" n n
8063 pr " int %s = Int_val (%sv);\n" n n
8065 pr " int64_t %s = Int64_val (%sv);\n" n n
8068 match fst style with
8069 | RErr -> pr " int r;\n"; "-1"
8070 | RInt _ -> pr " int r;\n"; "-1"
8071 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8072 | RBool _ -> pr " int r;\n"; "-1"
8073 | RConstString _ | RConstOptString _ ->
8074 pr " const char *r;\n"; "NULL"
8075 | RString _ -> pr " char *r;\n"; "NULL"
8080 | RStruct (_, typ) ->
8081 pr " struct guestfs_%s *r;\n" typ; "NULL"
8082 | RStructList (_, typ) ->
8083 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8090 pr " size_t size;\n";
8094 pr " caml_enter_blocking_section ();\n";
8095 pr " r = guestfs_%s " name;
8096 generate_c_call_args ~handle:"g" style;
8098 pr " caml_leave_blocking_section ();\n";
8102 | StringList n | DeviceList n ->
8103 pr " ocaml_guestfs_free_strings (%s);\n" n;
8104 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8105 | Bool _ | Int _ | Int64 _
8106 | FileIn _ | FileOut _ -> ()
8109 pr " if (r == %s)\n" error_code;
8110 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8113 (match fst style with
8114 | RErr -> pr " rv = Val_unit;\n"
8115 | RInt _ -> pr " rv = Val_int (r);\n"
8117 pr " rv = caml_copy_int64 (r);\n"
8118 | RBool _ -> pr " rv = Val_bool (r);\n"
8120 pr " rv = caml_copy_string (r);\n"
8121 | RConstOptString _ ->
8122 pr " if (r) { /* Some string */\n";
8123 pr " v = caml_alloc (1, 0);\n";
8124 pr " v2 = caml_copy_string (r);\n";
8125 pr " Store_field (v, 0, v2);\n";
8126 pr " } else /* None */\n";
8127 pr " v = Val_int (0);\n";
8129 pr " rv = caml_copy_string (r);\n";
8132 pr " rv = caml_copy_string_array ((const char **) r);\n";
8133 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8135 | RStruct (_, typ) ->
8136 pr " rv = copy_%s (r);\n" typ;
8137 pr " guestfs_free_%s (r);\n" typ;
8138 | RStructList (_, typ) ->
8139 pr " rv = copy_%s_list (r);\n" typ;
8140 pr " guestfs_free_%s_list (r);\n" typ;
8142 pr " rv = copy_table (r);\n";
8143 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8146 pr " rv = caml_alloc_string (size);\n";
8147 pr " memcpy (String_val (rv), r, size);\n";
8150 pr " CAMLreturn (rv);\n";
8154 if List.length params > 5 then (
8155 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8156 pr "CAMLprim value ";
8157 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8158 pr "CAMLprim value\n";
8159 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8161 pr " return ocaml_guestfs_%s (argv[0]" name;
8162 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8167 ) all_functions_sorted
8169 and generate_ocaml_structure_decls () =
8172 pr "type %s = {\n" typ;
8175 | name, FString -> pr " %s : string;\n" name
8176 | name, FBuffer -> pr " %s : string;\n" name
8177 | name, FUUID -> pr " %s : string;\n" name
8178 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8179 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8180 | name, FChar -> pr " %s : char;\n" name
8181 | name, FOptPercent -> pr " %s : float option;\n" name
8187 and generate_ocaml_prototype ?(is_external = false) name style =
8188 if is_external then pr "external " else pr "val ";
8189 pr "%s : t -> " name;
8192 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8193 | OptString _ -> pr "string option -> "
8194 | StringList _ | DeviceList _ -> pr "string array -> "
8195 | Bool _ -> pr "bool -> "
8196 | Int _ -> pr "int -> "
8197 | Int64 _ -> pr "int64 -> "
8199 (match fst style with
8200 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8201 | RInt _ -> pr "int"
8202 | RInt64 _ -> pr "int64"
8203 | RBool _ -> pr "bool"
8204 | RConstString _ -> pr "string"
8205 | RConstOptString _ -> pr "string option"
8206 | RString _ | RBufferOut _ -> pr "string"
8207 | RStringList _ -> pr "string array"
8208 | RStruct (_, typ) -> pr "%s" typ
8209 | RStructList (_, typ) -> pr "%s array" typ
8210 | RHashtable _ -> pr "(string * string) list"
8212 if is_external then (
8214 if List.length (snd style) + 1 > 5 then
8215 pr "\"ocaml_guestfs_%s_byte\" " name;
8216 pr "\"ocaml_guestfs_%s\"" name
8220 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8221 and generate_perl_xs () =
8222 generate_header CStyle LGPLv2plus;
8225 #include \"EXTERN.h\"
8229 #include <guestfs.h>
8232 #define PRId64 \"lld\"
8236 my_newSVll(long long val) {
8237 #ifdef USE_64_BIT_ALL
8238 return newSViv(val);
8242 len = snprintf(buf, 100, \"%%\" PRId64, val);
8243 return newSVpv(buf, len);
8248 #define PRIu64 \"llu\"
8252 my_newSVull(unsigned long long val) {
8253 #ifdef USE_64_BIT_ALL
8254 return newSVuv(val);
8258 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8259 return newSVpv(buf, len);
8263 /* http://www.perlmonks.org/?node_id=680842 */
8265 XS_unpack_charPtrPtr (SV *arg) {
8270 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8271 croak (\"array reference expected\");
8273 av = (AV *)SvRV (arg);
8274 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8276 croak (\"malloc failed\");
8278 for (i = 0; i <= av_len (av); i++) {
8279 SV **elem = av_fetch (av, i, 0);
8281 if (!elem || !*elem)
8282 croak (\"missing element in list\");
8284 ret[i] = SvPV_nolen (*elem);
8292 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8299 RETVAL = guestfs_create ();
8301 croak (\"could not create guestfs handle\");
8302 guestfs_set_error_handler (RETVAL, NULL, NULL);
8315 fun (name, style, _, _, _, _, _) ->
8316 (match fst style with
8317 | RErr -> pr "void\n"
8318 | RInt _ -> pr "SV *\n"
8319 | RInt64 _ -> pr "SV *\n"
8320 | RBool _ -> pr "SV *\n"
8321 | RConstString _ -> pr "SV *\n"
8322 | RConstOptString _ -> pr "SV *\n"
8323 | RString _ -> pr "SV *\n"
8324 | RBufferOut _ -> pr "SV *\n"
8326 | RStruct _ | RStructList _
8328 pr "void\n" (* all lists returned implictly on the stack *)
8330 (* Call and arguments. *)
8332 generate_c_call_args ~handle:"g" ~decl:true style;
8334 pr " guestfs_h *g;\n";
8338 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8341 (* http://www.perlmonks.org/?node_id=554277
8342 * Note that the implicit handle argument means we have
8343 * to add 1 to the ST(x) operator.
8345 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8346 | StringList n | DeviceList n -> pr " char **%s;\n" n
8347 | Bool n -> pr " int %s;\n" n
8348 | Int n -> pr " int %s;\n" n
8349 | Int64 n -> pr " int64_t %s;\n" n
8352 let do_cleanups () =
8355 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8356 | Bool _ | Int _ | Int64 _
8357 | FileIn _ | FileOut _ -> ()
8358 | StringList n | DeviceList n -> pr " free (%s);\n" n
8363 (match fst style with
8368 pr " r = guestfs_%s " name;
8369 generate_c_call_args ~handle:"g" style;
8372 pr " if (r == -1)\n";
8373 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8379 pr " %s = guestfs_%s " n name;
8380 generate_c_call_args ~handle:"g" style;
8383 pr " if (%s == -1)\n" n;
8384 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8385 pr " RETVAL = newSViv (%s);\n" n;
8390 pr " int64_t %s;\n" n;
8392 pr " %s = guestfs_%s " n name;
8393 generate_c_call_args ~handle:"g" style;
8396 pr " if (%s == -1)\n" n;
8397 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8398 pr " RETVAL = my_newSVll (%s);\n" n;
8403 pr " const char *%s;\n" n;
8405 pr " %s = guestfs_%s " n name;
8406 generate_c_call_args ~handle:"g" style;
8409 pr " if (%s == NULL)\n" n;
8410 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8411 pr " RETVAL = newSVpv (%s, 0);\n" n;
8414 | RConstOptString n ->
8416 pr " const char *%s;\n" n;
8418 pr " %s = guestfs_%s " n name;
8419 generate_c_call_args ~handle:"g" style;
8422 pr " if (%s == NULL)\n" n;
8423 pr " RETVAL = &PL_sv_undef;\n";
8425 pr " RETVAL = newSVpv (%s, 0);\n" n;
8430 pr " char *%s;\n" n;
8432 pr " %s = guestfs_%s " n name;
8433 generate_c_call_args ~handle:"g" style;
8436 pr " if (%s == NULL)\n" n;
8437 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8438 pr " RETVAL = newSVpv (%s, 0);\n" n;
8439 pr " free (%s);\n" n;
8442 | RStringList n | RHashtable n ->
8444 pr " char **%s;\n" n;
8447 pr " %s = guestfs_%s " n name;
8448 generate_c_call_args ~handle:"g" style;
8451 pr " if (%s == NULL)\n" n;
8452 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8453 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8454 pr " EXTEND (SP, n);\n";
8455 pr " for (i = 0; i < n; ++i) {\n";
8456 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8457 pr " free (%s[i]);\n" n;
8459 pr " free (%s);\n" n;
8460 | RStruct (n, typ) ->
8461 let cols = cols_of_struct typ in
8462 generate_perl_struct_code typ cols name style n do_cleanups
8463 | RStructList (n, typ) ->
8464 let cols = cols_of_struct typ in
8465 generate_perl_struct_list_code typ cols name style n do_cleanups
8468 pr " char *%s;\n" n;
8469 pr " size_t size;\n";
8471 pr " %s = guestfs_%s " n name;
8472 generate_c_call_args ~handle:"g" style;
8475 pr " if (%s == NULL)\n" n;
8476 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8477 pr " RETVAL = newSVpvn (%s, size);\n" n;
8478 pr " free (%s);\n" n;
8486 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8488 pr " struct guestfs_%s_list *%s;\n" typ n;
8492 pr " %s = guestfs_%s " n name;
8493 generate_c_call_args ~handle:"g" style;
8496 pr " if (%s == NULL)\n" n;
8497 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8498 pr " EXTEND (SP, %s->len);\n" n;
8499 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8500 pr " hv = newHV ();\n";
8504 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8505 name (String.length name) n name
8507 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8508 name (String.length name) n name
8510 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8511 name (String.length name) n name n name
8512 | name, (FBytes|FUInt64) ->
8513 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8514 name (String.length name) n name
8516 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8517 name (String.length name) n name
8518 | name, (FInt32|FUInt32) ->
8519 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8520 name (String.length name) n name
8522 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8523 name (String.length name) n name
8524 | name, FOptPercent ->
8525 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8526 name (String.length name) n name
8528 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8530 pr " guestfs_free_%s_list (%s);\n" typ n
8532 and generate_perl_struct_code typ cols name style n do_cleanups =
8534 pr " struct guestfs_%s *%s;\n" typ n;
8536 pr " %s = guestfs_%s " n name;
8537 generate_c_call_args ~handle:"g" style;
8540 pr " if (%s == NULL)\n" n;
8541 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8542 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8544 fun ((name, _) as col) ->
8545 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8549 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8552 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8555 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8557 | name, (FBytes|FUInt64) ->
8558 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8561 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8563 | name, (FInt32|FUInt32) ->
8564 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8567 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8569 | name, FOptPercent ->
8570 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8573 pr " free (%s);\n" n
8575 (* Generate Sys/Guestfs.pm. *)
8576 and generate_perl_pm () =
8577 generate_header HashStyle LGPLv2plus;
8584 Sys::Guestfs - Perl bindings for libguestfs
8590 my $h = Sys::Guestfs->new ();
8591 $h->add_drive ('guest.img');
8593 $h->mount ('/dev/sda1', '/');
8594 $h->touch ('/hello');
8599 The C<Sys::Guestfs> module provides a Perl XS binding to the
8600 libguestfs API for examining and modifying virtual machine
8603 Amongst the things this is good for: making batch configuration
8604 changes to guests, getting disk used/free statistics (see also:
8605 virt-df), migrating between virtualization systems (see also:
8606 virt-p2v), performing partial backups, performing partial guest
8607 clones, cloning guests and changing registry/UUID/hostname info, and
8610 Libguestfs uses Linux kernel and qemu code, and can access any type of
8611 guest filesystem that Linux and qemu can, including but not limited
8612 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8613 schemes, qcow, qcow2, vmdk.
8615 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8616 LVs, what filesystem is in each LV, etc.). It can also run commands
8617 in the context of the guest. Also you can access filesystems over
8620 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8621 functions for using libguestfs from Perl, including integration
8626 All errors turn into calls to C<croak> (see L<Carp(3)>).
8634 package Sys::Guestfs;
8640 XSLoader::load ('Sys::Guestfs');
8642 =item $h = Sys::Guestfs->new ();
8644 Create a new guestfs handle.
8650 my $class = ref ($proto) || $proto;
8652 my $self = Sys::Guestfs::_create ();
8653 bless $self, $class;
8659 (* Actions. We only need to print documentation for these as
8660 * they are pulled in from the XS code automatically.
8663 fun (name, style, _, flags, _, _, longdesc) ->
8664 if not (List.mem NotInDocs flags) then (
8665 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8667 generate_perl_prototype name style;
8669 pr "%s\n\n" longdesc;
8670 if List.mem ProtocolLimitWarning flags then
8671 pr "%s\n\n" protocol_limit_warning;
8672 if List.mem DangerWillRobinson flags then
8673 pr "%s\n\n" danger_will_robinson;
8674 match deprecation_notice flags with
8676 | Some txt -> pr "%s\n\n" txt
8678 ) all_functions_sorted;
8690 Copyright (C) %s Red Hat Inc.
8694 Please see the file COPYING.LIB for the full license.
8700 L<http://libguestfs.org>,
8701 L<Sys::Guestfs::Lib(3)>.
8706 and generate_perl_prototype name style =
8707 (match fst style with
8715 | RBufferOut n -> pr "$%s = " n
8717 | RHashtable n -> pr "%%%s = " n
8719 | RStructList (n,_) -> pr "@%s = " n
8722 let comma = ref false in
8725 if !comma then pr ", ";
8728 | Pathname n | Device n | Dev_or_Path n | String n
8729 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8731 | StringList n | DeviceList n ->
8736 (* Generate Python C module. *)
8737 and generate_python_c () =
8738 generate_header CStyle LGPLv2plus;
8747 #include \"guestfs.h\"
8755 get_handle (PyObject *obj)
8758 assert (obj != Py_None);
8759 return ((Pyguestfs_Object *) obj)->g;
8763 put_handle (guestfs_h *g)
8767 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8770 /* This list should be freed (but not the strings) after use. */
8772 get_string_list (PyObject *obj)
8779 if (!PyList_Check (obj)) {
8780 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8784 len = PyList_Size (obj);
8785 r = malloc (sizeof (char *) * (len+1));
8787 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8791 for (i = 0; i < len; ++i)
8792 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8799 put_string_list (char * const * const argv)
8804 for (argc = 0; argv[argc] != NULL; ++argc)
8807 list = PyList_New (argc);
8808 for (i = 0; i < argc; ++i)
8809 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8815 put_table (char * const * const argv)
8817 PyObject *list, *item;
8820 for (argc = 0; argv[argc] != NULL; ++argc)
8823 list = PyList_New (argc >> 1);
8824 for (i = 0; i < argc; i += 2) {
8825 item = PyTuple_New (2);
8826 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8827 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8828 PyList_SetItem (list, i >> 1, item);
8835 free_strings (char **argv)
8839 for (argc = 0; argv[argc] != NULL; ++argc)
8845 py_guestfs_create (PyObject *self, PyObject *args)
8849 g = guestfs_create ();
8851 PyErr_SetString (PyExc_RuntimeError,
8852 \"guestfs.create: failed to allocate handle\");
8855 guestfs_set_error_handler (g, NULL, NULL);
8856 return put_handle (g);
8860 py_guestfs_close (PyObject *self, PyObject *args)
8865 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8867 g = get_handle (py_g);
8871 Py_INCREF (Py_None);
8877 let emit_put_list_function typ =
8878 pr "static PyObject *\n";
8879 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8881 pr " PyObject *list;\n";
8884 pr " list = PyList_New (%ss->len);\n" typ;
8885 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8886 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8887 pr " return list;\n";
8892 (* Structures, turned into Python dictionaries. *)
8895 pr "static PyObject *\n";
8896 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8898 pr " PyObject *dict;\n";
8900 pr " dict = PyDict_New ();\n";
8904 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8905 pr " PyString_FromString (%s->%s));\n"
8908 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8909 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8912 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8913 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8915 | name, (FBytes|FUInt64) ->
8916 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8917 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8920 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8921 pr " PyLong_FromLongLong (%s->%s));\n"
8924 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8925 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8928 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8929 pr " PyLong_FromLong (%s->%s));\n"
8931 | name, FOptPercent ->
8932 pr " if (%s->%s >= 0)\n" typ name;
8933 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8934 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8937 pr " Py_INCREF (Py_None);\n";
8938 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8941 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8942 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8944 pr " return dict;\n";
8950 (* Emit a put_TYPE_list function definition only if that function is used. *)
8953 | typ, (RStructListOnly | RStructAndList) ->
8954 (* generate the function for typ *)
8955 emit_put_list_function typ
8956 | typ, _ -> () (* empty *)
8957 ) (rstructs_used_by all_functions);
8959 (* Python wrapper functions. *)
8961 fun (name, style, _, _, _, _, _) ->
8962 pr "static PyObject *\n";
8963 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8966 pr " PyObject *py_g;\n";
8967 pr " guestfs_h *g;\n";
8968 pr " PyObject *py_r;\n";
8971 match fst style with
8972 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8973 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8974 | RConstString _ | RConstOptString _ ->
8975 pr " const char *r;\n"; "NULL"
8976 | RString _ -> pr " char *r;\n"; "NULL"
8977 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8978 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8979 | RStructList (_, typ) ->
8980 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8983 pr " size_t size;\n";
8988 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8989 pr " const char *%s;\n" n
8990 | OptString n -> pr " const char *%s;\n" n
8991 | StringList n | DeviceList n ->
8992 pr " PyObject *py_%s;\n" n;
8993 pr " char **%s;\n" n
8994 | Bool n -> pr " int %s;\n" n
8995 | Int n -> pr " int %s;\n" n
8996 | Int64 n -> pr " long long %s;\n" n
9001 (* Convert the parameters. *)
9002 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9005 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9006 | OptString _ -> pr "z"
9007 | StringList _ | DeviceList _ -> pr "O"
9008 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9010 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9011 * emulate C's int/long/long long in Python?
9014 pr ":guestfs_%s\",\n" name;
9018 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9019 | OptString n -> pr ", &%s" n
9020 | StringList n | DeviceList n -> pr ", &py_%s" n
9021 | Bool n -> pr ", &%s" n
9022 | Int n -> pr ", &%s" n
9023 | Int64 n -> pr ", &%s" n
9027 pr " return NULL;\n";
9029 pr " g = get_handle (py_g);\n";
9032 | Pathname _ | Device _ | Dev_or_Path _ | String _
9033 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9034 | StringList n | DeviceList n ->
9035 pr " %s = get_string_list (py_%s);\n" n n;
9036 pr " if (!%s) return NULL;\n" n
9041 pr " r = guestfs_%s " name;
9042 generate_c_call_args ~handle:"g" style;
9047 | Pathname _ | Device _ | Dev_or_Path _ | String _
9048 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9049 | StringList n | DeviceList n ->
9050 pr " free (%s);\n" n
9053 pr " if (r == %s) {\n" error_code;
9054 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9055 pr " return NULL;\n";
9059 (match fst style with
9061 pr " Py_INCREF (Py_None);\n";
9062 pr " py_r = Py_None;\n"
9064 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9065 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9066 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9067 | RConstOptString _ ->
9069 pr " py_r = PyString_FromString (r);\n";
9071 pr " Py_INCREF (Py_None);\n";
9072 pr " py_r = Py_None;\n";
9075 pr " py_r = PyString_FromString (r);\n";
9078 pr " py_r = put_string_list (r);\n";
9079 pr " free_strings (r);\n"
9080 | RStruct (_, typ) ->
9081 pr " py_r = put_%s (r);\n" typ;
9082 pr " guestfs_free_%s (r);\n" typ
9083 | RStructList (_, typ) ->
9084 pr " py_r = put_%s_list (r);\n" typ;
9085 pr " guestfs_free_%s_list (r);\n" typ
9087 pr " py_r = put_table (r);\n";
9088 pr " free_strings (r);\n"
9090 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9094 pr " return py_r;\n";
9099 (* Table of functions. *)
9100 pr "static PyMethodDef methods[] = {\n";
9101 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9102 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9104 fun (name, _, _, _, _, _, _) ->
9105 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9108 pr " { NULL, NULL, 0, NULL }\n";
9112 (* Init function. *)
9115 initlibguestfsmod (void)
9117 static int initialized = 0;
9119 if (initialized) return;
9120 Py_InitModule ((char *) \"libguestfsmod\", methods);
9125 (* Generate Python module. *)
9126 and generate_python_py () =
9127 generate_header HashStyle LGPLv2plus;
9130 u\"\"\"Python bindings for libguestfs
9133 g = guestfs.GuestFS ()
9134 g.add_drive (\"guest.img\")
9136 parts = g.list_partitions ()
9138 The guestfs module provides a Python binding to the libguestfs API
9139 for examining and modifying virtual machine disk images.
9141 Amongst the things this is good for: making batch configuration
9142 changes to guests, getting disk used/free statistics (see also:
9143 virt-df), migrating between virtualization systems (see also:
9144 virt-p2v), performing partial backups, performing partial guest
9145 clones, cloning guests and changing registry/UUID/hostname info, and
9148 Libguestfs uses Linux kernel and qemu code, and can access any type of
9149 guest filesystem that Linux and qemu can, including but not limited
9150 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9151 schemes, qcow, qcow2, vmdk.
9153 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9154 LVs, what filesystem is in each LV, etc.). It can also run commands
9155 in the context of the guest. Also you can access filesystems over
9158 Errors which happen while using the API are turned into Python
9159 RuntimeError exceptions.
9161 To create a guestfs handle you usually have to perform the following
9164 # Create the handle, call add_drive at least once, and possibly
9165 # several times if the guest has multiple block devices:
9166 g = guestfs.GuestFS ()
9167 g.add_drive (\"guest.img\")
9169 # Launch the qemu subprocess and wait for it to become ready:
9172 # Now you can issue commands, for example:
9177 import libguestfsmod
9180 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9182 def __init__ (self):
9183 \"\"\"Create a new libguestfs handle.\"\"\"
9184 self._o = libguestfsmod.create ()
9187 libguestfsmod.close (self._o)
9192 fun (name, style, _, flags, _, _, longdesc) ->
9194 generate_py_call_args ~handle:"self" (snd style);
9197 if not (List.mem NotInDocs flags) then (
9198 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9200 match fst style with
9201 | RErr | RInt _ | RInt64 _ | RBool _
9202 | RConstOptString _ | RConstString _
9203 | RString _ | RBufferOut _ -> doc
9205 doc ^ "\n\nThis function returns a list of strings."
9206 | RStruct (_, typ) ->
9207 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9208 | RStructList (_, typ) ->
9209 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9211 doc ^ "\n\nThis function returns a dictionary." in
9213 if List.mem ProtocolLimitWarning flags then
9214 doc ^ "\n\n" ^ protocol_limit_warning
9217 if List.mem DangerWillRobinson flags then
9218 doc ^ "\n\n" ^ danger_will_robinson
9221 match deprecation_notice flags with
9223 | Some txt -> doc ^ "\n\n" ^ txt in
9224 let doc = pod2text ~width:60 name doc in
9225 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9226 let doc = String.concat "\n " doc in
9227 pr " u\"\"\"%s\"\"\"\n" doc;
9229 pr " return libguestfsmod.%s " name;
9230 generate_py_call_args ~handle:"self._o" (snd style);
9235 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9236 and generate_py_call_args ~handle args =
9238 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9241 (* Useful if you need the longdesc POD text as plain text. Returns a
9244 * Because this is very slow (the slowest part of autogeneration),
9245 * we memoize the results.
9247 and pod2text ~width name longdesc =
9248 let key = width, name, longdesc in
9249 try Hashtbl.find pod2text_memo key
9251 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9252 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9254 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9255 let chan = open_process_in cmd in
9256 let lines = ref [] in
9258 let line = input_line chan in
9259 if i = 1 then (* discard the first line of output *)
9262 let line = triml line in
9263 lines := line :: !lines;
9266 let lines = try loop 1 with End_of_file -> List.rev !lines in
9268 (match close_process_in chan with
9271 failwithf "pod2text: process exited with non-zero status (%d)" i
9272 | WSIGNALED i | WSTOPPED i ->
9273 failwithf "pod2text: process signalled or stopped by signal %d" i
9275 Hashtbl.add pod2text_memo key lines;
9276 pod2text_memo_updated ();
9279 (* Generate ruby bindings. *)
9280 and generate_ruby_c () =
9281 generate_header CStyle LGPLv2plus;
9289 #include \"guestfs.h\"
9291 #include \"extconf.h\"
9293 /* For Ruby < 1.9 */
9295 #define RARRAY_LEN(r) (RARRAY((r))->len)
9298 static VALUE m_guestfs; /* guestfs module */
9299 static VALUE c_guestfs; /* guestfs_h handle */
9300 static VALUE e_Error; /* used for all errors */
9302 static void ruby_guestfs_free (void *p)
9305 guestfs_close ((guestfs_h *) p);
9308 static VALUE ruby_guestfs_create (VALUE m)
9312 g = guestfs_create ();
9314 rb_raise (e_Error, \"failed to create guestfs handle\");
9316 /* Don't print error messages to stderr by default. */
9317 guestfs_set_error_handler (g, NULL, NULL);
9319 /* Wrap it, and make sure the close function is called when the
9322 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9325 static VALUE ruby_guestfs_close (VALUE gv)
9328 Data_Get_Struct (gv, guestfs_h, g);
9330 ruby_guestfs_free (g);
9331 DATA_PTR (gv) = NULL;
9339 fun (name, style, _, _, _, _, _) ->
9340 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9341 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9344 pr " guestfs_h *g;\n";
9345 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9347 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9353 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9354 pr " Check_Type (%sv, T_STRING);\n" n;
9355 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9357 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9358 pr " \"%s\", \"%s\");\n" n name
9360 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9361 | StringList n | DeviceList n ->
9362 pr " char **%s;\n" n;
9363 pr " Check_Type (%sv, T_ARRAY);\n" n;
9365 pr " int i, len;\n";
9366 pr " len = RARRAY_LEN (%sv);\n" n;
9367 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9369 pr " for (i = 0; i < len; ++i) {\n";
9370 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9371 pr " %s[i] = StringValueCStr (v);\n" n;
9373 pr " %s[len] = NULL;\n" n;
9376 pr " int %s = RTEST (%sv);\n" n n
9378 pr " int %s = NUM2INT (%sv);\n" n n
9380 pr " long long %s = NUM2LL (%sv);\n" n n
9385 match fst style with
9386 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9387 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9388 | RConstString _ | RConstOptString _ ->
9389 pr " const char *r;\n"; "NULL"
9390 | RString _ -> pr " char *r;\n"; "NULL"
9391 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9392 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9393 | RStructList (_, typ) ->
9394 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9397 pr " size_t size;\n";
9401 pr " r = guestfs_%s " name;
9402 generate_c_call_args ~handle:"g" style;
9407 | Pathname _ | Device _ | Dev_or_Path _ | String _
9408 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9409 | StringList n | DeviceList n ->
9410 pr " free (%s);\n" n
9413 pr " if (r == %s)\n" error_code;
9414 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9417 (match fst style with
9419 pr " return Qnil;\n"
9420 | RInt _ | RBool _ ->
9421 pr " return INT2NUM (r);\n"
9423 pr " return ULL2NUM (r);\n"
9425 pr " return rb_str_new2 (r);\n";
9426 | RConstOptString _ ->
9428 pr " return rb_str_new2 (r);\n";
9430 pr " return Qnil;\n";
9432 pr " VALUE rv = rb_str_new2 (r);\n";
9436 pr " int i, len = 0;\n";
9437 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9438 pr " VALUE rv = rb_ary_new2 (len);\n";
9439 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9440 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9441 pr " free (r[i]);\n";
9445 | RStruct (_, typ) ->
9446 let cols = cols_of_struct typ in
9447 generate_ruby_struct_code typ cols
9448 | RStructList (_, typ) ->
9449 let cols = cols_of_struct typ in
9450 generate_ruby_struct_list_code typ cols
9452 pr " VALUE rv = rb_hash_new ();\n";
9454 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9455 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9456 pr " free (r[i]);\n";
9457 pr " free (r[i+1]);\n";
9462 pr " VALUE rv = rb_str_new (r, size);\n";
9472 /* Initialize the module. */
9473 void Init__guestfs ()
9475 m_guestfs = rb_define_module (\"Guestfs\");
9476 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9477 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9479 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9480 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9483 (* Define the rest of the methods. *)
9485 fun (name, style, _, _, _, _, _) ->
9486 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9487 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9492 (* Ruby code to return a struct. *)
9493 and generate_ruby_struct_code typ cols =
9494 pr " VALUE rv = rb_hash_new ();\n";
9498 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9500 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9502 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9503 | name, (FBytes|FUInt64) ->
9504 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9506 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9508 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9510 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9511 | name, FOptPercent ->
9512 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9513 | name, FChar -> (* XXX wrong? *)
9514 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9516 pr " guestfs_free_%s (r);\n" typ;
9519 (* Ruby code to return a struct list. *)
9520 and generate_ruby_struct_list_code typ cols =
9521 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9523 pr " for (i = 0; i < r->len; ++i) {\n";
9524 pr " VALUE hv = rb_hash_new ();\n";
9528 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9530 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
9532 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9533 | name, (FBytes|FUInt64) ->
9534 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9536 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9538 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9540 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9541 | name, FOptPercent ->
9542 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9543 | name, FChar -> (* XXX wrong? *)
9544 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9546 pr " rb_ary_push (rv, hv);\n";
9548 pr " guestfs_free_%s_list (r);\n" typ;
9551 (* Generate Java bindings GuestFS.java file. *)
9552 and generate_java_java () =
9553 generate_header CStyle LGPLv2plus;
9556 package com.redhat.et.libguestfs;
9558 import java.util.HashMap;
9559 import com.redhat.et.libguestfs.LibGuestFSException;
9560 import com.redhat.et.libguestfs.PV;
9561 import com.redhat.et.libguestfs.VG;
9562 import com.redhat.et.libguestfs.LV;
9563 import com.redhat.et.libguestfs.Stat;
9564 import com.redhat.et.libguestfs.StatVFS;
9565 import com.redhat.et.libguestfs.IntBool;
9566 import com.redhat.et.libguestfs.Dirent;
9569 * The GuestFS object is a libguestfs handle.
9573 public class GuestFS {
9574 // Load the native code.
9576 System.loadLibrary (\"guestfs_jni\");
9580 * The native guestfs_h pointer.
9585 * Create a libguestfs handle.
9587 * @throws LibGuestFSException
9589 public GuestFS () throws LibGuestFSException
9593 private native long _create () throws LibGuestFSException;
9596 * Close a libguestfs handle.
9598 * You can also leave handles to be collected by the garbage
9599 * collector, but this method ensures that the resources used
9600 * by the handle are freed up immediately. If you call any
9601 * other methods after closing the handle, you will get an
9604 * @throws LibGuestFSException
9606 public void close () throws LibGuestFSException
9612 private native void _close (long g) throws LibGuestFSException;
9614 public void finalize () throws LibGuestFSException
9622 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9623 if not (List.mem NotInDocs flags); then (
9624 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9626 if List.mem ProtocolLimitWarning flags then
9627 doc ^ "\n\n" ^ protocol_limit_warning
9630 if List.mem DangerWillRobinson flags then
9631 doc ^ "\n\n" ^ danger_will_robinson
9634 match deprecation_notice flags with
9636 | Some txt -> doc ^ "\n\n" ^ txt in
9637 let doc = pod2text ~width:60 name doc in
9638 let doc = List.map ( (* RHBZ#501883 *)
9641 | nonempty -> nonempty
9643 let doc = String.concat "\n * " doc in
9646 pr " * %s\n" shortdesc;
9649 pr " * @throws LibGuestFSException\n";
9653 generate_java_prototype ~public:true ~semicolon:false name style;
9656 pr " if (g == 0)\n";
9657 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9660 if fst style <> RErr then pr "return ";
9662 generate_java_call_args ~handle:"g" (snd style);
9666 generate_java_prototype ~privat:true ~native:true name style;
9673 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9674 and generate_java_call_args ~handle args =
9676 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9679 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9680 ?(semicolon=true) name style =
9681 if privat then pr "private ";
9682 if public then pr "public ";
9683 if native then pr "native ";
9686 (match fst style with
9687 | RErr -> pr "void ";
9688 | RInt _ -> pr "int ";
9689 | RInt64 _ -> pr "long ";
9690 | RBool _ -> pr "boolean ";
9691 | RConstString _ | RConstOptString _ | RString _
9692 | RBufferOut _ -> pr "String ";
9693 | RStringList _ -> pr "String[] ";
9694 | RStruct (_, typ) ->
9695 let name = java_name_of_struct typ in
9697 | RStructList (_, typ) ->
9698 let name = java_name_of_struct typ in
9700 | RHashtable _ -> pr "HashMap<String,String> ";
9703 if native then pr "_%s " name else pr "%s " name;
9705 let needs_comma = ref false in
9714 if !needs_comma then pr ", ";
9715 needs_comma := true;
9719 | Device n | Dev_or_Path n
9725 | StringList n | DeviceList n ->
9736 pr " throws LibGuestFSException";
9737 if semicolon then pr ";"
9739 and generate_java_struct jtyp cols () =
9740 generate_header CStyle LGPLv2plus;
9743 package com.redhat.et.libguestfs;
9746 * Libguestfs %s structure.
9758 | name, FBuffer -> pr " public String %s;\n" name
9759 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9760 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9761 | name, FChar -> pr " public char %s;\n" name
9762 | name, FOptPercent ->
9763 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9764 pr " public float %s;\n" name
9769 and generate_java_c () =
9770 generate_header CStyle LGPLv2plus;
9777 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9778 #include \"guestfs.h\"
9780 /* Note that this function returns. The exception is not thrown
9781 * until after the wrapper function returns.
9784 throw_exception (JNIEnv *env, const char *msg)
9787 cl = (*env)->FindClass (env,
9788 \"com/redhat/et/libguestfs/LibGuestFSException\");
9789 (*env)->ThrowNew (env, cl, msg);
9792 JNIEXPORT jlong JNICALL
9793 Java_com_redhat_et_libguestfs_GuestFS__1create
9794 (JNIEnv *env, jobject obj)
9798 g = guestfs_create ();
9800 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9803 guestfs_set_error_handler (g, NULL, NULL);
9804 return (jlong) (long) g;
9807 JNIEXPORT void JNICALL
9808 Java_com_redhat_et_libguestfs_GuestFS__1close
9809 (JNIEnv *env, jobject obj, jlong jg)
9811 guestfs_h *g = (guestfs_h *) (long) jg;
9818 fun (name, style, _, _, _, _, _) ->
9820 (match fst style with
9821 | RErr -> pr "void ";
9822 | RInt _ -> pr "jint ";
9823 | RInt64 _ -> pr "jlong ";
9824 | RBool _ -> pr "jboolean ";
9825 | RConstString _ | RConstOptString _ | RString _
9826 | RBufferOut _ -> pr "jstring ";
9827 | RStruct _ | RHashtable _ ->
9829 | RStringList _ | RStructList _ ->
9833 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9834 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9836 pr " (JNIEnv *env, jobject obj, jlong jg";
9840 | Device n | Dev_or_Path n
9845 pr ", jstring j%s" n
9846 | StringList n | DeviceList n ->
9847 pr ", jobjectArray j%s" n
9849 pr ", jboolean j%s" n
9857 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9858 let error_code, no_ret =
9859 match fst style with
9860 | RErr -> pr " int r;\n"; "-1", ""
9862 | RInt _ -> pr " int r;\n"; "-1", "0"
9863 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9864 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9865 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9867 pr " jstring jr;\n";
9868 pr " char *r;\n"; "NULL", "NULL"
9870 pr " jobjectArray jr;\n";
9873 pr " jstring jstr;\n";
9874 pr " char **r;\n"; "NULL", "NULL"
9875 | RStruct (_, typ) ->
9876 pr " jobject jr;\n";
9878 pr " jfieldID fl;\n";
9879 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9880 | RStructList (_, typ) ->
9881 pr " jobjectArray jr;\n";
9883 pr " jfieldID fl;\n";
9884 pr " jobject jfl;\n";
9885 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9886 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9888 pr " jstring jr;\n";
9890 pr " size_t size;\n";
9895 | Device n | Dev_or_Path n
9900 pr " const char *%s;\n" n
9901 | StringList n | DeviceList n ->
9902 pr " int %s_len;\n" n;
9903 pr " const char **%s;\n" n
9908 pr " int64_t %s;\n" n
9912 (match fst style with
9913 | RStringList _ | RStructList _ -> true
9914 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9916 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9917 List.exists (function
9918 | StringList _ -> true
9919 | DeviceList _ -> true
9920 | _ -> false) (snd style) in
9926 (* Get the parameters. *)
9930 | Device n | Dev_or_Path n
9934 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9936 (* This is completely undocumented, but Java null becomes
9939 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9940 | StringList n | DeviceList n ->
9941 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9942 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9943 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9944 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9946 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9948 pr " %s[%s_len] = NULL;\n" n n;
9952 pr " %s = j%s;\n" n n
9955 (* Make the call. *)
9956 pr " r = guestfs_%s " name;
9957 generate_c_call_args ~handle:"g" style;
9960 (* Release the parameters. *)
9964 | Device n | Dev_or_Path n
9968 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9971 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9972 | StringList n | DeviceList n ->
9973 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9974 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9976 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9978 pr " free (%s);\n" n
9984 (* Check for errors. *)
9985 pr " if (r == %s) {\n" error_code;
9986 pr " throw_exception (env, guestfs_last_error (g));\n";
9987 pr " return %s;\n" no_ret;
9991 (match fst style with
9993 | RInt _ -> pr " return (jint) r;\n"
9994 | RBool _ -> pr " return (jboolean) r;\n"
9995 | RInt64 _ -> pr " return (jlong) r;\n"
9996 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9997 | RConstOptString _ ->
9998 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10000 pr " jr = (*env)->NewStringUTF (env, r);\n";
10004 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10005 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10006 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10007 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10008 pr " for (i = 0; i < r_len; ++i) {\n";
10009 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10010 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10011 pr " free (r[i]);\n";
10015 | RStruct (_, typ) ->
10016 let jtyp = java_name_of_struct typ in
10017 let cols = cols_of_struct typ in
10018 generate_java_struct_return typ jtyp cols
10019 | RStructList (_, typ) ->
10020 let jtyp = java_name_of_struct typ in
10021 let cols = cols_of_struct typ in
10022 generate_java_struct_list_return typ jtyp cols
10025 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10026 pr " return NULL;\n"
10028 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10037 and generate_java_struct_return typ jtyp cols =
10038 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10039 pr " jr = (*env)->AllocObject (env, cl);\n";
10043 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10044 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10047 pr " char s[33];\n";
10048 pr " memcpy (s, r->%s, 32);\n" name;
10049 pr " s[32] = 0;\n";
10050 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10051 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10055 pr " int len = r->%s_len;\n" name;
10056 pr " char s[len+1];\n";
10057 pr " memcpy (s, r->%s, len);\n" name;
10058 pr " s[len] = 0;\n";
10059 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10060 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10062 | name, (FBytes|FUInt64|FInt64) ->
10063 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10064 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10065 | name, (FUInt32|FInt32) ->
10066 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10067 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10068 | name, FOptPercent ->
10069 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10070 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10072 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10073 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10078 and generate_java_struct_list_return typ jtyp cols =
10079 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10080 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10081 pr " for (i = 0; i < r->len; ++i) {\n";
10082 pr " jfl = (*env)->AllocObject (env, cl);\n";
10086 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10087 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10090 pr " char s[33];\n";
10091 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10092 pr " s[32] = 0;\n";
10093 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10094 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10098 pr " int len = r->val[i].%s_len;\n" name;
10099 pr " char s[len+1];\n";
10100 pr " memcpy (s, r->val[i].%s, len);\n" name;
10101 pr " s[len] = 0;\n";
10102 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10103 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10105 | name, (FBytes|FUInt64|FInt64) ->
10106 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10107 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10108 | name, (FUInt32|FInt32) ->
10109 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10110 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10111 | name, FOptPercent ->
10112 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10113 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10115 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10116 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10118 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10120 pr " guestfs_free_%s_list (r);\n" typ;
10123 and generate_java_makefile_inc () =
10124 generate_header HashStyle GPLv2plus;
10126 pr "java_built_sources = \\\n";
10129 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10131 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10133 and generate_haskell_hs () =
10134 generate_header HaskellStyle LGPLv2plus;
10136 (* XXX We only know how to generate partial FFI for Haskell
10137 * at the moment. Please help out!
10139 let can_generate style =
10143 | RInt64 _, _ -> true
10145 | RConstString _, _
10146 | RConstOptString _, _
10152 | RBufferOut _, _ -> false in
10155 {-# INCLUDE <guestfs.h> #-}
10156 {-# LANGUAGE ForeignFunctionInterface #-}
10161 (* List out the names of the actions we want to export. *)
10163 fun (name, style, _, _, _, _, _) ->
10164 if can_generate style then pr ",\n %s" name
10170 -- Unfortunately some symbols duplicate ones already present
10171 -- in Prelude. We don't know which, so we hard-code a list
10173 import Prelude hiding (truncate)
10177 import Foreign.C.Types
10179 import Control.Exception
10180 import Data.Typeable
10182 data GuestfsS = GuestfsS -- represents the opaque C struct
10183 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10184 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10186 -- XXX define properly later XXX
10190 data IntBool = IntBool
10192 data StatVFS = StatVFS
10193 data Hashtable = Hashtable
10195 foreign import ccall unsafe \"guestfs_create\" c_create
10197 foreign import ccall unsafe \"&guestfs_close\" c_close
10198 :: FunPtr (GuestfsP -> IO ())
10199 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10200 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10202 create :: IO GuestfsH
10205 c_set_error_handler p nullPtr nullPtr
10206 h <- newForeignPtr c_close p
10209 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10210 :: GuestfsP -> IO CString
10212 -- last_error :: GuestfsH -> IO (Maybe String)
10213 -- last_error h = do
10214 -- str <- withForeignPtr h (\\p -> c_last_error p)
10215 -- maybePeek peekCString str
10217 last_error :: GuestfsH -> IO (String)
10219 str <- withForeignPtr h (\\p -> c_last_error p)
10220 if (str == nullPtr)
10221 then return \"no error\"
10222 else peekCString str
10226 (* Generate wrappers for each foreign function. *)
10228 fun (name, style, _, _, _, _, _) ->
10229 if can_generate style then (
10230 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10232 generate_haskell_prototype ~handle:"GuestfsP" style;
10236 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10238 pr "%s %s = do\n" name
10239 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10241 (* Convert pointer arguments using with* functions. *)
10246 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10247 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10248 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10249 | Bool _ | Int _ | Int64 _ -> ()
10251 (* Convert integer arguments. *)
10255 | Bool n -> sprintf "(fromBool %s)" n
10256 | Int n -> sprintf "(fromIntegral %s)" n
10257 | Int64 n -> sprintf "(fromIntegral %s)" n
10258 | FileIn n | FileOut n
10259 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10261 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10262 (String.concat " " ("p" :: args));
10263 (match fst style with
10264 | RErr | RInt _ | RInt64 _ | RBool _ ->
10265 pr " if (r == -1)\n";
10267 pr " err <- last_error h\n";
10269 | RConstString _ | RConstOptString _ | RString _
10270 | RStringList _ | RStruct _
10271 | RStructList _ | RHashtable _ | RBufferOut _ ->
10272 pr " if (r == nullPtr)\n";
10274 pr " err <- last_error h\n";
10277 (match fst style with
10279 pr " else return ()\n"
10281 pr " else return (fromIntegral r)\n"
10283 pr " else return (fromIntegral r)\n"
10285 pr " else return (toBool r)\n"
10287 | RConstOptString _
10294 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10300 and generate_haskell_prototype ~handle ?(hs = false) style =
10301 pr "%s -> " handle;
10302 let string = if hs then "String" else "CString" in
10303 let int = if hs then "Int" else "CInt" in
10304 let bool = if hs then "Bool" else "CInt" in
10305 let int64 = if hs then "Integer" else "Int64" in
10309 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10310 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10311 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10312 | Bool _ -> pr "%s" bool
10313 | Int _ -> pr "%s" int
10314 | Int64 _ -> pr "%s" int
10315 | FileIn _ -> pr "%s" string
10316 | FileOut _ -> pr "%s" string
10321 (match fst style with
10322 | RErr -> if not hs then pr "CInt"
10323 | RInt _ -> pr "%s" int
10324 | RInt64 _ -> pr "%s" int64
10325 | RBool _ -> pr "%s" bool
10326 | RConstString _ -> pr "%s" string
10327 | RConstOptString _ -> pr "Maybe %s" string
10328 | RString _ -> pr "%s" string
10329 | RStringList _ -> pr "[%s]" string
10330 | RStruct (_, typ) ->
10331 let name = java_name_of_struct typ in
10333 | RStructList (_, typ) ->
10334 let name = java_name_of_struct typ in
10336 | RHashtable _ -> pr "Hashtable"
10337 | RBufferOut _ -> pr "%s" string
10341 and generate_csharp () =
10342 generate_header CPlusPlusStyle LGPLv2plus;
10344 (* XXX Make this configurable by the C# assembly users. *)
10345 let library = "libguestfs.so.0" in
10348 // These C# bindings are highly experimental at present.
10350 // Firstly they only work on Linux (ie. Mono). In order to get them
10351 // to work on Windows (ie. .Net) you would need to port the library
10352 // itself to Windows first.
10354 // The second issue is that some calls are known to be incorrect and
10355 // can cause Mono to segfault. Particularly: calls which pass or
10356 // return string[], or return any structure value. This is because
10357 // we haven't worked out the correct way to do this from C#.
10359 // The third issue is that when compiling you get a lot of warnings.
10360 // We are not sure whether the warnings are important or not.
10362 // Fourthly we do not routinely build or test these bindings as part
10363 // of the make && make check cycle, which means that regressions might
10366 // Suggestions and patches are welcome.
10370 // gmcs Libguestfs.cs
10371 // mono Libguestfs.exe
10373 // (You'll probably want to add a Test class / static main function
10374 // otherwise this won't do anything useful).
10378 using System.Runtime.InteropServices;
10379 using System.Runtime.Serialization;
10380 using System.Collections;
10384 class Error : System.ApplicationException
10386 public Error (string message) : base (message) {}
10387 protected Error (SerializationInfo info, StreamingContext context) {}
10394 [DllImport (\"%s\")]
10395 static extern IntPtr guestfs_create ();
10399 _handle = guestfs_create ();
10400 if (_handle == IntPtr.Zero)
10401 throw new Error (\"could not create guestfs handle\");
10404 [DllImport (\"%s\")]
10405 static extern void guestfs_close (IntPtr h);
10409 guestfs_close (_handle);
10412 [DllImport (\"%s\")]
10413 static extern string guestfs_last_error (IntPtr h);
10415 " library library library;
10417 (* Generate C# structure bindings. We prefix struct names with
10418 * underscore because C# cannot have conflicting struct names and
10419 * method names (eg. "class stat" and "stat").
10423 pr " [StructLayout (LayoutKind.Sequential)]\n";
10424 pr " public class _%s {\n" typ;
10427 | name, FChar -> pr " char %s;\n" name
10428 | name, FString -> pr " string %s;\n" name
10430 pr " uint %s_len;\n" name;
10431 pr " string %s;\n" name
10433 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10434 pr " string %s;\n" name
10435 | name, FUInt32 -> pr " uint %s;\n" name
10436 | name, FInt32 -> pr " int %s;\n" name
10437 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10438 | name, FInt64 -> pr " long %s;\n" name
10439 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10445 (* Generate C# function bindings. *)
10447 fun (name, style, _, _, _, shortdesc, _) ->
10448 let rec csharp_return_type () =
10449 match fst style with
10451 | RBool n -> "bool"
10453 | RInt64 n -> "long"
10455 | RConstOptString n
10457 | RBufferOut n -> "string"
10458 | RStruct (_,n) -> "_" ^ n
10459 | RHashtable n -> "Hashtable"
10460 | RStringList n -> "string[]"
10461 | RStructList (_,n) -> sprintf "_%s[]" n
10463 and c_return_type () =
10464 match fst style with
10468 | RInt64 _ -> "long"
10470 | RConstOptString _
10472 | RBufferOut _ -> "string"
10473 | RStruct (_,n) -> "_" ^ n
10475 | RStringList _ -> "string[]"
10476 | RStructList (_,n) -> sprintf "_%s[]" n
10478 and c_error_comparison () =
10479 match fst style with
10483 | RInt64 _ -> "== -1"
10485 | RConstOptString _
10491 | RStructList (_,_) -> "== null"
10493 and generate_extern_prototype () =
10494 pr " static extern %s guestfs_%s (IntPtr h"
10495 (c_return_type ()) name;
10498 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10499 | FileIn n | FileOut n ->
10500 pr ", [In] string %s" n
10501 | StringList n | DeviceList n ->
10502 pr ", [In] string[] %s" n
10512 and generate_public_prototype () =
10513 pr " public %s %s (" (csharp_return_type ()) name;
10514 let comma = ref false in
10516 if !comma then pr ", ";
10521 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10522 | FileIn n | FileOut n ->
10523 next (); pr "string %s" n
10524 | StringList n | DeviceList n ->
10525 next (); pr "string[] %s" n
10527 next (); pr "bool %s" n
10529 next (); pr "int %s" n
10531 next (); pr "long %s" n
10535 and generate_call () =
10536 pr "guestfs_%s (_handle" name;
10537 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10541 pr " [DllImport (\"%s\")]\n" library;
10542 generate_extern_prototype ();
10544 pr " /// <summary>\n";
10545 pr " /// %s\n" shortdesc;
10546 pr " /// </summary>\n";
10547 generate_public_prototype ();
10549 pr " %s r;\n" (c_return_type ());
10552 pr " if (r %s)\n" (c_error_comparison ());
10553 pr " throw new Error (guestfs_last_error (_handle));\n";
10554 (match fst style with
10557 pr " return r != 0 ? true : false;\n"
10559 pr " Hashtable rr = new Hashtable ();\n";
10560 pr " for (int i = 0; i < r.Length; i += 2)\n";
10561 pr " rr.Add (r[i], r[i+1]);\n";
10563 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10564 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10570 ) all_functions_sorted;
10576 and generate_bindtests () =
10577 generate_header CStyle LGPLv2plus;
10581 #include <stdlib.h>
10582 #include <inttypes.h>
10583 #include <string.h>
10585 #include \"guestfs.h\"
10586 #include \"guestfs-internal.h\"
10587 #include \"guestfs-internal-actions.h\"
10588 #include \"guestfs_protocol.h\"
10590 #define error guestfs_error
10591 #define safe_calloc guestfs_safe_calloc
10592 #define safe_malloc guestfs_safe_malloc
10595 print_strings (char *const *argv)
10600 for (argc = 0; argv[argc] != NULL; ++argc) {
10601 if (argc > 0) printf (\", \");
10602 printf (\"\\\"%%s\\\"\", argv[argc]);
10607 /* The test0 function prints its parameters to stdout. */
10611 match test_functions with
10612 | [] -> assert false
10613 | test0 :: tests -> test0, tests in
10616 let (name, style, _, _, _, _, _) = test0 in
10617 generate_prototype ~extern:false ~semicolon:false ~newline:true
10618 ~handle:"g" ~prefix:"guestfs__" name style;
10623 | Device n | Dev_or_Path n
10626 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10627 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10628 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10629 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10630 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10631 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10633 pr " /* Java changes stdout line buffering so we need this: */\n";
10634 pr " fflush (stdout);\n";
10640 fun (name, style, _, _, _, _, _) ->
10641 if String.sub name (String.length name - 3) 3 <> "err" then (
10642 pr "/* Test normal return. */\n";
10643 generate_prototype ~extern:false ~semicolon:false ~newline:true
10644 ~handle:"g" ~prefix:"guestfs__" name style;
10646 (match fst style with
10651 pr " sscanf (val, \"%%d\", &r);\n";
10654 pr " int64_t r;\n";
10655 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10658 pr " return STREQ (val, \"true\");\n"
10660 | RConstOptString _ ->
10661 (* Can't return the input string here. Return a static
10662 * string so we ensure we get a segfault if the caller
10663 * tries to free it.
10665 pr " return \"static string\";\n"
10667 pr " return strdup (val);\n"
10669 pr " char **strs;\n";
10671 pr " sscanf (val, \"%%d\", &n);\n";
10672 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10673 pr " for (i = 0; i < n; ++i) {\n";
10674 pr " strs[i] = safe_malloc (g, 16);\n";
10675 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10677 pr " strs[n] = NULL;\n";
10678 pr " return strs;\n"
10679 | RStruct (_, typ) ->
10680 pr " struct guestfs_%s *r;\n" typ;
10681 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10683 | RStructList (_, typ) ->
10684 pr " struct guestfs_%s_list *r;\n" typ;
10685 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10686 pr " sscanf (val, \"%%d\", &r->len);\n";
10687 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10690 pr " char **strs;\n";
10692 pr " sscanf (val, \"%%d\", &n);\n";
10693 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10694 pr " for (i = 0; i < n; ++i) {\n";
10695 pr " strs[i*2] = safe_malloc (g, 16);\n";
10696 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10697 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10698 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10700 pr " strs[n*2] = NULL;\n";
10701 pr " return strs;\n"
10703 pr " return strdup (val);\n"
10708 pr "/* Test error return. */\n";
10709 generate_prototype ~extern:false ~semicolon:false ~newline:true
10710 ~handle:"g" ~prefix:"guestfs__" name style;
10712 pr " error (g, \"error\");\n";
10713 (match fst style with
10714 | RErr | RInt _ | RInt64 _ | RBool _ ->
10716 | RConstString _ | RConstOptString _
10717 | RString _ | RStringList _ | RStruct _
10721 pr " return NULL;\n"
10728 and generate_ocaml_bindtests () =
10729 generate_header OCamlStyle GPLv2plus;
10733 let g = Guestfs.create () in
10737 String.concat " " (
10740 | CallString s -> "\"" ^ s ^ "\""
10741 | CallOptString None -> "None"
10742 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10743 | CallStringList xs ->
10744 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10745 | CallInt i when i >= 0 -> string_of_int i
10746 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10747 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10748 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10749 | CallBool b -> string_of_bool b
10754 generate_lang_bindtests (
10755 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10758 pr "print_endline \"EOF\"\n"
10760 and generate_perl_bindtests () =
10761 pr "#!/usr/bin/perl -w\n";
10762 generate_header HashStyle GPLv2plus;
10769 my $g = Sys::Guestfs->new ();
10773 String.concat ", " (
10776 | CallString s -> "\"" ^ s ^ "\""
10777 | CallOptString None -> "undef"
10778 | CallOptString (Some s) -> sprintf "\"%s\"" s
10779 | CallStringList xs ->
10780 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10781 | CallInt i -> string_of_int i
10782 | CallInt64 i -> Int64.to_string i
10783 | CallBool b -> if b then "1" else "0"
10788 generate_lang_bindtests (
10789 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10792 pr "print \"EOF\\n\"\n"
10794 and generate_python_bindtests () =
10795 generate_header HashStyle GPLv2plus;
10800 g = guestfs.GuestFS ()
10804 String.concat ", " (
10807 | CallString s -> "\"" ^ s ^ "\""
10808 | CallOptString None -> "None"
10809 | CallOptString (Some s) -> sprintf "\"%s\"" s
10810 | CallStringList xs ->
10811 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10812 | CallInt i -> string_of_int i
10813 | CallInt64 i -> Int64.to_string i
10814 | CallBool b -> if b then "1" else "0"
10819 generate_lang_bindtests (
10820 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10823 pr "print \"EOF\"\n"
10825 and generate_ruby_bindtests () =
10826 generate_header HashStyle GPLv2plus;
10831 g = Guestfs::create()
10835 String.concat ", " (
10838 | CallString s -> "\"" ^ s ^ "\""
10839 | CallOptString None -> "nil"
10840 | CallOptString (Some s) -> sprintf "\"%s\"" s
10841 | CallStringList xs ->
10842 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10843 | CallInt i -> string_of_int i
10844 | CallInt64 i -> Int64.to_string i
10845 | CallBool b -> string_of_bool b
10850 generate_lang_bindtests (
10851 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10854 pr "print \"EOF\\n\"\n"
10856 and generate_java_bindtests () =
10857 generate_header CStyle GPLv2plus;
10860 import com.redhat.et.libguestfs.*;
10862 public class Bindtests {
10863 public static void main (String[] argv)
10866 GuestFS g = new GuestFS ();
10870 String.concat ", " (
10873 | CallString s -> "\"" ^ s ^ "\""
10874 | CallOptString None -> "null"
10875 | CallOptString (Some s) -> sprintf "\"%s\"" s
10876 | CallStringList xs ->
10878 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10879 | CallInt i -> string_of_int i
10880 | CallInt64 i -> Int64.to_string i
10881 | CallBool b -> string_of_bool b
10886 generate_lang_bindtests (
10887 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10891 System.out.println (\"EOF\");
10893 catch (Exception exn) {
10894 System.err.println (exn);
10901 and generate_haskell_bindtests () =
10902 generate_header HaskellStyle GPLv2plus;
10905 module Bindtests where
10906 import qualified Guestfs
10909 g <- Guestfs.create
10913 String.concat " " (
10916 | CallString s -> "\"" ^ s ^ "\""
10917 | CallOptString None -> "Nothing"
10918 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10919 | CallStringList xs ->
10920 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10921 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10922 | CallInt i -> string_of_int i
10923 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10924 | CallInt64 i -> Int64.to_string i
10925 | CallBool true -> "True"
10926 | CallBool false -> "False"
10931 generate_lang_bindtests (
10932 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10935 pr " putStrLn \"EOF\"\n"
10937 (* Language-independent bindings tests - we do it this way to
10938 * ensure there is parity in testing bindings across all languages.
10940 and generate_lang_bindtests call =
10941 call "test0" [CallString "abc"; CallOptString (Some "def");
10942 CallStringList []; CallBool false;
10943 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10944 call "test0" [CallString "abc"; CallOptString None;
10945 CallStringList []; CallBool false;
10946 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10947 call "test0" [CallString ""; CallOptString (Some "def");
10948 CallStringList []; CallBool false;
10949 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10950 call "test0" [CallString ""; CallOptString (Some "");
10951 CallStringList []; CallBool false;
10952 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10953 call "test0" [CallString "abc"; CallOptString (Some "def");
10954 CallStringList ["1"]; CallBool false;
10955 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10956 call "test0" [CallString "abc"; CallOptString (Some "def");
10957 CallStringList ["1"; "2"]; CallBool false;
10958 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10959 call "test0" [CallString "abc"; CallOptString (Some "def");
10960 CallStringList ["1"]; CallBool true;
10961 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10962 call "test0" [CallString "abc"; CallOptString (Some "def");
10963 CallStringList ["1"]; CallBool false;
10964 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10965 call "test0" [CallString "abc"; CallOptString (Some "def");
10966 CallStringList ["1"]; CallBool false;
10967 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10968 call "test0" [CallString "abc"; CallOptString (Some "def");
10969 CallStringList ["1"]; CallBool false;
10970 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10971 call "test0" [CallString "abc"; CallOptString (Some "def");
10972 CallStringList ["1"]; CallBool false;
10973 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10974 call "test0" [CallString "abc"; CallOptString (Some "def");
10975 CallStringList ["1"]; CallBool false;
10976 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10977 call "test0" [CallString "abc"; CallOptString (Some "def");
10978 CallStringList ["1"]; CallBool false;
10979 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10981 (* XXX Add here tests of the return and error functions. *)
10983 (* Code to generator bindings for virt-inspector. Currently only
10984 * implemented for OCaml code (for virt-p2v 2.0).
10986 let rng_input = "inspector/virt-inspector.rng"
10988 (* Read the input file and parse it into internal structures. This is
10989 * by no means a complete RELAX NG parser, but is just enough to be
10990 * able to parse the specific input file.
10993 | Element of string * rng list (* <element name=name/> *)
10994 | Attribute of string * rng list (* <attribute name=name/> *)
10995 | Interleave of rng list (* <interleave/> *)
10996 | ZeroOrMore of rng (* <zeroOrMore/> *)
10997 | OneOrMore of rng (* <oneOrMore/> *)
10998 | Optional of rng (* <optional/> *)
10999 | Choice of string list (* <choice><value/>*</choice> *)
11000 | Value of string (* <value>str</value> *)
11001 | Text (* <text/> *)
11003 let rec string_of_rng = function
11004 | Element (name, xs) ->
11005 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11006 | Attribute (name, xs) ->
11007 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11008 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11009 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11010 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11011 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11012 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11013 | Value value -> "Value \"" ^ value ^ "\""
11016 and string_of_rng_list xs =
11017 String.concat ", " (List.map string_of_rng xs)
11019 let rec parse_rng ?defines context = function
11021 | Xml.Element ("element", ["name", name], children) :: rest ->
11022 Element (name, parse_rng ?defines context children)
11023 :: parse_rng ?defines context rest
11024 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11025 Attribute (name, parse_rng ?defines context children)
11026 :: parse_rng ?defines context rest
11027 | Xml.Element ("interleave", [], children) :: rest ->
11028 Interleave (parse_rng ?defines context children)
11029 :: parse_rng ?defines context rest
11030 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11031 let rng = parse_rng ?defines context [child] in
11033 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11035 failwithf "%s: <zeroOrMore> contains more than one child element"
11038 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11039 let rng = parse_rng ?defines context [child] in
11041 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11043 failwithf "%s: <oneOrMore> contains more than one child element"
11046 | Xml.Element ("optional", [], [child]) :: rest ->
11047 let rng = parse_rng ?defines context [child] in
11049 | [child] -> Optional child :: parse_rng ?defines context rest
11051 failwithf "%s: <optional> contains more than one child element"
11054 | Xml.Element ("choice", [], children) :: rest ->
11055 let values = List.map (
11056 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11058 failwithf "%s: can't handle anything except <value> in <choice>"
11062 :: parse_rng ?defines context rest
11063 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11064 Value value :: parse_rng ?defines context rest
11065 | Xml.Element ("text", [], []) :: rest ->
11066 Text :: parse_rng ?defines context rest
11067 | Xml.Element ("ref", ["name", name], []) :: rest ->
11068 (* Look up the reference. Because of limitations in this parser,
11069 * we can't handle arbitrarily nested <ref> yet. You can only
11070 * use <ref> from inside <start>.
11072 (match defines with
11074 failwithf "%s: contains <ref>, but no refs are defined yet" context
11076 let rng = StringMap.find name map in
11077 rng @ parse_rng ?defines context rest
11080 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11083 let xml = Xml.parse_file rng_input in
11085 | Xml.Element ("grammar", _,
11086 Xml.Element ("start", _, gram) :: defines) ->
11087 (* The <define/> elements are referenced in the <start> section,
11088 * so build a map of those first.
11090 let defines = List.fold_left (
11092 function Xml.Element ("define", ["name", name], defn) ->
11093 StringMap.add name defn map
11095 failwithf "%s: expected <define name=name/>" rng_input
11096 ) StringMap.empty defines in
11097 let defines = StringMap.mapi parse_rng defines in
11099 (* Parse the <start> clause, passing the defines. *)
11100 parse_rng ~defines "<start>" gram
11102 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11105 let name_of_field = function
11106 | Element (name, _) | Attribute (name, _)
11107 | ZeroOrMore (Element (name, _))
11108 | OneOrMore (Element (name, _))
11109 | Optional (Element (name, _)) -> name
11110 | Optional (Attribute (name, _)) -> name
11111 | Text -> (* an unnamed field in an element *)
11114 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11116 (* At the moment this function only generates OCaml types. However we
11117 * should parameterize it later so it can generate types/structs in a
11118 * variety of languages.
11120 let generate_types xs =
11121 (* A simple type is one that can be printed out directly, eg.
11122 * "string option". A complex type is one which has a name and has
11123 * to be defined via another toplevel definition, eg. a struct.
11125 * generate_type generates code for either simple or complex types.
11126 * In the simple case, it returns the string ("string option"). In
11127 * the complex case, it returns the name ("mountpoint"). In the
11128 * complex case it has to print out the definition before returning,
11129 * so it should only be called when we are at the beginning of a
11130 * new line (BOL context).
11132 let rec generate_type = function
11133 | Text -> (* string *)
11135 | Choice values -> (* [`val1|`val2|...] *)
11136 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11137 | ZeroOrMore rng -> (* <rng> list *)
11138 let t, is_simple = generate_type rng in
11139 t ^ " list (* 0 or more *)", is_simple
11140 | OneOrMore rng -> (* <rng> list *)
11141 let t, is_simple = generate_type rng in
11142 t ^ " list (* 1 or more *)", is_simple
11143 (* virt-inspector hack: bool *)
11144 | Optional (Attribute (name, [Value "1"])) ->
11146 | Optional rng -> (* <rng> list *)
11147 let t, is_simple = generate_type rng in
11148 t ^ " option", is_simple
11149 (* type name = { fields ... } *)
11150 | Element (name, fields) when is_attrs_interleave fields ->
11151 generate_type_struct name (get_attrs_interleave fields)
11152 | Element (name, [field]) (* type name = field *)
11153 | Attribute (name, [field]) ->
11154 let t, is_simple = generate_type field in
11155 if is_simple then (t, true)
11157 pr "type %s = %s\n" name t;
11160 | Element (name, fields) -> (* type name = { fields ... } *)
11161 generate_type_struct name fields
11163 failwithf "generate_type failed at: %s" (string_of_rng rng)
11165 and is_attrs_interleave = function
11166 | [Interleave _] -> true
11167 | Attribute _ :: fields -> is_attrs_interleave fields
11168 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11171 and get_attrs_interleave = function
11172 | [Interleave fields] -> fields
11173 | ((Attribute _) as field) :: fields
11174 | ((Optional (Attribute _)) as field) :: fields ->
11175 field :: get_attrs_interleave fields
11176 | _ -> assert false
11178 and generate_types xs =
11179 List.iter (fun x -> ignore (generate_type x)) xs
11181 and generate_type_struct name fields =
11182 (* Calculate the types of the fields first. We have to do this
11183 * before printing anything so we are still in BOL context.
11185 let types = List.map fst (List.map generate_type fields) in
11187 (* Special case of a struct containing just a string and another
11188 * field. Turn it into an assoc list.
11191 | ["string"; other] ->
11192 let fname1, fname2 =
11194 | [f1; f2] -> name_of_field f1, name_of_field f2
11195 | _ -> assert false in
11196 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11200 pr "type %s = {\n" name;
11202 fun (field, ftype) ->
11203 let fname = name_of_field field in
11204 pr " %s_%s : %s;\n" name fname ftype
11205 ) (List.combine fields types);
11207 (* Return the name of this type, and
11208 * false because it's not a simple type.
11215 let generate_parsers xs =
11216 (* As for generate_type above, generate_parser makes a parser for
11217 * some type, and returns the name of the parser it has generated.
11218 * Because it (may) need to print something, it should always be
11219 * called in BOL context.
11221 let rec generate_parser = function
11222 | Text -> (* string *)
11223 "string_child_or_empty"
11224 | Choice values -> (* [`val1|`val2|...] *)
11225 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11227 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11228 | ZeroOrMore rng -> (* <rng> list *)
11229 let pa = generate_parser rng in
11230 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11231 | OneOrMore rng -> (* <rng> list *)
11232 let pa = generate_parser rng in
11233 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11234 (* virt-inspector hack: bool *)
11235 | Optional (Attribute (name, [Value "1"])) ->
11236 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11237 | Optional rng -> (* <rng> list *)
11238 let pa = generate_parser rng in
11239 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11240 (* type name = { fields ... } *)
11241 | Element (name, fields) when is_attrs_interleave fields ->
11242 generate_parser_struct name (get_attrs_interleave fields)
11243 | Element (name, [field]) -> (* type name = field *)
11244 let pa = generate_parser field in
11245 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11246 pr "let %s =\n" parser_name;
11248 pr "let parse_%s = %s\n" name parser_name;
11250 | Attribute (name, [field]) ->
11251 let pa = generate_parser field in
11252 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11253 pr "let %s =\n" parser_name;
11255 pr "let parse_%s = %s\n" name parser_name;
11257 | Element (name, fields) -> (* type name = { fields ... } *)
11258 generate_parser_struct name ([], fields)
11260 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11262 and is_attrs_interleave = function
11263 | [Interleave _] -> true
11264 | Attribute _ :: fields -> is_attrs_interleave fields
11265 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11268 and get_attrs_interleave = function
11269 | [Interleave fields] -> [], fields
11270 | ((Attribute _) as field) :: fields
11271 | ((Optional (Attribute _)) as field) :: fields ->
11272 let attrs, interleaves = get_attrs_interleave fields in
11273 (field :: attrs), interleaves
11274 | _ -> assert false
11276 and generate_parsers xs =
11277 List.iter (fun x -> ignore (generate_parser x)) xs
11279 and generate_parser_struct name (attrs, interleaves) =
11280 (* Generate parsers for the fields first. We have to do this
11281 * before printing anything so we are still in BOL context.
11283 let fields = attrs @ interleaves in
11284 let pas = List.map generate_parser fields in
11286 (* Generate an intermediate tuple from all the fields first.
11287 * If the type is just a string + another field, then we will
11288 * return this directly, otherwise it is turned into a record.
11290 * RELAX NG note: This code treats <interleave> and plain lists of
11291 * fields the same. In other words, it doesn't bother enforcing
11292 * any ordering of fields in the XML.
11294 pr "let parse_%s x =\n" name;
11295 pr " let t = (\n ";
11296 let comma = ref false in
11299 if !comma then pr ",\n ";
11302 | Optional (Attribute (fname, [field])), pa ->
11304 | Optional (Element (fname, [field])), pa ->
11305 pr "%s (optional_child %S x)" pa fname
11306 | Attribute (fname, [Text]), _ ->
11307 pr "attribute %S x" fname
11308 | (ZeroOrMore _ | OneOrMore _), pa ->
11313 let fname = name_of_field field in
11314 pr "%s (child %S x)" pa fname
11315 ) (List.combine fields pas);
11319 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11323 pr " (Obj.magic t : %s)\n" name
11327 | (Optional (Attribute (fname, [field])), pa) ->
11328 pr " %s_%s =\n" name fname;
11330 | (Optional (Element (fname, [field])), pa) ->
11331 pr " %s_%s =\n" name fname;
11332 pr " (let x = optional_child %S x in\n" fname;
11335 let fname = name_of_field field in
11336 pr " %s_%s =\n" name fname;
11337 pr " (let x = child %S x in\n" fname;
11339 ) (List.combine fields pas);
11343 sprintf "parse_%s" name
11346 generate_parsers xs
11348 (* Generate ocaml/guestfs_inspector.mli. *)
11349 let generate_ocaml_inspector_mli () =
11350 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11353 (** This is an OCaml language binding to the external [virt-inspector]
11356 For more information, please read the man page [virt-inspector(1)].
11361 generate_types grammar;
11362 pr "(** The nested information returned from the {!inspect} function. *)\n";
11366 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11367 (** To inspect a libvirt domain called [name], pass a singleton
11368 list: [inspect [name]]. When using libvirt only, you may
11369 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11371 To inspect a disk image or images, pass a list of the filenames
11372 of the disk images: [inspect filenames]
11374 This function inspects the given guest or disk images and
11375 returns a list of operating system(s) found and a large amount
11376 of information about them. In the vast majority of cases,
11377 a virtual machine only contains a single operating system.
11379 If the optional [~xml] parameter is given, then this function
11380 skips running the external virt-inspector program and just
11381 parses the given XML directly (which is expected to be XML
11382 produced from a previous run of virt-inspector). The list of
11383 names and connect URI are ignored in this case.
11385 This function can throw a wide variety of exceptions, for example
11386 if the external virt-inspector program cannot be found, or if
11387 it doesn't generate valid XML.
11391 (* Generate ocaml/guestfs_inspector.ml. *)
11392 let generate_ocaml_inspector_ml () =
11393 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11398 generate_types grammar;
11402 (* Misc functions which are used by the parser code below. *)
11403 let first_child = function
11404 | Xml.Element (_, _, c::_) -> c
11405 | Xml.Element (name, _, []) ->
11406 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11407 | Xml.PCData str ->
11408 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11410 let string_child_or_empty = function
11411 | Xml.Element (_, _, [Xml.PCData s]) -> s
11412 | Xml.Element (_, _, []) -> \"\"
11413 | Xml.Element (x, _, _) ->
11414 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11416 | Xml.PCData str ->
11417 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11419 let optional_child name xml =
11420 let children = Xml.children xml in
11422 Some (List.find (function
11423 | Xml.Element (n, _, _) when n = name -> true
11424 | _ -> false) children)
11428 let child name xml =
11429 match optional_child name xml with
11432 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11434 let attribute name xml =
11435 try Xml.attrib xml name
11436 with Xml.No_attribute _ ->
11437 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11441 generate_parsers grammar;
11445 (* Run external virt-inspector, then use parser to parse the XML. *)
11446 let inspect ?connect ?xml names =
11450 if names = [] then invalid_arg \"inspect: no names given\";
11451 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11452 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11454 let cmd = List.map Filename.quote cmd in
11455 let cmd = String.concat \" \" cmd in
11456 let chan = open_process_in cmd in
11457 let xml = Xml.parse_in chan in
11458 (match close_process_in chan with
11460 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11461 | WSIGNALED i | WSTOPPED i ->
11462 failwith (\"external virt-inspector command died or stopped on sig \" ^
11467 Xml.parse_string doc in
11468 parse_operatingsystems xml
11471 (* This is used to generate the src/MAX_PROC_NR file which
11472 * contains the maximum procedure number, a surrogate for the
11473 * ABI version number. See src/Makefile.am for the details.
11475 and generate_max_proc_nr () =
11476 let proc_nrs = List.map (
11477 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11478 ) daemon_functions in
11480 let max_proc_nr = List.fold_left max 0 proc_nrs in
11482 pr "%d\n" max_proc_nr
11484 let output_to filename k =
11485 let filename_new = filename ^ ".new" in
11486 chan := open_out filename_new;
11489 chan := Pervasives.stdout;
11491 (* Is the new file different from the current file? *)
11492 if Sys.file_exists filename && files_equal filename filename_new then
11493 unlink filename_new (* same, so skip it *)
11495 (* different, overwrite old one *)
11496 (try chmod filename 0o644 with Unix_error _ -> ());
11497 rename filename_new filename;
11498 chmod filename 0o444;
11499 printf "written %s\n%!" filename;
11502 let perror msg = function
11503 | Unix_error (err, _, _) ->
11504 eprintf "%s: %s\n" msg (error_message err)
11506 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11508 (* Main program. *)
11511 try openfile "HACKING" [O_RDWR] 0
11513 | Unix_error (ENOENT, _, _) ->
11515 You are probably running this from the wrong directory.
11516 Run it from the top source directory using the command
11521 perror "open: HACKING" exn;
11524 (* Acquire a lock so parallel builds won't try to run the generator
11525 * twice at the same time. Subsequent builds will wait for the first
11526 * one to finish. Note the lock is released implicitly when the
11529 (try lockf lock_fd F_LOCK 1
11531 perror "lock: HACKING" exn;
11534 check_functions ();
11536 output_to "src/guestfs_protocol.x" generate_xdr;
11537 output_to "src/guestfs-structs.h" generate_structs_h;
11538 output_to "src/guestfs-actions.h" generate_actions_h;
11539 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11540 output_to "src/guestfs-actions.c" generate_client_actions;
11541 output_to "src/guestfs-bindtests.c" generate_bindtests;
11542 output_to "src/guestfs-structs.pod" generate_structs_pod;
11543 output_to "src/guestfs-actions.pod" generate_actions_pod;
11544 output_to "src/guestfs-availability.pod" generate_availability_pod;
11545 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11546 output_to "src/libguestfs.syms" generate_linker_script;
11547 output_to "daemon/actions.h" generate_daemon_actions_h;
11548 output_to "daemon/stubs.c" generate_daemon_actions;
11549 output_to "daemon/names.c" generate_daemon_names;
11550 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11551 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11552 output_to "capitests/tests.c" generate_tests;
11553 output_to "fish/cmds.c" generate_fish_cmds;
11554 output_to "fish/completion.c" generate_fish_completion;
11555 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11556 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11557 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11558 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11559 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11560 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11561 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11562 output_to "perl/Guestfs.xs" generate_perl_xs;
11563 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11564 output_to "perl/bindtests.pl" generate_perl_bindtests;
11565 output_to "python/guestfs-py.c" generate_python_c;
11566 output_to "python/guestfs.py" generate_python_py;
11567 output_to "python/bindtests.py" generate_python_bindtests;
11568 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11569 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11570 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11574 let cols = cols_of_struct typ in
11575 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11576 output_to filename (generate_java_struct jtyp cols);
11579 output_to "java/Makefile.inc" generate_java_makefile_inc;
11580 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11581 output_to "java/Bindtests.java" generate_java_bindtests;
11582 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11583 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11584 output_to "csharp/Libguestfs.cs" generate_csharp;
11586 (* Always generate this file last, and unconditionally. It's used
11587 * by the Makefile to know when we must re-run the generator.
11589 let chan = open_out "src/stamp-generator" in
11590 fprintf chan "1\n";
11593 printf "generated %d lines of code\n" !lines