3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | NotInFish (* do not export via guestfish *)
186 | NotInDocs (* do not add this function to documentation *)
187 | DeprecatedBy of string (* function is deprecated, use .. instead *)
188 | Optional of string (* function is part of an optional group *)
190 (* You can supply zero or as many tests as you want per API call.
192 * Note that the test environment has 3 block devices, of size 500MB,
193 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194 * a fourth ISO block device with some known files on it (/dev/sdd).
196 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197 * Number of cylinders was 63 for IDE emulated disks with precisely
198 * the same size. How exactly this is calculated is a mystery.
200 * The ISO block device (/dev/sdd) comes from images/test.iso.
202 * To be able to run the tests in a reasonable amount of time,
203 * the virtual machine and block devices are reused between tests.
204 * So don't try testing kill_subprocess :-x
206 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
208 * Don't assume anything about the previous contents of the block
209 * devices. Use 'Init*' to create some initial scenarios.
211 * You can add a prerequisite clause to any individual test. This
212 * is a run-time check, which, if it fails, causes the test to be
213 * skipped. Useful if testing a command which might not work on
214 * all variations of libguestfs builds. A test that has prerequisite
215 * of 'Always' is run unconditionally.
217 * In addition, packagers can skip individual tests by setting the
218 * environment variables: eg:
219 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
220 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
222 type tests = (test_init * test_prereq * test) list
224 (* Run the command sequence and just expect nothing to fail. *)
227 (* Run the command sequence and expect the output of the final
228 * command to be the string.
230 | TestOutput of seq * string
232 (* Run the command sequence and expect the output of the final
233 * command to be the list of strings.
235 | TestOutputList of seq * string list
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of block devices (could be either
239 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240 * character of each string).
242 | TestOutputListOfDevices of seq * string list
244 (* Run the command sequence and expect the output of the final
245 * command to be the integer.
247 | TestOutputInt of seq * int
249 (* Run the command sequence and expect the output of the final
250 * command to be <op> <int>, eg. ">=", "1".
252 | TestOutputIntOp of seq * string * int
254 (* Run the command sequence and expect the output of the final
255 * command to be a true value (!= 0 or != NULL).
257 | TestOutputTrue of seq
259 (* Run the command sequence and expect the output of the final
260 * command to be a false value (== 0 or == NULL, but not an error).
262 | TestOutputFalse of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a list of the given length (but don't care about
268 | TestOutputLength of seq * int
270 (* Run the command sequence and expect the output of the final
271 * command to be a buffer (RBufferOut), ie. string + size.
273 | TestOutputBuffer of seq * string
275 (* Run the command sequence and expect the output of the final
276 * command to be a structure.
278 | TestOutputStruct of seq * test_field_compare list
280 (* Run the command sequence and expect the final command (only)
283 | TestLastFail of seq
285 and test_field_compare =
286 | CompareWithInt of string * int
287 | CompareWithIntOp of string * string * int
288 | CompareWithString of string * string
289 | CompareFieldsIntEq of string * string
290 | CompareFieldsStrEq of string * string
292 (* Test prerequisites. *)
294 (* Test always runs. *)
297 (* Test is currently disabled - eg. it fails, or it tests some
298 * unimplemented feature.
302 (* 'string' is some C code (a function body) that should return
303 * true or false. The test will run if the code returns true.
307 (* As for 'If' but the test runs _unless_ the code returns true. *)
310 (* Some initial scenarios for testing. *)
312 (* Do nothing, block devices could contain random stuff including
313 * LVM PVs, and some filesystems might be mounted. This is usually
318 (* Block devices are empty and no filesystems are mounted. *)
321 (* /dev/sda contains a single partition /dev/sda1, with random
322 * content. /dev/sdb and /dev/sdc may have random content.
327 (* /dev/sda contains a single partition /dev/sda1, which is formatted
328 * as ext2, empty [except for lost+found] and mounted on /.
329 * /dev/sdb and /dev/sdc may have random content.
335 * /dev/sda1 (is a PV):
336 * /dev/VG/LV (size 8MB):
337 * formatted as ext2, empty [except for lost+found], mounted on /
338 * /dev/sdb and /dev/sdc may have random content.
342 (* /dev/sdd (the ISO, see images/ directory in source)
347 (* Sequence of commands for testing. *)
349 and cmd = string list
351 (* Note about long descriptions: When referring to another
352 * action, use the format C<guestfs_other> (ie. the full name of
353 * the C function). This will be replaced as appropriate in other
356 * Apart from that, long descriptions are just perldoc paragraphs.
359 (* Generate a random UUID (used in tests). *)
361 let chan = open_process_in "uuidgen" in
362 let uuid = input_line chan in
363 (match close_process_in chan with
366 failwith "uuidgen: process exited with non-zero status"
367 | WSIGNALED _ | WSTOPPED _ ->
368 failwith "uuidgen: process signalled or stopped by signal"
372 (* These test functions are used in the language binding tests. *)
374 let test_all_args = [
377 StringList "strlist";
385 let test_all_rets = [
386 (* except for RErr, which is tested thoroughly elsewhere *)
387 "test0rint", RInt "valout";
388 "test0rint64", RInt64 "valout";
389 "test0rbool", RBool "valout";
390 "test0rconststring", RConstString "valout";
391 "test0rconstoptstring", RConstOptString "valout";
392 "test0rstring", RString "valout";
393 "test0rstringlist", RStringList "valout";
394 "test0rstruct", RStruct ("valout", "lvm_pv");
395 "test0rstructlist", RStructList ("valout", "lvm_pv");
396 "test0rhashtable", RHashtable "valout";
399 let test_functions = [
400 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
402 "internal test function - do not use",
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
408 It echos the contents of each parameter to stdout.
410 You probably don't want to call this function.");
414 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
416 "internal test function - do not use",
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
422 It converts string C<val> to the return type.
424 You probably don't want to call this function.");
425 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
427 "internal test function - do not use",
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
433 This function always returns an error.
435 You probably don't want to call this function.")]
439 (* non_daemon_functions are any functions which don't get processed
440 * in the daemon, eg. functions for setting and getting local
441 * configuration values.
444 let non_daemon_functions = test_functions @ [
445 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
447 "launch the qemu subprocess",
449 Internally libguestfs is implemented by running a virtual machine
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
455 ("wait_ready", (RErr, []), -1, [NotInFish],
457 "wait until the qemu subprocess launches (no op)",
459 This function is a no op.
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete. However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
470 ("kill_subprocess", (RErr, []), -1, [],
472 "kill the qemu subprocess",
474 This kills the qemu subprocess. You should never need to call this.");
476 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
478 "add an image to examine or modify",
480 This function adds a virtual machine disk image C<filename> to the
481 guest. The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
485 You don't necessarily need to be root when using libguestfs. However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>. In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
502 Note that this call checks for the existence of C<filename>. This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
505 the general C<guestfs_config> call instead.");
507 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
509 "add a CD-ROM disk image to examine",
511 This function adds a virtual CD-ROM disk image to the guest.
513 This is equivalent to the qemu parameter C<-cdrom filename>.
521 This call checks for the existence of C<filename>. This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
524 the general C<guestfs_config> call instead.
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
534 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
536 "add a drive in snapshot mode (read-only)",
538 This adds a drive in snapshot mode, making it effectively
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed. We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>. In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
555 C<readonly=on> is only added where qemu supports this option.
557 Note that this call checks for the existence of C<filename>. This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
560 the general C<guestfs_config> call instead.");
562 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
564 "add qemu parameters",
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>. Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
571 The first character of C<param> string must be a C<-> (dash).
573 C<value> can be NULL.");
575 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
577 "set the qemu binary",
579 Set the qemu binary that we will use.
581 The default is chosen when the library was compiled by the
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
589 Note that you should call this function as early as possible
590 after creating the handle. This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results. Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
597 ("get_qemu", (RConstString "qemu", []), -1, [],
598 [InitNone, Always, TestRun (
600 "get the qemu binary",
602 Return the current qemu binary.
604 This is always non-NULL. If it wasn't set already, then this will
605 return the default qemu binary name.");
607 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
609 "set the search path",
611 Set the path that libguestfs searches for kernel and initrd.img.
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
616 Setting C<path> to C<NULL> restores the default path.");
618 ("get_path", (RConstString "path", []), -1, [],
619 [InitNone, Always, TestRun (
621 "get the search path",
623 Return the current search path.
625 This is always non-NULL. If it wasn't set already, then this will
626 return the default path.");
628 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
630 "add options to kernel command line",
632 This function is used to add additional options to the
633 guest kernel command line.
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
641 ("get_append", (RConstOptString "append", []), -1, [],
642 (* This cannot be tested with the current framework. The
643 * function can return NULL in normal operations, which the
644 * test framework interprets as an error.
647 "get the additional kernel options",
649 Return the additional kernel options which are added to the
650 guest kernel command line.
652 If C<NULL> then no options are added.");
654 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658 If C<autosync> is true, this enables autosync. Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
666 ("get_autosync", (RBool "autosync", []), -1, [],
667 [InitNone, Always, TestRun (
668 [["get_autosync"]])],
671 Get the autosync flag.");
673 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
682 ("get_verbose", (RBool "verbose", []), -1, [],
686 This returns the verbose messages flag.");
688 ("is_ready", (RBool "ready", []), -1, [],
689 [InitNone, Always, TestOutputTrue (
691 "is ready to accept commands",
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
696 For more information on states, see L<guestfs(3)>.");
698 ("is_config", (RBool "config", []), -1, [],
699 [InitNone, Always, TestOutputFalse (
701 "is in configuration state",
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
706 For more information on states, see L<guestfs(3)>.");
708 ("is_launching", (RBool "launching", []), -1, [],
709 [InitNone, Always, TestOutputFalse (
710 [["is_launching"]])],
711 "is launching subprocess",
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
716 For more information on states, see L<guestfs(3)>.");
718 ("is_busy", (RBool "busy", []), -1, [],
719 [InitNone, Always, TestOutputFalse (
721 "is busy processing a command",
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
726 For more information on states, see L<guestfs(3)>.");
728 ("get_state", (RInt "state", []), -1, [],
730 "get the current state",
732 This returns the current state as an opaque integer. This is
733 only useful for printing debug and internal error messages.
735 For more information on states, see L<guestfs(3)>.");
737 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738 [InitNone, Always, TestOutputInt (
739 [["set_memsize"; "500"];
740 ["get_memsize"]], 500)],
741 "set memory allocated to the qemu subprocess",
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess. This only has any effect if called before
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
754 ("get_memsize", (RInt "memsize", []), -1, [],
755 [InitNone, Always, TestOutputIntOp (
756 [["get_memsize"]], ">=", 256)],
757 "get memory allocated to the qemu subprocess",
759 This gets the memory size in megabytes allocated to the
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
769 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770 [InitNone, Always, TestOutputIntOp (
771 [["get_pid"]], ">=", 1)],
772 "get PID of qemu subprocess",
774 Return the process ID of the qemu subprocess. If there is no
775 qemu subprocess, then this will return an error.
777 This is an internal call used for debugging and testing.");
779 ("version", (RStruct ("version", "version"), []), -1, [],
780 [InitNone, Always, TestOutputStruct (
781 [["version"]], [CompareWithInt ("major", 1)])],
782 "get the library version number",
784 Return the libguestfs version number that the program is linked
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against. You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
792 This call was added in version C<1.0.58>. In previous
793 versions of libguestfs there was no way to get the version
794 number. From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
797 The call returns a structure with four elements. The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet. The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
806 I<Note:> Don't use this call to test for availability
807 of features. Distro backports makes this unreliable. Use
808 C<guestfs_available> instead.");
810 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811 [InitNone, Always, TestOutputTrue (
812 [["set_selinux"; "true"];
814 "set SELinux enabled or disabled at appliance boot",
816 This sets the selinux flag that is passed to the appliance
817 at boot time. The default is C<selinux=0> (disabled).
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
825 ("get_selinux", (RBool "selinux", []), -1, [],
827 "get SELinux enabled flag",
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
835 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836 [InitNone, Always, TestOutputFalse (
837 [["set_trace"; "false"];
839 "enable or disable command traces",
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish. In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
855 ("get_trace", (RBool "trace", []), -1, [],
857 "get command trace enabled flag",
859 Return the command trace flag.");
861 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862 [InitNone, Always, TestOutputFalse (
863 [["set_direct"; "false"];
865 "enable or disable direct appliance mode",
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
875 You probably don't want to use this unless you know what you
878 The default is disabled.");
880 ("get_direct", (RBool "direct", []), -1, [],
882 "get direct appliance mode flag",
884 Return the direct appliance mode flag.");
886 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887 [InitNone, Always, TestOutputTrue (
888 [["set_recovery_proc"; "true"];
889 ["get_recovery_proc"]])],
890 "enable or disable the recovery process",
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process. The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself). In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
906 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
908 "get recovery process enabled flag",
910 Return the recovery process enabled flag.");
912 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
914 "add a drive specifying the QEMU block emulation to use",
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
919 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921 "add a drive read-only specifying the QEMU block emulation to use",
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
928 (* daemon_functions are any functions which cause some action
929 * to take place in the daemon.
932 let daemon_functions = [
933 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934 [InitEmpty, Always, TestOutput (
935 [["part_disk"; "/dev/sda"; "mbr"];
936 ["mkfs"; "ext2"; "/dev/sda1"];
937 ["mount"; "/dev/sda1"; "/"];
938 ["write_file"; "/new"; "new file contents"; "0"];
939 ["cat"; "/new"]], "new file contents")],
940 "mount a guest disk at a position in the filesystem",
942 Mount a guest disk at a position in the filesystem. Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest. If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
948 The rules are the same as for L<mount(2)>: A filesystem must
949 first be mounted on C</> before others can be mounted. Other
950 filesystems can only be mounted on directories which already
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
959 ("sync", (RErr, []), 2, [],
960 [ InitEmpty, Always, TestRun [["sync"]]],
961 "sync disks, writes are flushed through to the disk image",
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
969 ("touch", (RErr, [Pathname "path"]), 3, [],
970 [InitBasicFS, Always, TestOutputTrue (
972 ["exists"; "/new"]])],
973 "update file timestamps or create a new file",
975 Touch acts like the L<touch(1)> command. It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
979 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980 [InitISOFS, Always, TestOutput (
981 [["cat"; "/known-2"]], "abcdef\n")],
982 "list the contents of a file",
984 Return the contents of the file named C<path>.
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string). For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
991 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992 [], (* XXX Tricky to test because it depends on the exact format
993 * of the 'ls -l' command, which changes between F10 and F11.
995 "list the files in a directory (long format)",
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
1000 This command is mostly useful for interactive sessions. It
1001 is I<not> intended that you try to parse the output string.");
1003 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004 [InitBasicFS, Always, TestOutputList (
1006 ["touch"; "/newer"];
1007 ["touch"; "/newest"];
1008 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009 "list the files in a directory",
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd). The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1015 This command is mostly useful for interactive sessions. Programs
1016 should probably use C<guestfs_readdir> instead.");
1018 ("list_devices", (RStringList "devices", []), 7, [],
1019 [InitEmpty, Always, TestOutputListOfDevices (
1020 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021 "list the block devices",
1023 List all the block devices.
1025 The full block device names are returned, eg. C</dev/sda>");
1027 ("list_partitions", (RStringList "partitions", []), 8, [],
1028 [InitBasicFS, Always, TestOutputListOfDevices (
1029 [["list_partitions"]], ["/dev/sda1"]);
1030 InitEmpty, Always, TestOutputListOfDevices (
1031 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033 "list the partitions",
1035 List all the partitions detected on all block devices.
1037 The full partition device names are returned, eg. C</dev/sda1>
1039 This does not return logical volumes. For that you will need to
1040 call C<guestfs_lvs>.");
1042 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044 [["pvs"]], ["/dev/sda1"]);
1045 InitEmpty, Always, TestOutputListOfDevices (
1046 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047 ["pvcreate"; "/dev/sda1"];
1048 ["pvcreate"; "/dev/sda2"];
1049 ["pvcreate"; "/dev/sda3"];
1050 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051 "list the LVM physical volumes (PVs)",
1053 List all the physical volumes detected. This is the equivalent
1054 of the L<pvs(8)> command.
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1059 See also C<guestfs_pvs_full>.");
1061 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062 [InitBasicFSonLVM, Always, TestOutputList (
1064 InitEmpty, Always, TestOutputList (
1065 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066 ["pvcreate"; "/dev/sda1"];
1067 ["pvcreate"; "/dev/sda2"];
1068 ["pvcreate"; "/dev/sda3"];
1069 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070 ["vgcreate"; "VG2"; "/dev/sda3"];
1071 ["vgs"]], ["VG1"; "VG2"])],
1072 "list the LVM volume groups (VGs)",
1074 List all the volumes groups detected. This is the equivalent
1075 of the L<vgs(8)> command.
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1080 See also C<guestfs_vgs_full>.");
1082 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083 [InitBasicFSonLVM, Always, TestOutputList (
1084 [["lvs"]], ["/dev/VG/LV"]);
1085 InitEmpty, Always, TestOutputList (
1086 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087 ["pvcreate"; "/dev/sda1"];
1088 ["pvcreate"; "/dev/sda2"];
1089 ["pvcreate"; "/dev/sda3"];
1090 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091 ["vgcreate"; "VG2"; "/dev/sda3"];
1092 ["lvcreate"; "LV1"; "VG1"; "50"];
1093 ["lvcreate"; "LV2"; "VG1"; "50"];
1094 ["lvcreate"; "LV3"; "VG2"; "50"];
1095 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096 "list the LVM logical volumes (LVs)",
1098 List all the logical volumes detected. This is the equivalent
1099 of the L<lvs(8)> command.
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1104 See also C<guestfs_lvs_full>.");
1106 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107 [], (* XXX how to test? *)
1108 "list the LVM physical volumes (PVs)",
1110 List all the physical volumes detected. This is the equivalent
1111 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1113 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114 [], (* XXX how to test? *)
1115 "list the LVM volume groups (VGs)",
1117 List all the volumes groups detected. This is the equivalent
1118 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1120 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121 [], (* XXX how to test? *)
1122 "list the LVM logical volumes (LVs)",
1124 List all the logical volumes detected. This is the equivalent
1125 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1127 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128 [InitISOFS, Always, TestOutputList (
1129 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130 InitISOFS, Always, TestOutputList (
1131 [["read_lines"; "/empty"]], [])],
1132 "read file as lines",
1134 Return the contents of the file named C<path>.
1136 The file contents are returned as a list of lines. Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line). For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1144 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145 [], (* XXX Augeas code needs tests. *)
1146 "create a new Augeas handle",
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1152 You must call this before using any other C<guestfs_aug_*>
1155 C<root> is the filesystem root. C<root> must not be NULL,
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1164 =item C<AUG_SAVE_BACKUP> = 1
1166 Keep the original file with a C<.augsave> extension.
1168 =item C<AUG_SAVE_NEWFILE> = 2
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1173 =item C<AUG_TYPE_CHECK> = 4
1175 Typecheck lenses (can be expensive).
1177 =item C<AUG_NO_STDINC> = 8
1179 Do not use standard load path for modules.
1181 =item C<AUG_SAVE_NOOP> = 16
1183 Make save a no-op, just record what would have been changed.
1185 =item C<AUG_NO_LOAD> = 32
1187 Do not load the tree in C<guestfs_aug_init>.
1191 To close the handle, you can call C<guestfs_aug_close>.
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1195 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196 [], (* XXX Augeas code needs tests. *)
1197 "close the current Augeas handle",
1199 Close the current Augeas handle and free up any resources
1200 used by it. After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1204 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205 [], (* XXX Augeas code needs tests. *)
1206 "define an Augeas variable",
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1215 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216 [], (* XXX Augeas code needs tests. *)
1217 "define an Augeas node",
1219 Defines a variable C<name> whose value is the result of
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1230 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231 [], (* XXX Augeas code needs tests. *)
1232 "look up the value of an Augeas path",
1234 Look up the value associated with C<path>. If C<path>
1235 matches exactly one node, the C<value> is returned.");
1237 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238 [], (* XXX Augeas code needs tests. *)
1239 "set Augeas path to value",
1241 Set the value associated with C<path> to C<value>.");
1243 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244 [], (* XXX Augeas code needs tests. *)
1245 "insert a sibling Augeas node",
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1255 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256 [], (* XXX Augeas code needs tests. *)
1257 "remove an Augeas path",
1259 Remove C<path> and all of its children.
1261 On success this returns the number of entries which were removed.");
1263 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264 [], (* XXX Augeas code needs tests. *)
1267 Move the node C<src> to C<dest>. C<src> must match exactly
1268 one node. C<dest> is overwritten if it exists.");
1270 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271 [], (* XXX Augeas code needs tests. *)
1272 "return Augeas nodes which match augpath",
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1278 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279 [], (* XXX Augeas code needs tests. *)
1280 "write all pending Augeas changes to disk",
1282 This writes all pending changes to disk.
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1287 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1289 "load files into the tree",
1291 Load files into the tree.
1293 See C<aug_load> in the Augeas documentation for the full gory
1296 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297 [], (* XXX Augeas code needs tests. *)
1298 "list Augeas nodes under augpath",
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1303 ("rm", (RErr, [Pathname "path"]), 29, [],
1304 [InitBasicFS, Always, TestRun
1307 InitBasicFS, Always, TestLastFail
1309 InitBasicFS, Always, TestLastFail
1314 Remove the single file C<path>.");
1316 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317 [InitBasicFS, Always, TestRun
1320 InitBasicFS, Always, TestLastFail
1321 [["rmdir"; "/new"]];
1322 InitBasicFS, Always, TestLastFail
1324 ["rmdir"; "/new"]]],
1325 "remove a directory",
1327 Remove the single directory C<path>.");
1329 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330 [InitBasicFS, Always, TestOutputFalse
1332 ["mkdir"; "/new/foo"];
1333 ["touch"; "/new/foo/bar"];
1335 ["exists"; "/new"]]],
1336 "remove a file or directory recursively",
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory. This is like the C<rm -rf> shell
1342 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343 [InitBasicFS, Always, TestOutputTrue
1345 ["is_dir"; "/new"]];
1346 InitBasicFS, Always, TestLastFail
1347 [["mkdir"; "/new/foo/bar"]]],
1348 "create a directory",
1350 Create a directory named C<path>.");
1352 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353 [InitBasicFS, Always, TestOutputTrue
1354 [["mkdir_p"; "/new/foo/bar"];
1355 ["is_dir"; "/new/foo/bar"]];
1356 InitBasicFS, Always, TestOutputTrue
1357 [["mkdir_p"; "/new/foo/bar"];
1358 ["is_dir"; "/new/foo"]];
1359 InitBasicFS, Always, TestOutputTrue
1360 [["mkdir_p"; "/new/foo/bar"];
1361 ["is_dir"; "/new"]];
1362 (* Regression tests for RHBZ#503133: *)
1363 InitBasicFS, Always, TestRun
1365 ["mkdir_p"; "/new"]];
1366 InitBasicFS, Always, TestLastFail
1368 ["mkdir_p"; "/new"]]],
1369 "create a directory and parents",
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary. This is like the C<mkdir -p> shell command.");
1374 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375 [], (* XXX Need stat command to test *)
1378 Change the mode (permissions) of C<path> to C<mode>. Only
1379 numeric modes are supported.
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.
1385 The mode actually set is affected by the umask.");
1387 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1388 [], (* XXX Need stat command to test *)
1389 "change file owner and group",
1391 Change the file owner to C<owner> and group to C<group>.
1393 Only numeric uid and gid are supported. If you want to use
1394 names, you will need to locate and parse the password file
1395 yourself (Augeas support makes this relatively easy).");
1397 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1398 [InitISOFS, Always, TestOutputTrue (
1399 [["exists"; "/empty"]]);
1400 InitISOFS, Always, TestOutputTrue (
1401 [["exists"; "/directory"]])],
1402 "test if file or directory exists",
1404 This returns C<true> if and only if there is a file, directory
1405 (or anything) with the given C<path> name.
1407 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1409 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1410 [InitISOFS, Always, TestOutputTrue (
1411 [["is_file"; "/known-1"]]);
1412 InitISOFS, Always, TestOutputFalse (
1413 [["is_file"; "/directory"]])],
1414 "test if file exists",
1416 This returns C<true> if and only if there is a file
1417 with the given C<path> name. Note that it returns false for
1418 other objects like directories.
1420 See also C<guestfs_stat>.");
1422 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1423 [InitISOFS, Always, TestOutputFalse (
1424 [["is_dir"; "/known-3"]]);
1425 InitISOFS, Always, TestOutputTrue (
1426 [["is_dir"; "/directory"]])],
1427 "test if file exists",
1429 This returns C<true> if and only if there is a directory
1430 with the given C<path> name. Note that it returns false for
1431 other objects like files.
1433 See also C<guestfs_stat>.");
1435 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1436 [InitEmpty, Always, TestOutputListOfDevices (
1437 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1438 ["pvcreate"; "/dev/sda1"];
1439 ["pvcreate"; "/dev/sda2"];
1440 ["pvcreate"; "/dev/sda3"];
1441 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1442 "create an LVM physical volume",
1444 This creates an LVM physical volume on the named C<device>,
1445 where C<device> should usually be a partition name such
1448 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1449 [InitEmpty, Always, TestOutputList (
1450 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1451 ["pvcreate"; "/dev/sda1"];
1452 ["pvcreate"; "/dev/sda2"];
1453 ["pvcreate"; "/dev/sda3"];
1454 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1455 ["vgcreate"; "VG2"; "/dev/sda3"];
1456 ["vgs"]], ["VG1"; "VG2"])],
1457 "create an LVM volume group",
1459 This creates an LVM volume group called C<volgroup>
1460 from the non-empty list of physical volumes C<physvols>.");
1462 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1463 [InitEmpty, Always, TestOutputList (
1464 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1465 ["pvcreate"; "/dev/sda1"];
1466 ["pvcreate"; "/dev/sda2"];
1467 ["pvcreate"; "/dev/sda3"];
1468 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1469 ["vgcreate"; "VG2"; "/dev/sda3"];
1470 ["lvcreate"; "LV1"; "VG1"; "50"];
1471 ["lvcreate"; "LV2"; "VG1"; "50"];
1472 ["lvcreate"; "LV3"; "VG2"; "50"];
1473 ["lvcreate"; "LV4"; "VG2"; "50"];
1474 ["lvcreate"; "LV5"; "VG2"; "50"];
1476 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1477 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1478 "create an LVM logical volume",
1480 This creates an LVM logical volume called C<logvol>
1481 on the volume group C<volgroup>, with C<size> megabytes.");
1483 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1484 [InitEmpty, Always, TestOutput (
1485 [["part_disk"; "/dev/sda"; "mbr"];
1486 ["mkfs"; "ext2"; "/dev/sda1"];
1487 ["mount_options"; ""; "/dev/sda1"; "/"];
1488 ["write_file"; "/new"; "new file contents"; "0"];
1489 ["cat"; "/new"]], "new file contents")],
1490 "make a filesystem",
1492 This creates a filesystem on C<device> (usually a partition
1493 or LVM logical volume). The filesystem type is C<fstype>, for
1496 ("sfdisk", (RErr, [Device "device";
1497 Int "cyls"; Int "heads"; Int "sectors";
1498 StringList "lines"]), 43, [DangerWillRobinson],
1500 "create partitions on a block device",
1502 This is a direct interface to the L<sfdisk(8)> program for creating
1503 partitions on block devices.
1505 C<device> should be a block device, for example C</dev/sda>.
1507 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1508 and sectors on the device, which are passed directly to sfdisk as
1509 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1510 of these, then the corresponding parameter is omitted. Usually for
1511 'large' disks, you can just pass C<0> for these, but for small
1512 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1513 out the right geometry and you will need to tell it.
1515 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1516 information refer to the L<sfdisk(8)> manpage.
1518 To create a single partition occupying the whole disk, you would
1519 pass C<lines> as a single element list, when the single element being
1520 the string C<,> (comma).
1522 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1523 C<guestfs_part_init>");
1525 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1526 [InitBasicFS, Always, TestOutput (
1527 [["write_file"; "/new"; "new file contents"; "0"];
1528 ["cat"; "/new"]], "new file contents");
1529 InitBasicFS, Always, TestOutput (
1530 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1531 ["cat"; "/new"]], "\nnew file contents\n");
1532 InitBasicFS, Always, TestOutput (
1533 [["write_file"; "/new"; "\n\n"; "0"];
1534 ["cat"; "/new"]], "\n\n");
1535 InitBasicFS, Always, TestOutput (
1536 [["write_file"; "/new"; ""; "0"];
1537 ["cat"; "/new"]], "");
1538 InitBasicFS, Always, TestOutput (
1539 [["write_file"; "/new"; "\n\n\n"; "0"];
1540 ["cat"; "/new"]], "\n\n\n");
1541 InitBasicFS, Always, TestOutput (
1542 [["write_file"; "/new"; "\n"; "0"];
1543 ["cat"; "/new"]], "\n")],
1546 This call creates a file called C<path>. The contents of the
1547 file is the string C<content> (which can contain any 8 bit data),
1548 with length C<size>.
1550 As a special case, if C<size> is C<0>
1551 then the length is calculated using C<strlen> (so in this case
1552 the content cannot contain embedded ASCII NULs).
1554 I<NB.> Owing to a bug, writing content containing ASCII NUL
1555 characters does I<not> work, even if the length is specified.
1556 We hope to resolve this bug in a future version. In the meantime
1557 use C<guestfs_upload>.");
1559 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1560 [InitEmpty, Always, TestOutputListOfDevices (
1561 [["part_disk"; "/dev/sda"; "mbr"];
1562 ["mkfs"; "ext2"; "/dev/sda1"];
1563 ["mount_options"; ""; "/dev/sda1"; "/"];
1564 ["mounts"]], ["/dev/sda1"]);
1565 InitEmpty, Always, TestOutputList (
1566 [["part_disk"; "/dev/sda"; "mbr"];
1567 ["mkfs"; "ext2"; "/dev/sda1"];
1568 ["mount_options"; ""; "/dev/sda1"; "/"];
1571 "unmount a filesystem",
1573 This unmounts the given filesystem. The filesystem may be
1574 specified either by its mountpoint (path) or the device which
1575 contains the filesystem.");
1577 ("mounts", (RStringList "devices", []), 46, [],
1578 [InitBasicFS, Always, TestOutputListOfDevices (
1579 [["mounts"]], ["/dev/sda1"])],
1580 "show mounted filesystems",
1582 This returns the list of currently mounted filesystems. It returns
1583 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1585 Some internal mounts are not shown.
1587 See also: C<guestfs_mountpoints>");
1589 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1590 [InitBasicFS, Always, TestOutputList (
1593 (* check that umount_all can unmount nested mounts correctly: *)
1594 InitEmpty, Always, TestOutputList (
1595 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1596 ["mkfs"; "ext2"; "/dev/sda1"];
1597 ["mkfs"; "ext2"; "/dev/sda2"];
1598 ["mkfs"; "ext2"; "/dev/sda3"];
1599 ["mount_options"; ""; "/dev/sda1"; "/"];
1601 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1602 ["mkdir"; "/mp1/mp2"];
1603 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1604 ["mkdir"; "/mp1/mp2/mp3"];
1607 "unmount all filesystems",
1609 This unmounts all mounted filesystems.
1611 Some internal mounts are not unmounted by this call.");
1613 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1615 "remove all LVM LVs, VGs and PVs",
1617 This command removes all LVM logical volumes, volume groups
1618 and physical volumes.");
1620 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1621 [InitISOFS, Always, TestOutput (
1622 [["file"; "/empty"]], "empty");
1623 InitISOFS, Always, TestOutput (
1624 [["file"; "/known-1"]], "ASCII text");
1625 InitISOFS, Always, TestLastFail (
1626 [["file"; "/notexists"]])],
1627 "determine file type",
1629 This call uses the standard L<file(1)> command to determine
1630 the type or contents of the file. This also works on devices,
1631 for example to find out whether a partition contains a filesystem.
1633 This call will also transparently look inside various types
1636 The exact command which runs is C<file -zbsL path>. Note in
1637 particular that the filename is not prepended to the output
1638 (the C<-b> option).");
1640 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1641 [InitBasicFS, Always, TestOutput (
1642 [["upload"; "test-command"; "/test-command"];
1643 ["chmod"; "0o755"; "/test-command"];
1644 ["command"; "/test-command 1"]], "Result1");
1645 InitBasicFS, Always, TestOutput (
1646 [["upload"; "test-command"; "/test-command"];
1647 ["chmod"; "0o755"; "/test-command"];
1648 ["command"; "/test-command 2"]], "Result2\n");
1649 InitBasicFS, Always, TestOutput (
1650 [["upload"; "test-command"; "/test-command"];
1651 ["chmod"; "0o755"; "/test-command"];
1652 ["command"; "/test-command 3"]], "\nResult3");
1653 InitBasicFS, Always, TestOutput (
1654 [["upload"; "test-command"; "/test-command"];
1655 ["chmod"; "0o755"; "/test-command"];
1656 ["command"; "/test-command 4"]], "\nResult4\n");
1657 InitBasicFS, Always, TestOutput (
1658 [["upload"; "test-command"; "/test-command"];
1659 ["chmod"; "0o755"; "/test-command"];
1660 ["command"; "/test-command 5"]], "\nResult5\n\n");
1661 InitBasicFS, Always, TestOutput (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1665 InitBasicFS, Always, TestOutput (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command"; "/test-command 7"]], "");
1669 InitBasicFS, Always, TestOutput (
1670 [["upload"; "test-command"; "/test-command"];
1671 ["chmod"; "0o755"; "/test-command"];
1672 ["command"; "/test-command 8"]], "\n");
1673 InitBasicFS, Always, TestOutput (
1674 [["upload"; "test-command"; "/test-command"];
1675 ["chmod"; "0o755"; "/test-command"];
1676 ["command"; "/test-command 9"]], "\n\n");
1677 InitBasicFS, Always, TestOutput (
1678 [["upload"; "test-command"; "/test-command"];
1679 ["chmod"; "0o755"; "/test-command"];
1680 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1681 InitBasicFS, Always, TestOutput (
1682 [["upload"; "test-command"; "/test-command"];
1683 ["chmod"; "0o755"; "/test-command"];
1684 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1685 InitBasicFS, Always, TestLastFail (
1686 [["upload"; "test-command"; "/test-command"];
1687 ["chmod"; "0o755"; "/test-command"];
1688 ["command"; "/test-command"]])],
1689 "run a command from the guest filesystem",
1691 This call runs a command from the guest filesystem. The
1692 filesystem must be mounted, and must contain a compatible
1693 operating system (ie. something Linux, with the same
1694 or compatible processor architecture).
1696 The single parameter is an argv-style list of arguments.
1697 The first element is the name of the program to run.
1698 Subsequent elements are parameters. The list must be
1699 non-empty (ie. must contain a program name). Note that
1700 the command runs directly, and is I<not> invoked via
1701 the shell (see C<guestfs_sh>).
1703 The return value is anything printed to I<stdout> by
1706 If the command returns a non-zero exit status, then
1707 this function returns an error message. The error message
1708 string is the content of I<stderr> from the command.
1710 The C<$PATH> environment variable will contain at least
1711 C</usr/bin> and C</bin>. If you require a program from
1712 another location, you should provide the full path in the
1715 Shared libraries and data files required by the program
1716 must be available on filesystems which are mounted in the
1717 correct places. It is the caller's responsibility to ensure
1718 all filesystems that are needed are mounted at the right
1721 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1722 [InitBasicFS, Always, TestOutputList (
1723 [["upload"; "test-command"; "/test-command"];
1724 ["chmod"; "0o755"; "/test-command"];
1725 ["command_lines"; "/test-command 1"]], ["Result1"]);
1726 InitBasicFS, Always, TestOutputList (
1727 [["upload"; "test-command"; "/test-command"];
1728 ["chmod"; "0o755"; "/test-command"];
1729 ["command_lines"; "/test-command 2"]], ["Result2"]);
1730 InitBasicFS, Always, TestOutputList (
1731 [["upload"; "test-command"; "/test-command"];
1732 ["chmod"; "0o755"; "/test-command"];
1733 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1734 InitBasicFS, Always, TestOutputList (
1735 [["upload"; "test-command"; "/test-command"];
1736 ["chmod"; "0o755"; "/test-command"];
1737 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1738 InitBasicFS, Always, TestOutputList (
1739 [["upload"; "test-command"; "/test-command"];
1740 ["chmod"; "0o755"; "/test-command"];
1741 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1742 InitBasicFS, Always, TestOutputList (
1743 [["upload"; "test-command"; "/test-command"];
1744 ["chmod"; "0o755"; "/test-command"];
1745 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1746 InitBasicFS, Always, TestOutputList (
1747 [["upload"; "test-command"; "/test-command"];
1748 ["chmod"; "0o755"; "/test-command"];
1749 ["command_lines"; "/test-command 7"]], []);
1750 InitBasicFS, Always, TestOutputList (
1751 [["upload"; "test-command"; "/test-command"];
1752 ["chmod"; "0o755"; "/test-command"];
1753 ["command_lines"; "/test-command 8"]], [""]);
1754 InitBasicFS, Always, TestOutputList (
1755 [["upload"; "test-command"; "/test-command"];
1756 ["chmod"; "0o755"; "/test-command"];
1757 ["command_lines"; "/test-command 9"]], ["";""]);
1758 InitBasicFS, Always, TestOutputList (
1759 [["upload"; "test-command"; "/test-command"];
1760 ["chmod"; "0o755"; "/test-command"];
1761 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1762 InitBasicFS, Always, TestOutputList (
1763 [["upload"; "test-command"; "/test-command"];
1764 ["chmod"; "0o755"; "/test-command"];
1765 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1766 "run a command, returning lines",
1768 This is the same as C<guestfs_command>, but splits the
1769 result into a list of lines.
1771 See also: C<guestfs_sh_lines>");
1773 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1774 [InitISOFS, Always, TestOutputStruct (
1775 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1776 "get file information",
1778 Returns file information for the given C<path>.
1780 This is the same as the C<stat(2)> system call.");
1782 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1783 [InitISOFS, Always, TestOutputStruct (
1784 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1785 "get file information for a symbolic link",
1787 Returns file information for the given C<path>.
1789 This is the same as C<guestfs_stat> except that if C<path>
1790 is a symbolic link, then the link is stat-ed, not the file it
1793 This is the same as the C<lstat(2)> system call.");
1795 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1796 [InitISOFS, Always, TestOutputStruct (
1797 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1798 "get file system statistics",
1800 Returns file system statistics for any mounted file system.
1801 C<path> should be a file or directory in the mounted file system
1802 (typically it is the mount point itself, but it doesn't need to be).
1804 This is the same as the C<statvfs(2)> system call.");
1806 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1808 "get ext2/ext3/ext4 superblock details",
1810 This returns the contents of the ext2, ext3 or ext4 filesystem
1811 superblock on C<device>.
1813 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1814 manpage for more details. The list of fields returned isn't
1815 clearly defined, and depends on both the version of C<tune2fs>
1816 that libguestfs was built against, and the filesystem itself.");
1818 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1819 [InitEmpty, Always, TestOutputTrue (
1820 [["blockdev_setro"; "/dev/sda"];
1821 ["blockdev_getro"; "/dev/sda"]])],
1822 "set block device to read-only",
1824 Sets the block device named C<device> to read-only.
1826 This uses the L<blockdev(8)> command.");
1828 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1829 [InitEmpty, Always, TestOutputFalse (
1830 [["blockdev_setrw"; "/dev/sda"];
1831 ["blockdev_getro"; "/dev/sda"]])],
1832 "set block device to read-write",
1834 Sets the block device named C<device> to read-write.
1836 This uses the L<blockdev(8)> command.");
1838 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1839 [InitEmpty, Always, TestOutputTrue (
1840 [["blockdev_setro"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "is block device set to read-only",
1844 Returns a boolean indicating if the block device is read-only
1845 (true if read-only, false if not).
1847 This uses the L<blockdev(8)> command.");
1849 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1850 [InitEmpty, Always, TestOutputInt (
1851 [["blockdev_getss"; "/dev/sda"]], 512)],
1852 "get sectorsize of block device",
1854 This returns the size of sectors on a block device.
1855 Usually 512, but can be larger for modern devices.
1857 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1860 This uses the L<blockdev(8)> command.");
1862 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1863 [InitEmpty, Always, TestOutputInt (
1864 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1865 "get blocksize of block device",
1867 This returns the block size of a device.
1869 (Note this is different from both I<size in blocks> and
1870 I<filesystem block size>).
1872 This uses the L<blockdev(8)> command.");
1874 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1876 "set blocksize of block device",
1878 This sets the block size of a device.
1880 (Note this is different from both I<size in blocks> and
1881 I<filesystem block size>).
1883 This uses the L<blockdev(8)> command.");
1885 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1886 [InitEmpty, Always, TestOutputInt (
1887 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1888 "get total size of device in 512-byte sectors",
1890 This returns the size of the device in units of 512-byte sectors
1891 (even if the sectorsize isn't 512 bytes ... weird).
1893 See also C<guestfs_blockdev_getss> for the real sector size of
1894 the device, and C<guestfs_blockdev_getsize64> for the more
1895 useful I<size in bytes>.
1897 This uses the L<blockdev(8)> command.");
1899 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1900 [InitEmpty, Always, TestOutputInt (
1901 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1902 "get total size of device in bytes",
1904 This returns the size of the device in bytes.
1906 See also C<guestfs_blockdev_getsz>.
1908 This uses the L<blockdev(8)> command.");
1910 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1911 [InitEmpty, Always, TestRun
1912 [["blockdev_flushbufs"; "/dev/sda"]]],
1913 "flush device buffers",
1915 This tells the kernel to flush internal buffers associated
1918 This uses the L<blockdev(8)> command.");
1920 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1921 [InitEmpty, Always, TestRun
1922 [["blockdev_rereadpt"; "/dev/sda"]]],
1923 "reread partition table",
1925 Reread the partition table on C<device>.
1927 This uses the L<blockdev(8)> command.");
1929 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1930 [InitBasicFS, Always, TestOutput (
1931 (* Pick a file from cwd which isn't likely to change. *)
1932 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1933 ["checksum"; "md5"; "/COPYING.LIB"]],
1934 Digest.to_hex (Digest.file "COPYING.LIB"))],
1935 "upload a file from the local machine",
1937 Upload local file C<filename> to C<remotefilename> on the
1940 C<filename> can also be a named pipe.
1942 See also C<guestfs_download>.");
1944 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1945 [InitBasicFS, Always, TestOutput (
1946 (* Pick a file from cwd which isn't likely to change. *)
1947 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1949 ["upload"; "testdownload.tmp"; "/upload"];
1950 ["checksum"; "md5"; "/upload"]],
1951 Digest.to_hex (Digest.file "COPYING.LIB"))],
1952 "download a file to the local machine",
1954 Download file C<remotefilename> and save it as C<filename>
1955 on the local machine.
1957 C<filename> can also be a named pipe.
1959 See also C<guestfs_upload>, C<guestfs_cat>.");
1961 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1962 [InitISOFS, Always, TestOutput (
1963 [["checksum"; "crc"; "/known-3"]], "2891671662");
1964 InitISOFS, Always, TestLastFail (
1965 [["checksum"; "crc"; "/notexists"]]);
1966 InitISOFS, Always, TestOutput (
1967 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1968 InitISOFS, Always, TestOutput (
1969 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1970 InitISOFS, Always, TestOutput (
1971 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1972 InitISOFS, Always, TestOutput (
1973 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1974 InitISOFS, Always, TestOutput (
1975 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1978 "compute MD5, SHAx or CRC checksum of file",
1980 This call computes the MD5, SHAx or CRC checksum of the
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1995 Compute the MD5 hash (using the C<md5sum> program).
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2019 The checksum is returned as a printable string.");
2021 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2022 [InitBasicFS, Always, TestOutput (
2023 [["tar_in"; "../images/helloworld.tar"; "/"];
2024 ["cat"; "/hello"]], "hello\n")],
2025 "unpack tarfile to directory",
2027 This command uploads and unpacks local file C<tarfile> (an
2028 I<uncompressed> tar file) into C<directory>.
2030 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2032 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2034 "pack directory into tarfile",
2036 This command packs the contents of C<directory> and downloads
2037 it to local file C<tarfile>.
2039 To download a compressed tarball, use C<guestfs_tgz_out>.");
2041 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042 [InitBasicFS, Always, TestOutput (
2043 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044 ["cat"; "/hello"]], "hello\n")],
2045 "unpack compressed tarball to directory",
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2052 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2054 "pack directory into compressed tarball",
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2061 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062 [InitBasicFS, Always, TestLastFail (
2064 ["mount_ro"; "/dev/sda1"; "/"];
2065 ["touch"; "/new"]]);
2066 InitBasicFS, Always, TestOutput (
2067 [["write_file"; "/new"; "data"; "0"];
2069 ["mount_ro"; "/dev/sda1"; "/"];
2070 ["cat"; "/new"]], "data")],
2071 "mount a guest disk, read-only",
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2076 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2078 "mount a guest disk with mount options",
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2084 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2086 "mount a guest disk with mount options and vfstype",
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2092 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2094 "debugging and internals",
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2100 There is no comprehensive help for this command. You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2104 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105 [InitEmpty, Always, TestOutputList (
2106 [["part_disk"; "/dev/sda"; "mbr"];
2107 ["pvcreate"; "/dev/sda1"];
2108 ["vgcreate"; "VG"; "/dev/sda1"];
2109 ["lvcreate"; "LV1"; "VG"; "50"];
2110 ["lvcreate"; "LV2"; "VG"; "50"];
2111 ["lvremove"; "/dev/VG/LV1"];
2112 ["lvs"]], ["/dev/VG/LV2"]);
2113 InitEmpty, Always, TestOutputList (
2114 [["part_disk"; "/dev/sda"; "mbr"];
2115 ["pvcreate"; "/dev/sda1"];
2116 ["vgcreate"; "VG"; "/dev/sda1"];
2117 ["lvcreate"; "LV1"; "VG"; "50"];
2118 ["lvcreate"; "LV2"; "VG"; "50"];
2119 ["lvremove"; "/dev/VG"];
2121 InitEmpty, Always, TestOutputList (
2122 [["part_disk"; "/dev/sda"; "mbr"];
2123 ["pvcreate"; "/dev/sda1"];
2124 ["vgcreate"; "VG"; "/dev/sda1"];
2125 ["lvcreate"; "LV1"; "VG"; "50"];
2126 ["lvcreate"; "LV2"; "VG"; "50"];
2127 ["lvremove"; "/dev/VG"];
2129 "remove an LVM logical volume",
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2137 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138 [InitEmpty, Always, TestOutputList (
2139 [["part_disk"; "/dev/sda"; "mbr"];
2140 ["pvcreate"; "/dev/sda1"];
2141 ["vgcreate"; "VG"; "/dev/sda1"];
2142 ["lvcreate"; "LV1"; "VG"; "50"];
2143 ["lvcreate"; "LV2"; "VG"; "50"];
2146 InitEmpty, Always, TestOutputList (
2147 [["part_disk"; "/dev/sda"; "mbr"];
2148 ["pvcreate"; "/dev/sda1"];
2149 ["vgcreate"; "VG"; "/dev/sda1"];
2150 ["lvcreate"; "LV1"; "VG"; "50"];
2151 ["lvcreate"; "LV2"; "VG"; "50"];
2154 "remove an LVM volume group",
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2158 This also forcibly removes all logical volumes in the volume
2161 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162 [InitEmpty, Always, TestOutputListOfDevices (
2163 [["part_disk"; "/dev/sda"; "mbr"];
2164 ["pvcreate"; "/dev/sda1"];
2165 ["vgcreate"; "VG"; "/dev/sda1"];
2166 ["lvcreate"; "LV1"; "VG"; "50"];
2167 ["lvcreate"; "LV2"; "VG"; "50"];
2169 ["pvremove"; "/dev/sda1"];
2171 InitEmpty, Always, TestOutputListOfDevices (
2172 [["part_disk"; "/dev/sda"; "mbr"];
2173 ["pvcreate"; "/dev/sda1"];
2174 ["vgcreate"; "VG"; "/dev/sda1"];
2175 ["lvcreate"; "LV1"; "VG"; "50"];
2176 ["lvcreate"; "LV2"; "VG"; "50"];
2178 ["pvremove"; "/dev/sda1"];
2180 InitEmpty, Always, TestOutputListOfDevices (
2181 [["part_disk"; "/dev/sda"; "mbr"];
2182 ["pvcreate"; "/dev/sda1"];
2183 ["vgcreate"; "VG"; "/dev/sda1"];
2184 ["lvcreate"; "LV1"; "VG"; "50"];
2185 ["lvcreate"; "LV2"; "VG"; "50"];
2187 ["pvremove"; "/dev/sda1"];
2189 "remove an LVM physical volume",
2191 This wipes a physical volume C<device> so that LVM will no longer
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2198 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199 [InitBasicFS, Always, TestOutput (
2200 [["set_e2label"; "/dev/sda1"; "testlabel"];
2201 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202 "set the ext2/3/4 filesystem label",
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>. Filesystem labels are limited to
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2211 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2213 "get the ext2/3/4 filesystem label",
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2218 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219 (let uuid = uuidgen () in
2220 [InitBasicFS, Always, TestOutput (
2221 [["set_e2uuid"; "/dev/sda1"; uuid];
2222 ["get_e2uuid"; "/dev/sda1"]], uuid);
2223 InitBasicFS, Always, TestOutput (
2224 [["set_e2uuid"; "/dev/sda1"; "clear"];
2225 ["get_e2uuid"; "/dev/sda1"]], "");
2226 (* We can't predict what UUIDs will be, so just check the commands run. *)
2227 InitBasicFS, Always, TestRun (
2228 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229 InitBasicFS, Always, TestRun (
2230 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231 "set the ext2/3/4 filesystem UUID",
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>. The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2241 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2243 "get the ext2/3/4 filesystem UUID",
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2248 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249 [InitBasicFS, Always, TestOutputInt (
2250 [["umount"; "/dev/sda1"];
2251 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252 InitBasicFS, Always, TestOutputInt (
2253 [["umount"; "/dev/sda1"];
2254 ["zero"; "/dev/sda1"];
2255 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256 "run the filesystem checker",
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2261 The returned integer is the status. See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2270 Multiple status codes can be summed together.
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2279 Checking or repairing NTFS volumes is not supported
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2286 ("zero", (RErr, [Device "device"]), 85, [],
2287 [InitBasicFS, Always, TestOutput (
2288 [["umount"; "/dev/sda1"];
2289 ["zero"; "/dev/sda1"];
2290 ["file"; "/dev/sda1"]], "data")],
2291 "write zeroes to the device",
2293 This command writes zeroes over the first few blocks of C<device>.
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device). It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2299 See also: C<guestfs_scrub_device>.");
2301 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302 (* Test disabled because grub-install incompatible with virtio-blk driver.
2303 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2305 [InitBasicFS, Disabled, TestOutputTrue (
2306 [["grub_install"; "/"; "/dev/sda1"];
2307 ["is_dir"; "/boot"]])],
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2313 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314 [InitBasicFS, Always, TestOutput (
2315 [["write_file"; "/old"; "file content"; "0"];
2316 ["cp"; "/old"; "/new"];
2317 ["cat"; "/new"]], "file content");
2318 InitBasicFS, Always, TestOutputTrue (
2319 [["write_file"; "/old"; "file content"; "0"];
2320 ["cp"; "/old"; "/new"];
2321 ["is_file"; "/old"]]);
2322 InitBasicFS, Always, TestOutput (
2323 [["write_file"; "/old"; "file content"; "0"];
2325 ["cp"; "/old"; "/dir/new"];
2326 ["cat"; "/dir/new"]], "file content")],
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2332 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333 [InitBasicFS, Always, TestOutput (
2334 [["mkdir"; "/olddir"];
2335 ["mkdir"; "/newdir"];
2336 ["write_file"; "/olddir/file"; "file content"; "0"];
2337 ["cp_a"; "/olddir"; "/newdir"];
2338 ["cat"; "/newdir/olddir/file"]], "file content")],
2339 "copy a file or directory recursively",
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2344 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345 [InitBasicFS, Always, TestOutput (
2346 [["write_file"; "/old"; "file content"; "0"];
2347 ["mv"; "/old"; "/new"];
2348 ["cat"; "/new"]], "file content");
2349 InitBasicFS, Always, TestOutputFalse (
2350 [["write_file"; "/old"; "file content"; "0"];
2351 ["mv"; "/old"; "/new"];
2352 ["is_file"; "/old"]])],
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2358 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359 [InitEmpty, Always, TestRun (
2360 [["drop_caches"; "3"]])],
2361 "drop kernel page cache, dentries and inodes",
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches. The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2368 Setting C<whattodrop> to 3 should drop everything.
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2373 ("dmesg", (RString "kmsgs", []), 91, [],
2374 [InitEmpty, Always, TestRun (
2376 "return kernel messages",
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel. This is sometimes useful for extended
2380 debugging of problems.
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2387 ("ping_daemon", (RErr, []), 92, [],
2388 [InitEmpty, Always, TestRun (
2389 [["ping_daemon"]])],
2390 "ping the guest daemon",
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess. Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2397 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398 [InitBasicFS, Always, TestOutputTrue (
2399 [["write_file"; "/file1"; "contents of a file"; "0"];
2400 ["cp"; "/file1"; "/file2"];
2401 ["equal"; "/file1"; "/file2"]]);
2402 InitBasicFS, Always, TestOutputFalse (
2403 [["write_file"; "/file1"; "contents of a file"; "0"];
2404 ["write_file"; "/file2"; "contents of another file"; "0"];
2405 ["equal"; "/file1"; "/file2"]]);
2406 InitBasicFS, Always, TestLastFail (
2407 [["equal"; "/file1"; "/file2"]])],
2408 "test if two files have equal contents",
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2413 The external L<cmp(1)> program is used for the comparison.");
2415 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416 [InitISOFS, Always, TestOutputList (
2417 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418 InitISOFS, Always, TestOutputList (
2419 [["strings"; "/empty"]], [])],
2420 "print the printable strings in a file",
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2425 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426 [InitISOFS, Always, TestOutputList (
2427 [["strings_e"; "b"; "/known-5"]], []);
2428 InitBasicFS, Disabled, TestOutputList (
2429 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431 "print the printable strings in a file",
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2436 See the L<strings(1)> manpage for the full list of encodings.
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2441 The returned strings are transcoded to UTF-8.");
2443 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444 [InitISOFS, Always, TestOutput (
2445 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2446 (* Test for RHBZ#501888c2 regression which caused large hexdump
2447 * commands to segfault.
2449 InitISOFS, Always, TestRun (
2450 [["hexdump"; "/100krandom"]])],
2451 "dump a file in hexadecimal",
2453 This runs C<hexdump -C> on the given C<path>. The result is
2454 the human-readable, canonical hex dump of the file.");
2456 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457 [InitNone, Always, TestOutput (
2458 [["part_disk"; "/dev/sda"; "mbr"];
2459 ["mkfs"; "ext3"; "/dev/sda1"];
2460 ["mount_options"; ""; "/dev/sda1"; "/"];
2461 ["write_file"; "/new"; "test file"; "0"];
2462 ["umount"; "/dev/sda1"];
2463 ["zerofree"; "/dev/sda1"];
2464 ["mount_options"; ""; "/dev/sda1"; "/"];
2465 ["cat"; "/new"]], "test file")],
2466 "zero unused inodes and disk blocks on ext2/3 filesystem",
2468 This runs the I<zerofree> program on C<device>. This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2473 You should B<not> run this program if the filesystem is
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2479 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2481 "resize an LVM physical volume",
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2486 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487 Int "cyls"; Int "heads"; Int "sectors";
2488 String "line"]), 99, [DangerWillRobinson],
2490 "modify a single partition on a block device",
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2495 For other parameters, see C<guestfs_sfdisk>. You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2498 See also: C<guestfs_part_add>");
2500 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2502 "display the partition table",
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command. It is
2506 not intended to be parsed.
2508 See also: C<guestfs_part_list>");
2510 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2512 "display the kernel geometry",
2514 This displays the kernel's idea of the geometry of C<device>.
2516 The result is in human-readable format, and not designed to
2519 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2521 "display the disk geometry from the partition table",
2523 This displays the disk geometry of C<device> read from the
2524 partition table. Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2528 The result is in human-readable format, and not designed to
2531 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2533 "activate or deactivate all volume groups",
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2539 then those devices disappear.
2541 This command is the same as running C<vgchange -a y|n>");
2543 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2545 "activate or deactivate some volume groups",
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2551 then those devices disappear.
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2558 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559 [InitNone, Always, TestOutput (
2560 [["part_disk"; "/dev/sda"; "mbr"];
2561 ["pvcreate"; "/dev/sda1"];
2562 ["vgcreate"; "VG"; "/dev/sda1"];
2563 ["lvcreate"; "LV"; "VG"; "10"];
2564 ["mkfs"; "ext2"; "/dev/VG/LV"];
2565 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566 ["write_file"; "/new"; "test content"; "0"];
2568 ["lvresize"; "/dev/VG/LV"; "20"];
2569 ["e2fsck_f"; "/dev/VG/LV"];
2570 ["resize2fs"; "/dev/VG/LV"];
2571 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572 ["cat"; "/new"]], "test content")],
2573 "resize an LVM logical volume",
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>. When reducing, data in the reduced part
2579 ("resize2fs", (RErr, [Device "device"]), 106, [],
2580 [], (* lvresize tests this *)
2581 "resize an ext2/ext3 filesystem",
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command. For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2592 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593 [InitBasicFS, Always, TestOutputList (
2594 [["find"; "/"]], ["lost+found"]);
2595 InitBasicFS, Always, TestOutputList (
2599 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600 InitBasicFS, Always, TestOutputList (
2601 [["mkdir_p"; "/a/b/c"];
2602 ["touch"; "/a/b/c/d"];
2603 ["find"; "/a/b/"]], ["c"; "c/d"])],
2604 "find all files and directories",
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>. It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2611 This returns a list of strings I<without any prefix>. Thus
2612 if the directory structure was:
2618 then the returned list from C<guestfs_find> C</tmp> would be
2626 If C<directory> is not a directory, then this command returns
2629 The returned list is sorted.
2631 See also C<guestfs_find0>.");
2633 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634 [], (* lvresize tests this *)
2635 "check an ext2/ext3 filesystem",
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.). Normally you should use C<guestfs_fsck>.");
2644 ("sleep", (RErr, [Int "secs"]), 109, [],
2645 [InitNone, Always, TestRun (
2647 "sleep for some seconds",
2649 Sleep for C<secs> seconds.");
2651 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652 [InitNone, Always, TestOutputInt (
2653 [["part_disk"; "/dev/sda"; "mbr"];
2654 ["mkfs"; "ntfs"; "/dev/sda1"];
2655 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656 InitNone, Always, TestOutputInt (
2657 [["part_disk"; "/dev/sda"; "mbr"];
2658 ["mkfs"; "ext2"; "/dev/sda1"];
2659 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660 "probe NTFS volume",
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability. (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2666 C<rw> is a boolean flag. Set it to true if you want to test
2667 if the volume can be mounted read-write. Set it to false if
2668 you want to test if the volume can be mounted read-only.
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2674 ("sh", (RString "output", [String "command"]), 111, [],
2675 [], (* XXX needs tests *)
2676 "run a command via the shell",
2678 This call runs a command from the guest filesystem via the
2681 This is like C<guestfs_command>, but passes the command to:
2683 /bin/sh -c \"command\"
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2689 All the provisos about C<guestfs_command> apply to this call.");
2691 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692 [], (* XXX needs tests *)
2693 "run a command via the shell returning lines",
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2698 See also: C<guestfs_command_lines>");
2700 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702 * code in stubs.c, since all valid glob patterns must start with "/".
2703 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2705 [InitBasicFS, Always, TestOutputList (
2706 [["mkdir_p"; "/a/b/c"];
2707 ["touch"; "/a/b/c/d"];
2708 ["touch"; "/a/b/c/e"];
2709 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710 InitBasicFS, Always, TestOutputList (
2711 [["mkdir_p"; "/a/b/c"];
2712 ["touch"; "/a/b/c/d"];
2713 ["touch"; "/a/b/c/e"];
2714 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715 InitBasicFS, Always, TestOutputList (
2716 [["mkdir_p"; "/a/b/c"];
2717 ["touch"; "/a/b/c/d"];
2718 ["touch"; "/a/b/c/e"];
2719 ["glob_expand"; "/a/*/x/*"]], [])],
2720 "expand a wildcard path",
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2733 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735 [["scrub_device"; "/dev/sdc"]])],
2736 "scrub (securely wipe) a device",
2738 This command writes patterns over C<device> to make data retrieval
2741 It is an interface to the L<scrub(1)> program. See that
2742 manual page for more details.");
2744 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745 [InitBasicFS, Always, TestRun (
2746 [["write_file"; "/file"; "content"; "0"];
2747 ["scrub_file"; "/file"]])],
2748 "scrub (securely wipe) a file",
2750 This command writes patterns over a file to make data retrieval
2753 The file is I<removed> after scrubbing.
2755 It is an interface to the L<scrub(1)> program. See that
2756 manual page for more details.");
2758 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759 [], (* XXX needs testing *)
2760 "scrub (securely wipe) free space",
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2768 It is an interface to the L<scrub(1)> program. See that
2769 manual page for more details.");
2771 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772 [InitBasicFS, Always, TestRun (
2774 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775 "create a temporary directory",
2777 This command creates a temporary directory. The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2785 The name of the temporary directory that was created
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2794 See also: L<mkdtemp(3)>");
2796 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797 [InitISOFS, Always, TestOutputInt (
2798 [["wc_l"; "/10klines"]], 10000)],
2799 "count lines in a file",
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2804 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805 [InitISOFS, Always, TestOutputInt (
2806 [["wc_w"; "/10klines"]], 10000)],
2807 "count words in a file",
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2812 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813 [InitISOFS, Always, TestOutputInt (
2814 [["wc_c"; "/100kallspaces"]], 102400)],
2815 "count characters in a file",
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2820 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821 [InitISOFS, Always, TestOutputList (
2822 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823 "return first 10 lines of a file",
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2828 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829 [InitISOFS, Always, TestOutputList (
2830 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831 InitISOFS, Always, TestOutputList (
2832 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833 InitISOFS, Always, TestOutputList (
2834 [["head_n"; "0"; "/10klines"]], [])],
2835 "return first N lines of a file",
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2845 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846 [InitISOFS, Always, TestOutputList (
2847 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848 "return last 10 lines of a file",
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2853 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854 [InitISOFS, Always, TestOutputList (
2855 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856 InitISOFS, Always, TestOutputList (
2857 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858 InitISOFS, Always, TestOutputList (
2859 [["tail_n"; "0"; "/10klines"]], [])],
2860 "return last N lines of a file",
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2870 ("df", (RString "output", []), 125, [],
2871 [], (* XXX Tricky to test because it depends on the exact format
2872 * of the 'df' command and other imponderables.
2874 "report file system disk space usage",
2876 This command runs the C<df> command to report disk space used.
2878 This command is mostly useful for interactive sessions. It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2882 ("df_h", (RString "output", []), 126, [],
2883 [], (* XXX Tricky to test because it depends on the exact format
2884 * of the 'df' command and other imponderables.
2886 "report file system disk space usage (human readable)",
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2891 This command is mostly useful for interactive sessions. It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2895 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896 [InitISOFS, Always, TestOutputInt (
2897 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898 "estimate file space usage",
2900 This command runs the C<du -s> command to estimate file space
2903 C<path> can be a file or a directory. If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2910 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911 [InitISOFS, Always, TestOutputList (
2912 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913 "list files in an initrd",
2915 This command lists out files contained in an initrd.
2917 The files are listed without any initial C</> character. The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical). Directory names are listed as separate items.
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd. We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2925 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2927 "mount a file using the loop device",
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point. It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2933 ("mkswap", (RErr, [Device "device"]), 130, [],
2934 [InitEmpty, Always, TestRun (
2935 [["part_disk"; "/dev/sda"; "mbr"];
2936 ["mkswap"; "/dev/sda1"]])],
2937 "create a swap partition",
2939 Create a swap partition on C<device>.");
2941 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942 [InitEmpty, Always, TestRun (
2943 [["part_disk"; "/dev/sda"; "mbr"];
2944 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945 "create a swap partition with a label",
2947 Create a swap partition on C<device> with label C<label>.
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition. This appears to be
2951 a limitation of the kernel or swap tools.");
2953 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954 (let uuid = uuidgen () in
2955 [InitEmpty, Always, TestRun (
2956 [["part_disk"; "/dev/sda"; "mbr"];
2957 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958 "create a swap partition with an explicit UUID",
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2962 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963 [InitBasicFS, Always, TestOutputStruct (
2964 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967 InitBasicFS, Always, TestOutputStruct (
2968 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970 "make block, character or FIFO devices",
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2975 The C<mode> parameter should be the mode, using the standard
2976 constants. C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.
2980 Note that, just like L<mknod(2)>, the mode must be bitwise
2981 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2982 just creates a regular file). These constants are
2983 available in the standard Linux header files, or you can use
2984 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
2985 which are wrappers around this command which bitwise OR
2986 in the appropriate constant for you.
2988 The mode actually set is affected by the umask.");
2990 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2991 [InitBasicFS, Always, TestOutputStruct (
2992 [["mkfifo"; "0o777"; "/node"];
2993 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2994 "make FIFO (named pipe)",
2996 This call creates a FIFO (named pipe) called C<path> with
2997 mode C<mode>. It is just a convenient wrapper around
3000 The mode actually set is affected by the umask.");
3002 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3003 [InitBasicFS, Always, TestOutputStruct (
3004 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3005 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3006 "make block device node",
3008 This call creates a block device node called C<path> with
3009 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3010 It is just a convenient wrapper around C<guestfs_mknod>.
3012 The mode actually set is affected by the umask.");
3014 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3015 [InitBasicFS, Always, TestOutputStruct (
3016 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3017 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3018 "make char device node",
3020 This call creates a char device node called C<path> with
3021 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3022 It is just a convenient wrapper around C<guestfs_mknod>.
3024 The mode actually set is affected by the umask.");
3026 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3027 [InitEmpty, Always, TestOutputInt (
3028 [["umask"; "0o22"]], 0o22)],
3029 "set file mode creation mask (umask)",
3031 This function sets the mask used for creating new files and
3032 device nodes to C<mask & 0777>.
3034 Typical umask values would be C<022> which creates new files
3035 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3036 C<002> which creates new files with permissions like
3037 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3039 The default umask is C<022>. This is important because it
3040 means that directories and device nodes will be created with
3041 C<0644> or C<0755> mode even if you specify C<0777>.
3043 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3045 This call returns the previous umask.");
3047 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3049 "read directories entries",
3051 This returns the list of directory entries in directory C<dir>.
3053 All entries in the directory are returned, including C<.> and
3054 C<..>. The entries are I<not> sorted, but returned in the same
3055 order as the underlying filesystem.
3057 Also this call returns basic file type information about each
3058 file. The C<ftyp> field will contain one of the following characters:
3096 The L<readdir(3)> returned a C<d_type> field with an
3101 This function is primarily intended for use by programs. To
3102 get a simple list of names, use C<guestfs_ls>. To get a printable
3103 directory for human consumption, use C<guestfs_ll>.");
3105 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3107 "create partitions on a block device",
3109 This is a simplified interface to the C<guestfs_sfdisk>
3110 command, where partition sizes are specified in megabytes
3111 only (rounded to the nearest cylinder) and you don't need
3112 to specify the cyls, heads and sectors parameters which
3113 were rarely if ever used anyway.
3115 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3116 and C<guestfs_part_disk>");
3118 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3120 "determine file type inside a compressed file",
3122 This command runs C<file> after first decompressing C<path>
3125 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3127 Since 1.0.63, use C<guestfs_file> instead which can now
3128 process compressed files.");
3130 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3132 "list extended attributes of a file or directory",
3134 This call lists the extended attributes of the file or directory
3137 At the system call level, this is a combination of the
3138 L<listxattr(2)> and L<getxattr(2)> calls.
3140 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3142 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3144 "list extended attributes of a file or directory",
3146 This is the same as C<guestfs_getxattrs>, but if C<path>
3147 is a symbolic link, then it returns the extended attributes
3148 of the link itself.");
3150 ("setxattr", (RErr, [String "xattr";
3151 String "val"; Int "vallen"; (* will be BufferIn *)
3152 Pathname "path"]), 143, [Optional "linuxxattrs"],
3154 "set extended attribute of a file or directory",
3156 This call sets the extended attribute named C<xattr>
3157 of the file C<path> to the value C<val> (of length C<vallen>).
3158 The value is arbitrary 8 bit data.
3160 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3162 ("lsetxattr", (RErr, [String "xattr";
3163 String "val"; Int "vallen"; (* will be BufferIn *)
3164 Pathname "path"]), 144, [Optional "linuxxattrs"],
3166 "set extended attribute of a file or directory",
3168 This is the same as C<guestfs_setxattr>, but if C<path>
3169 is a symbolic link, then it sets an extended attribute
3170 of the link itself.");
3172 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3174 "remove extended attribute of a file or directory",
3176 This call removes the extended attribute named C<xattr>
3177 of the file C<path>.
3179 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3181 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3183 "remove extended attribute of a file or directory",
3185 This is the same as C<guestfs_removexattr>, but if C<path>
3186 is a symbolic link, then it removes an extended attribute
3187 of the link itself.");
3189 ("mountpoints", (RHashtable "mps", []), 147, [],
3193 This call is similar to C<guestfs_mounts>. That call returns
3194 a list of devices. This one returns a hash table (map) of
3195 device name to directory where the device is mounted.");
3197 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3198 (* This is a special case: while you would expect a parameter
3199 * of type "Pathname", that doesn't work, because it implies
3200 * NEED_ROOT in the generated calling code in stubs.c, and
3201 * this function cannot use NEED_ROOT.
3204 "create a mountpoint",
3206 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3207 specialized calls that can be used to create extra mountpoints
3208 before mounting the first filesystem.
3210 These calls are I<only> necessary in some very limited circumstances,
3211 mainly the case where you want to mount a mix of unrelated and/or
3212 read-only filesystems together.
3214 For example, live CDs often contain a \"Russian doll\" nest of
3215 filesystems, an ISO outer layer, with a squashfs image inside, with
3216 an ext2/3 image inside that. You can unpack this as follows
3219 add-ro Fedora-11-i686-Live.iso
3222 mkmountpoint /squash
3225 mount-loop /cd/LiveOS/squashfs.img /squash
3226 mount-loop /squash/LiveOS/ext3fs.img /ext3
3228 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3230 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3232 "remove a mountpoint",
3234 This calls removes a mountpoint that was previously created
3235 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3236 for full details.");
3238 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3239 [InitISOFS, Always, TestOutputBuffer (
3240 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3243 This calls returns the contents of the file C<path> as a
3246 Unlike C<guestfs_cat>, this function can correctly
3247 handle files that contain embedded ASCII NUL characters.
3248 However unlike C<guestfs_download>, this function is limited
3249 in the total size of file that can be handled.");
3251 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3252 [InitISOFS, Always, TestOutputList (
3253 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3254 InitISOFS, Always, TestOutputList (
3255 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3256 "return lines matching a pattern",
3258 This calls the external C<grep> program and returns the
3261 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3262 [InitISOFS, Always, TestOutputList (
3263 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3264 "return lines matching a pattern",
3266 This calls the external C<egrep> program and returns the
3269 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3270 [InitISOFS, Always, TestOutputList (
3271 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3272 "return lines matching a pattern",
3274 This calls the external C<fgrep> program and returns the
3277 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3278 [InitISOFS, Always, TestOutputList (
3279 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3280 "return lines matching a pattern",
3282 This calls the external C<grep -i> program and returns the
3285 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3286 [InitISOFS, Always, TestOutputList (
3287 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3288 "return lines matching a pattern",
3290 This calls the external C<egrep -i> program and returns the
3293 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3294 [InitISOFS, Always, TestOutputList (
3295 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3296 "return lines matching a pattern",
3298 This calls the external C<fgrep -i> program and returns the
3301 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3302 [InitISOFS, Always, TestOutputList (
3303 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3304 "return lines matching a pattern",
3306 This calls the external C<zgrep> program and returns the
3309 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3310 [InitISOFS, Always, TestOutputList (
3311 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3312 "return lines matching a pattern",
3314 This calls the external C<zegrep> program and returns the
3317 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3318 [InitISOFS, Always, TestOutputList (
3319 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3320 "return lines matching a pattern",
3322 This calls the external C<zfgrep> program and returns the
3325 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3326 [InitISOFS, Always, TestOutputList (
3327 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3328 "return lines matching a pattern",
3330 This calls the external C<zgrep -i> program and returns the
3333 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3334 [InitISOFS, Always, TestOutputList (
3335 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3336 "return lines matching a pattern",
3338 This calls the external C<zegrep -i> program and returns the
3341 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3342 [InitISOFS, Always, TestOutputList (
3343 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3344 "return lines matching a pattern",
3346 This calls the external C<zfgrep -i> program and returns the
3349 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3350 [InitISOFS, Always, TestOutput (
3351 [["realpath"; "/../directory"]], "/directory")],
3352 "canonicalized absolute pathname",
3354 Return the canonicalized absolute pathname of C<path>. The
3355 returned path has no C<.>, C<..> or symbolic link path elements.");
3357 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3358 [InitBasicFS, Always, TestOutputStruct (
3361 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3362 "create a hard link",
3364 This command creates a hard link using the C<ln> command.");
3366 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3367 [InitBasicFS, Always, TestOutputStruct (
3370 ["ln_f"; "/a"; "/b"];
3371 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3372 "create a hard link",
3374 This command creates a hard link using the C<ln -f> command.
3375 The C<-f> option removes the link (C<linkname>) if it exists already.");
3377 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3378 [InitBasicFS, Always, TestOutputStruct (
3380 ["ln_s"; "a"; "/b"];
3381 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3382 "create a symbolic link",
3384 This command creates a symbolic link using the C<ln -s> command.");
3386 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3387 [InitBasicFS, Always, TestOutput (
3388 [["mkdir_p"; "/a/b"];
3389 ["touch"; "/a/b/c"];
3390 ["ln_sf"; "../d"; "/a/b/c"];
3391 ["readlink"; "/a/b/c"]], "../d")],
3392 "create a symbolic link",
3394 This command creates a symbolic link using the C<ln -sf> command,
3395 The C<-f> option removes the link (C<linkname>) if it exists already.");
3397 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3398 [] (* XXX tested above *),
3399 "read the target of a symbolic link",
3401 This command reads the target of a symbolic link.");
3403 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3404 [InitBasicFS, Always, TestOutputStruct (
3405 [["fallocate"; "/a"; "1000000"];
3406 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3407 "preallocate a file in the guest filesystem",
3409 This command preallocates a file (containing zero bytes) named
3410 C<path> of size C<len> bytes. If the file exists already, it
3413 Do not confuse this with the guestfish-specific
3414 C<alloc> command which allocates a file in the host and
3415 attaches it as a device.");
3417 ("swapon_device", (RErr, [Device "device"]), 170, [],
3418 [InitPartition, Always, TestRun (
3419 [["mkswap"; "/dev/sda1"];
3420 ["swapon_device"; "/dev/sda1"];
3421 ["swapoff_device"; "/dev/sda1"]])],
3422 "enable swap on device",
3424 This command enables the libguestfs appliance to use the
3425 swap device or partition named C<device>. The increased
3426 memory is made available for all commands, for example
3427 those run using C<guestfs_command> or C<guestfs_sh>.
3429 Note that you should not swap to existing guest swap
3430 partitions unless you know what you are doing. They may
3431 contain hibernation information, or other information that
3432 the guest doesn't want you to trash. You also risk leaking
3433 information about the host to the guest this way. Instead,
3434 attach a new host device to the guest and swap on that.");
3436 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3437 [], (* XXX tested by swapon_device *)
3438 "disable swap on device",
3440 This command disables the libguestfs appliance swap
3441 device or partition named C<device>.
3442 See C<guestfs_swapon_device>.");
3444 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3445 [InitBasicFS, Always, TestRun (
3446 [["fallocate"; "/swap"; "8388608"];
3447 ["mkswap_file"; "/swap"];
3448 ["swapon_file"; "/swap"];
3449 ["swapoff_file"; "/swap"]])],
3450 "enable swap on file",
3452 This command enables swap to a file.
3453 See C<guestfs_swapon_device> for other notes.");
3455 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3456 [], (* XXX tested by swapon_file *)
3457 "disable swap on file",
3459 This command disables the libguestfs appliance swap on file.");
3461 ("swapon_label", (RErr, [String "label"]), 174, [],
3462 [InitEmpty, Always, TestRun (
3463 [["part_disk"; "/dev/sdb"; "mbr"];
3464 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3465 ["swapon_label"; "swapit"];
3466 ["swapoff_label"; "swapit"];
3467 ["zero"; "/dev/sdb"];
3468 ["blockdev_rereadpt"; "/dev/sdb"]])],
3469 "enable swap on labeled swap partition",
3471 This command enables swap to a labeled swap partition.
3472 See C<guestfs_swapon_device> for other notes.");
3474 ("swapoff_label", (RErr, [String "label"]), 175, [],
3475 [], (* XXX tested by swapon_label *)
3476 "disable swap on labeled swap partition",
3478 This command disables the libguestfs appliance swap on
3479 labeled swap partition.");
3481 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3482 (let uuid = uuidgen () in
3483 [InitEmpty, Always, TestRun (
3484 [["mkswap_U"; uuid; "/dev/sdb"];
3485 ["swapon_uuid"; uuid];
3486 ["swapoff_uuid"; uuid]])]),
3487 "enable swap on swap partition by UUID",
3489 This command enables swap to a swap partition with the given UUID.
3490 See C<guestfs_swapon_device> for other notes.");
3492 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3493 [], (* XXX tested by swapon_uuid *)
3494 "disable swap on swap partition by UUID",
3496 This command disables the libguestfs appliance swap partition
3497 with the given UUID.");
3499 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3500 [InitBasicFS, Always, TestRun (
3501 [["fallocate"; "/swap"; "8388608"];
3502 ["mkswap_file"; "/swap"]])],
3503 "create a swap file",
3507 This command just writes a swap file signature to an existing
3508 file. To create the file itself, use something like C<guestfs_fallocate>.");
3510 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3511 [InitISOFS, Always, TestRun (
3512 [["inotify_init"; "0"]])],
3513 "create an inotify handle",
3515 This command creates a new inotify handle.
3516 The inotify subsystem can be used to notify events which happen to
3517 objects in the guest filesystem.
3519 C<maxevents> is the maximum number of events which will be
3520 queued up between calls to C<guestfs_inotify_read> or
3521 C<guestfs_inotify_files>.
3522 If this is passed as C<0>, then the kernel (or previously set)
3523 default is used. For Linux 2.6.29 the default was 16384 events.
3524 Beyond this limit, the kernel throws away events, but records
3525 the fact that it threw them away by setting a flag
3526 C<IN_Q_OVERFLOW> in the returned structure list (see
3527 C<guestfs_inotify_read>).
3529 Before any events are generated, you have to add some
3530 watches to the internal watch list. See:
3531 C<guestfs_inotify_add_watch>,
3532 C<guestfs_inotify_rm_watch> and
3533 C<guestfs_inotify_watch_all>.
3535 Queued up events should be read periodically by calling
3536 C<guestfs_inotify_read>
3537 (or C<guestfs_inotify_files> which is just a helpful
3538 wrapper around C<guestfs_inotify_read>). If you don't
3539 read the events out often enough then you risk the internal
3542 The handle should be closed after use by calling
3543 C<guestfs_inotify_close>. This also removes any
3544 watches automatically.
3546 See also L<inotify(7)> for an overview of the inotify interface
3547 as exposed by the Linux kernel, which is roughly what we expose
3548 via libguestfs. Note that there is one global inotify handle
3549 per libguestfs instance.");
3551 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3552 [InitBasicFS, Always, TestOutputList (
3553 [["inotify_init"; "0"];
3554 ["inotify_add_watch"; "/"; "1073741823"];
3557 ["inotify_files"]], ["a"; "b"])],
3558 "add an inotify watch",
3560 Watch C<path> for the events listed in C<mask>.
3562 Note that if C<path> is a directory then events within that
3563 directory are watched, but this does I<not> happen recursively
3564 (in subdirectories).
3566 Note for non-C or non-Linux callers: the inotify events are
3567 defined by the Linux kernel ABI and are listed in
3568 C</usr/include/sys/inotify.h>.");
3570 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3572 "remove an inotify watch",
3574 Remove a previously defined inotify watch.
3575 See C<guestfs_inotify_add_watch>.");
3577 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3579 "return list of inotify events",
3581 Return the complete queue of events that have happened
3582 since the previous read call.
3584 If no events have happened, this returns an empty list.
3586 I<Note>: In order to make sure that all events have been
3587 read, you must call this function repeatedly until it
3588 returns an empty list. The reason is that the call will
3589 read events up to the maximum appliance-to-host message
3590 size and leave remaining events in the queue.");
3592 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3594 "return list of watched files that had events",
3596 This function is a helpful wrapper around C<guestfs_inotify_read>
3597 which just returns a list of pathnames of objects that were
3598 touched. The returned pathnames are sorted and deduplicated.");
3600 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3602 "close the inotify handle",
3604 This closes the inotify handle which was previously
3605 opened by inotify_init. It removes all watches, throws
3606 away any pending events, and deallocates all resources.");
3608 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3610 "set SELinux security context",
3612 This sets the SELinux security context of the daemon
3613 to the string C<context>.
3615 See the documentation about SELINUX in L<guestfs(3)>.");
3617 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3619 "get SELinux security context",
3621 This gets the SELinux security context of the daemon.
3623 See the documentation about SELINUX in L<guestfs(3)>,
3624 and C<guestfs_setcon>");
3626 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3627 [InitEmpty, Always, TestOutput (
3628 [["part_disk"; "/dev/sda"; "mbr"];
3629 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3630 ["mount_options"; ""; "/dev/sda1"; "/"];
3631 ["write_file"; "/new"; "new file contents"; "0"];
3632 ["cat"; "/new"]], "new file contents")],
3633 "make a filesystem with block size",
3635 This call is similar to C<guestfs_mkfs>, but it allows you to
3636 control the block size of the resulting filesystem. Supported
3637 block sizes depend on the filesystem type, but typically they
3638 are C<1024>, C<2048> or C<4096> only.");
3640 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3641 [InitEmpty, Always, TestOutput (
3642 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643 ["mke2journal"; "4096"; "/dev/sda1"];
3644 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3645 ["mount_options"; ""; "/dev/sda2"; "/"];
3646 ["write_file"; "/new"; "new file contents"; "0"];
3647 ["cat"; "/new"]], "new file contents")],
3648 "make ext2/3/4 external journal",
3650 This creates an ext2 external journal on C<device>. It is equivalent
3653 mke2fs -O journal_dev -b blocksize device");
3655 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3656 [InitEmpty, Always, TestOutput (
3657 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3658 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3659 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3660 ["mount_options"; ""; "/dev/sda2"; "/"];
3661 ["write_file"; "/new"; "new file contents"; "0"];
3662 ["cat"; "/new"]], "new file contents")],
3663 "make ext2/3/4 external journal with label",
3665 This creates an ext2 external journal on C<device> with label C<label>.");
3667 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3668 (let uuid = uuidgen () in
3669 [InitEmpty, Always, TestOutput (
3670 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3671 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3672 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3673 ["mount_options"; ""; "/dev/sda2"; "/"];
3674 ["write_file"; "/new"; "new file contents"; "0"];
3675 ["cat"; "/new"]], "new file contents")]),
3676 "make ext2/3/4 external journal with UUID",
3678 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3680 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3682 "make ext2/3/4 filesystem with external journal",
3684 This creates an ext2/3/4 filesystem on C<device> with
3685 an external journal on C<journal>. It is equivalent
3688 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3690 See also C<guestfs_mke2journal>.");
3692 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3694 "make ext2/3/4 filesystem with external journal",
3696 This creates an ext2/3/4 filesystem on C<device> with
3697 an external journal on the journal labeled C<label>.
3699 See also C<guestfs_mke2journal_L>.");
3701 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3703 "make ext2/3/4 filesystem with external journal",
3705 This creates an ext2/3/4 filesystem on C<device> with
3706 an external journal on the journal with UUID C<uuid>.
3708 See also C<guestfs_mke2journal_U>.");
3710 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3711 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3712 "load a kernel module",
3714 This loads a kernel module in the appliance.
3716 The kernel module must have been whitelisted when libguestfs
3717 was built (see C<appliance/kmod.whitelist.in> in the source).");
3719 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3720 [InitNone, Always, TestOutput (
3721 [["echo_daemon"; "This is a test"]], "This is a test"
3723 "echo arguments back to the client",
3725 This command concatenate the list of C<words> passed with single spaces between
3726 them and returns the resulting string.
3728 You can use this command to test the connection through to the daemon.
3730 See also C<guestfs_ping_daemon>.");
3732 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3733 [], (* There is a regression test for this. *)
3734 "find all files and directories, returning NUL-separated list",
3736 This command lists out all files and directories, recursively,
3737 starting at C<directory>, placing the resulting list in the
3738 external file called C<files>.
3740 This command works the same way as C<guestfs_find> with the
3741 following exceptions:
3747 The resulting list is written to an external file.
3751 Items (filenames) in the result are separated
3752 by C<\\0> characters. See L<find(1)> option I<-print0>.
3756 This command is not limited in the number of names that it
3761 The result list is not sorted.
3765 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3766 [InitISOFS, Always, TestOutput (
3767 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3768 InitISOFS, Always, TestOutput (
3769 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3770 InitISOFS, Always, TestOutput (
3771 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3772 InitISOFS, Always, TestLastFail (
3773 [["case_sensitive_path"; "/Known-1/"]]);
3774 InitBasicFS, Always, TestOutput (
3776 ["mkdir"; "/a/bbb"];
3777 ["touch"; "/a/bbb/c"];
3778 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3779 InitBasicFS, Always, TestOutput (
3781 ["mkdir"; "/a/bbb"];
3782 ["touch"; "/a/bbb/c"];
3783 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3784 InitBasicFS, Always, TestLastFail (
3786 ["mkdir"; "/a/bbb"];
3787 ["touch"; "/a/bbb/c"];
3788 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3789 "return true path on case-insensitive filesystem",
3791 This can be used to resolve case insensitive paths on
3792 a filesystem which is case sensitive. The use case is
3793 to resolve paths which you have read from Windows configuration
3794 files or the Windows Registry, to the true path.
3796 The command handles a peculiarity of the Linux ntfs-3g
3797 filesystem driver (and probably others), which is that although
3798 the underlying filesystem is case-insensitive, the driver
3799 exports the filesystem to Linux as case-sensitive.
3801 One consequence of this is that special directories such
3802 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3803 (or other things) depending on the precise details of how
3804 they were created. In Windows itself this would not be
3807 Bug or feature? You decide:
3808 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3810 This function resolves the true case of each element in the
3811 path and returns the case-sensitive path.
3813 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3814 might return C<\"/WINDOWS/system32\"> (the exact return value
3815 would depend on details of how the directories were originally
3816 created under Windows).
3819 This function does not handle drive names, backslashes etc.
3821 See also C<guestfs_realpath>.");
3823 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3824 [InitBasicFS, Always, TestOutput (
3825 [["vfs_type"; "/dev/sda1"]], "ext2")],
3826 "get the Linux VFS type corresponding to a mounted device",
3828 This command gets the block device type corresponding to
3829 a mounted device called C<device>.
3831 Usually the result is the name of the Linux VFS module that
3832 is used to mount this device (probably determined automatically
3833 if you used the C<guestfs_mount> call).");
3835 ("truncate", (RErr, [Pathname "path"]), 199, [],
3836 [InitBasicFS, Always, TestOutputStruct (
3837 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3838 ["truncate"; "/test"];
3839 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3840 "truncate a file to zero size",
3842 This command truncates C<path> to a zero-length file. The
3843 file must exist already.");
3845 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3846 [InitBasicFS, Always, TestOutputStruct (
3847 [["touch"; "/test"];
3848 ["truncate_size"; "/test"; "1000"];
3849 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3850 "truncate a file to a particular size",
3852 This command truncates C<path> to size C<size> bytes. The file
3853 must exist already. If the file is smaller than C<size> then
3854 the file is extended to the required size with null bytes.");
3856 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3857 [InitBasicFS, Always, TestOutputStruct (
3858 [["touch"; "/test"];
3859 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3860 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3861 "set timestamp of a file with nanosecond precision",
3863 This command sets the timestamps of a file with nanosecond
3866 C<atsecs, atnsecs> are the last access time (atime) in secs and
3867 nanoseconds from the epoch.
3869 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3870 secs and nanoseconds from the epoch.
3872 If the C<*nsecs> field contains the special value C<-1> then
3873 the corresponding timestamp is set to the current time. (The
3874 C<*secs> field is ignored in this case).
3876 If the C<*nsecs> field contains the special value C<-2> then
3877 the corresponding timestamp is left unchanged. (The
3878 C<*secs> field is ignored in this case).");
3880 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3881 [InitBasicFS, Always, TestOutputStruct (
3882 [["mkdir_mode"; "/test"; "0o111"];
3883 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3884 "create a directory with a particular mode",
3886 This command creates a directory, setting the initial permissions
3887 of the directory to C<mode>.
3889 For common Linux filesystems, the actual mode which is set will
3890 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3891 interpret the mode in other ways.
3893 See also C<guestfs_mkdir>, C<guestfs_umask>");
3895 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3897 "change file owner and group",
3899 Change the file owner to C<owner> and group to C<group>.
3900 This is like C<guestfs_chown> but if C<path> is a symlink then
3901 the link itself is changed, not the target.
3903 Only numeric uid and gid are supported. If you want to use
3904 names, you will need to locate and parse the password file
3905 yourself (Augeas support makes this relatively easy).");
3907 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3909 "lstat on multiple files",
3911 This call allows you to perform the C<guestfs_lstat> operation
3912 on multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3915 On return you get a list of stat structs, with a one-to-one
3916 correspondence to the C<names> list. If any name did not exist
3917 or could not be lstat'd, then the C<ino> field of that structure
3920 This call is intended for programs that want to efficiently
3921 list a directory contents without making many round-trips.
3922 See also C<guestfs_lxattrlist> for a similarly efficient call
3923 for getting extended attributes. Very long directory listings
3924 might cause the protocol message size to be exceeded, causing
3925 this call to fail. The caller must split up such requests
3926 into smaller groups of names.");
3928 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3930 "lgetxattr on multiple files",
3932 This call allows you to get the extended attributes
3933 of multiple files, where all files are in the directory C<path>.
3934 C<names> is the list of files from this directory.
3936 On return you get a flat list of xattr structs which must be
3937 interpreted sequentially. The first xattr struct always has a zero-length
3938 C<attrname>. C<attrval> in this struct is zero-length
3939 to indicate there was an error doing C<lgetxattr> for this
3940 file, I<or> is a C string which is a decimal number
3941 (the number of following attributes for this file, which could
3942 be C<\"0\">). Then after the first xattr struct are the
3943 zero or more attributes for the first named file.
3944 This repeats for the second and subsequent files.
3946 This call is intended for programs that want to efficiently
3947 list a directory contents without making many round-trips.
3948 See also C<guestfs_lstatlist> for a similarly efficient call
3949 for getting standard stats. Very long directory listings
3950 might cause the protocol message size to be exceeded, causing
3951 this call to fail. The caller must split up such requests
3952 into smaller groups of names.");
3954 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3956 "readlink on multiple files",
3958 This call allows you to do a C<readlink> operation
3959 on multiple files, where all files are in the directory C<path>.
3960 C<names> is the list of files from this directory.
3962 On return you get a list of strings, with a one-to-one
3963 correspondence to the C<names> list. Each string is the
3964 value of the symbol link.
3966 If the C<readlink(2)> operation fails on any name, then
3967 the corresponding result string is the empty string C<\"\">.
3968 However the whole operation is completed even if there
3969 were C<readlink(2)> errors, and so you can call this
3970 function with names where you don't know if they are
3971 symbolic links already (albeit slightly less efficient).
3973 This call is intended for programs that want to efficiently
3974 list a directory contents without making many round-trips.
3975 Very long directory listings might cause the protocol
3976 message size to be exceeded, causing
3977 this call to fail. The caller must split up such requests
3978 into smaller groups of names.");
3980 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3981 [InitISOFS, Always, TestOutputBuffer (
3982 [["pread"; "/known-4"; "1"; "3"]], "\n");
3983 InitISOFS, Always, TestOutputBuffer (
3984 [["pread"; "/empty"; "0"; "100"]], "")],
3985 "read part of a file",
3987 This command lets you read part of a file. It reads C<count>
3988 bytes of the file, starting at C<offset>, from file C<path>.
3990 This may read fewer bytes than requested. For further details
3991 see the L<pread(2)> system call.");
3993 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3994 [InitEmpty, Always, TestRun (
3995 [["part_init"; "/dev/sda"; "gpt"]])],
3996 "create an empty partition table",
3998 This creates an empty partition table on C<device> of one of the
3999 partition types listed below. Usually C<parttype> should be
4000 either C<msdos> or C<gpt> (for large disks).
4002 Initially there are no partitions. Following this, you should
4003 call C<guestfs_part_add> for each partition required.
4005 Possible values for C<parttype> are:
4009 =item B<efi> | B<gpt>
4011 Intel EFI / GPT partition table.
4013 This is recommended for >= 2 TB partitions that will be accessed
4014 from Linux and Intel-based Mac OS X. It also has limited backwards
4015 compatibility with the C<mbr> format.
4017 =item B<mbr> | B<msdos>
4019 The standard PC \"Master Boot Record\" (MBR) format used
4020 by MS-DOS and Windows. This partition type will B<only> work
4021 for device sizes up to 2 TB. For large disks we recommend
4026 Other partition table types that may work but are not
4035 =item B<amiga> | B<rdb>
4037 Amiga \"Rigid Disk Block\" format.
4045 DASD, used on IBM mainframes.
4053 Old Mac partition format. Modern Macs use C<gpt>.
4057 NEC PC-98 format, common in Japan apparently.
4065 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4066 [InitEmpty, Always, TestRun (
4067 [["part_init"; "/dev/sda"; "mbr"];
4068 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4069 InitEmpty, Always, TestRun (
4070 [["part_init"; "/dev/sda"; "gpt"];
4071 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4072 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4073 InitEmpty, Always, TestRun (
4074 [["part_init"; "/dev/sda"; "mbr"];
4075 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4076 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4077 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4078 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4079 "add a partition to the device",
4081 This command adds a partition to C<device>. If there is no partition
4082 table on the device, call C<guestfs_part_init> first.
4084 The C<prlogex> parameter is the type of partition. Normally you
4085 should pass C<p> or C<primary> here, but MBR partition tables also
4086 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4089 C<startsect> and C<endsect> are the start and end of the partition
4090 in I<sectors>. C<endsect> may be negative, which means it counts
4091 backwards from the end of the disk (C<-1> is the last sector).
4093 Creating a partition which covers the whole disk is not so easy.
4094 Use C<guestfs_part_disk> to do that.");
4096 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4097 [InitEmpty, Always, TestRun (
4098 [["part_disk"; "/dev/sda"; "mbr"]]);
4099 InitEmpty, Always, TestRun (
4100 [["part_disk"; "/dev/sda"; "gpt"]])],
4101 "partition whole disk with a single primary partition",
4103 This command is simply a combination of C<guestfs_part_init>
4104 followed by C<guestfs_part_add> to create a single primary partition
4105 covering the whole disk.
4107 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4108 but other possible values are described in C<guestfs_part_init>.");
4110 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4111 [InitEmpty, Always, TestRun (
4112 [["part_disk"; "/dev/sda"; "mbr"];
4113 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4114 "make a partition bootable",
4116 This sets the bootable flag on partition numbered C<partnum> on
4117 device C<device>. Note that partitions are numbered from 1.
4119 The bootable flag is used by some operating systems (notably
4120 Windows) to determine which partition to boot from. It is by
4121 no means universally recognized.");
4123 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4124 [InitEmpty, Always, TestRun (
4125 [["part_disk"; "/dev/sda"; "gpt"];
4126 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4127 "set partition name",
4129 This sets the partition name on partition numbered C<partnum> on
4130 device C<device>. Note that partitions are numbered from 1.
4132 The partition name can only be set on certain types of partition
4133 table. This works on C<gpt> but not on C<mbr> partitions.");
4135 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4136 [], (* XXX Add a regression test for this. *)
4137 "list partitions on a device",
4139 This command parses the partition table on C<device> and
4140 returns the list of partitions found.
4142 The fields in the returned structure are:
4148 Partition number, counting from 1.
4152 Start of the partition I<in bytes>. To get sectors you have to
4153 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4157 End of the partition in bytes.
4161 Size of the partition in bytes.
4165 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4166 [InitEmpty, Always, TestOutput (
4167 [["part_disk"; "/dev/sda"; "gpt"];
4168 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4169 "get the partition table type",
4171 This command examines the partition table on C<device> and
4172 returns the partition table type (format) being used.
4174 Common return values include: C<msdos> (a DOS/Windows style MBR
4175 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4176 values are possible, although unusual. See C<guestfs_part_init>
4179 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4180 [InitBasicFS, Always, TestOutputBuffer (
4181 [["fill"; "0x63"; "10"; "/test"];
4182 ["read_file"; "/test"]], "cccccccccc")],
4183 "fill a file with octets",
4185 This command creates a new file called C<path>. The initial
4186 content of the file is C<len> octets of C<c>, where C<c>
4187 must be a number in the range C<[0..255]>.
4189 To fill a file with zero bytes (sparsely), it is
4190 much more efficient to use C<guestfs_truncate_size>.");
4192 ("available", (RErr, [StringList "groups"]), 216, [],
4193 [InitNone, Always, TestRun [["available"; ""]]],
4194 "test availability of some parts of the API",
4196 This command is used to check the availability of some
4197 groups of functionality in the appliance, which not all builds of
4198 the libguestfs appliance will be able to provide.
4200 The libguestfs groups, and the functions that those
4201 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4203 The argument C<groups> is a list of group names, eg:
4204 C<[\"inotify\", \"augeas\"]> would check for the availability of
4205 the Linux inotify functions and Augeas (configuration file
4208 The command returns no error if I<all> requested groups are available.
4210 It fails with an error if one or more of the requested
4211 groups is unavailable in the appliance.
4213 If an unknown group name is included in the
4214 list of groups then an error is always returned.
4222 You must call C<guestfs_launch> before calling this function.
4224 The reason is because we don't know what groups are
4225 supported by the appliance/daemon until it is running and can
4230 If a group of functions is available, this does not necessarily
4231 mean that they will work. You still have to check for errors
4232 when calling individual API functions even if they are
4237 It is usually the job of distro packagers to build
4238 complete functionality into the libguestfs appliance.
4239 Upstream libguestfs, if built from source with all
4240 requirements satisfied, will support everything.
4244 This call was added in version C<1.0.80>. In previous
4245 versions of libguestfs all you could do would be to speculatively
4246 execute a command to find out if the daemon implemented it.
4247 See also C<guestfs_version>.
4251 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4252 [InitBasicFS, Always, TestOutputBuffer (
4253 [["write_file"; "/src"; "hello, world"; "0"];
4254 ["dd"; "/src"; "/dest"];
4255 ["read_file"; "/dest"]], "hello, world")],
4256 "copy from source to destination using dd",
4258 This command copies from one source device or file C<src>
4259 to another destination device or file C<dest>. Normally you
4260 would use this to copy to or from a device or partition, for
4261 example to duplicate a filesystem.
4263 If the destination is a device, it must be as large or larger
4264 than the source file or device, otherwise the copy will fail.
4265 This command cannot do partial copies (see C<guestfs_copy_size>).");
4267 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4268 [InitBasicFS, Always, TestOutputInt (
4269 [["write_file"; "/file"; "hello, world"; "0"];
4270 ["filesize"; "/file"]], 12)],
4271 "return the size of the file in bytes",
4273 This command returns the size of C<file> in bytes.
4275 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4276 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4277 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4279 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4280 [InitBasicFSonLVM, Always, TestOutputList (
4281 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4282 ["lvs"]], ["/dev/VG/LV2"])],
4283 "rename an LVM logical volume",
4285 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4287 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4288 [InitBasicFSonLVM, Always, TestOutputList (
4290 ["vg_activate"; "false"; "VG"];
4291 ["vgrename"; "VG"; "VG2"];
4292 ["vg_activate"; "true"; "VG2"];
4293 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4294 ["vgs"]], ["VG2"])],
4295 "rename an LVM volume group",
4297 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4299 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4300 [InitISOFS, Always, TestOutputBuffer (
4301 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4302 "list the contents of a single file in an initrd",
4304 This command unpacks the file C<filename> from the initrd file
4305 called C<initrdpath>. The filename must be given I<without> the
4306 initial C</> character.
4308 For example, in guestfish you could use the following command
4309 to examine the boot script (usually called C</init>)
4310 contained in a Linux initrd or initramfs image:
4312 initrd-cat /boot/initrd-<version>.img init
4314 See also C<guestfs_initrd_list>.");
4316 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4318 "get the UUID of a physical volume",
4320 This command returns the UUID of the LVM PV C<device>.");
4322 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4324 "get the UUID of a volume group",
4326 This command returns the UUID of the LVM VG named C<vgname>.");
4328 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4330 "get the UUID of a logical volume",
4332 This command returns the UUID of the LVM LV C<device>.");
4334 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4336 "get the PV UUIDs containing the volume group",
4338 Given a VG called C<vgname>, this returns the UUIDs of all
4339 the physical volumes that this volume group resides on.
4341 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4342 calls to associate physical volumes and volume groups.
4344 See also C<guestfs_vglvuuids>.");
4346 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4348 "get the LV UUIDs of all LVs in the volume group",
4350 Given a VG called C<vgname>, this returns the UUIDs of all
4351 the logical volumes created in this volume group.
4353 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4354 calls to associate logical volumes and volume groups.
4356 See also C<guestfs_vgpvuuids>.");
4358 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4359 [InitBasicFS, Always, TestOutputBuffer (
4360 [["write_file"; "/src"; "hello, world"; "0"];
4361 ["copy_size"; "/src"; "/dest"; "5"];
4362 ["read_file"; "/dest"]], "hello")],
4363 "copy size bytes from source to destination using dd",
4365 This command copies exactly C<size> bytes from one source device
4366 or file C<src> to another destination device or file C<dest>.
4368 Note this will fail if the source is too short or if the destination
4369 is not large enough.");
4371 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4372 [InitEmpty, Always, TestRun (
4373 [["part_init"; "/dev/sda"; "mbr"];
4374 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4375 ["part_del"; "/dev/sda"; "1"]])],
4376 "delete a partition",
4378 This command deletes the partition numbered C<partnum> on C<device>.
4380 Note that in the case of MBR partitioning, deleting an
4381 extended partition also deletes any logical partitions
4384 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4385 [InitEmpty, Always, TestOutputTrue (
4386 [["part_init"; "/dev/sda"; "mbr"];
4387 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4388 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4389 ["part_get_bootable"; "/dev/sda"; "1"]])],
4390 "return true if a partition is bootable",
4392 This command returns true if the partition C<partnum> on
4393 C<device> has the bootable flag set.
4395 See also C<guestfs_part_set_bootable>.");
4397 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4398 [InitEmpty, Always, TestOutputInt (
4399 [["part_init"; "/dev/sda"; "mbr"];
4400 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4401 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4402 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4403 "get the MBR type byte (ID byte) from a partition",
4405 Returns the MBR type byte (also known as the ID byte) from
4406 the numbered partition C<partnum>.
4408 Note that only MBR (old DOS-style) partitions have type bytes.
4409 You will get undefined results for other partition table
4410 types (see C<guestfs_part_get_parttype>).");
4412 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4413 [], (* tested by part_get_mbr_id *)
4414 "set the MBR type byte (ID byte) of a partition",
4416 Sets the MBR type byte (also known as the ID byte) of
4417 the numbered partition C<partnum> to C<idbyte>. Note
4418 that the type bytes quoted in most documentation are
4419 in fact hexadecimal numbers, but usually documented
4420 without any leading \"0x\" which might be confusing.
4422 Note that only MBR (old DOS-style) partitions have type bytes.
4423 You will get undefined results for other partition table
4424 types (see C<guestfs_part_get_parttype>).");
4428 let all_functions = non_daemon_functions @ daemon_functions
4430 (* In some places we want the functions to be displayed sorted
4431 * alphabetically, so this is useful:
4433 let all_functions_sorted =
4434 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4435 compare n1 n2) all_functions
4437 (* Field types for structures. *)
4439 | FChar (* C 'char' (really, a 7 bit byte). *)
4440 | FString (* nul-terminated ASCII string, NOT NULL. *)
4441 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4446 | FBytes (* Any int measure that counts bytes. *)
4447 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4448 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4450 (* Because we generate extra parsing code for LVM command line tools,
4451 * we have to pull out the LVM columns separately here.
4461 "pv_attr", FString (* XXX *);
4462 "pv_pe_count", FInt64;
4463 "pv_pe_alloc_count", FInt64;
4466 "pv_mda_count", FInt64;
4467 "pv_mda_free", FBytes;
4468 (* Not in Fedora 10:
4469 "pv_mda_size", FBytes;
4476 "vg_attr", FString (* XXX *);
4479 "vg_sysid", FString;
4480 "vg_extent_size", FBytes;
4481 "vg_extent_count", FInt64;
4482 "vg_free_count", FInt64;
4487 "snap_count", FInt64;
4490 "vg_mda_count", FInt64;
4491 "vg_mda_free", FBytes;
4492 (* Not in Fedora 10:
4493 "vg_mda_size", FBytes;
4499 "lv_attr", FString (* XXX *);
4502 "lv_kernel_major", FInt64;
4503 "lv_kernel_minor", FInt64;
4505 "seg_count", FInt64;
4507 "snap_percent", FOptPercent;
4508 "copy_percent", FOptPercent;
4511 "mirror_log", FString;
4515 (* Names and fields in all structures (in RStruct and RStructList)
4519 (* The old RIntBool return type, only ever used for aug_defnode. Do
4520 * not use this struct in any new code.
4523 "i", FInt32; (* for historical compatibility *)
4524 "b", FInt32; (* for historical compatibility *)
4527 (* LVM PVs, VGs, LVs. *)
4528 "lvm_pv", lvm_pv_cols;
4529 "lvm_vg", lvm_vg_cols;
4530 "lvm_lv", lvm_lv_cols;
4532 (* Column names and types from stat structures.
4533 * NB. Can't use things like 'st_atime' because glibc header files
4534 * define some of these as macros. Ugh.
4565 (* Column names in dirent structure. *)
4568 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4573 (* Version numbers. *)
4581 (* Extended attribute. *)
4583 "attrname", FString;
4587 (* Inotify events. *)
4591 "in_cookie", FUInt32;
4595 (* Partition table entry. *)
4598 "part_start", FBytes;
4600 "part_size", FBytes;
4602 ] (* end of structs *)
4604 (* Ugh, Java has to be different ..
4605 * These names are also used by the Haskell bindings.
4607 let java_structs = [
4608 "int_bool", "IntBool";
4613 "statvfs", "StatVFS";
4615 "version", "Version";
4617 "inotify_event", "INotifyEvent";
4618 "partition", "Partition";
4621 (* What structs are actually returned. *)
4622 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4624 (* Returns a list of RStruct/RStructList structs that are returned
4625 * by any function. Each element of returned list is a pair:
4627 * (structname, RStructOnly)
4628 * == there exists function which returns RStruct (_, structname)
4629 * (structname, RStructListOnly)
4630 * == there exists function which returns RStructList (_, structname)
4631 * (structname, RStructAndList)
4632 * == there are functions returning both RStruct (_, structname)
4633 * and RStructList (_, structname)
4635 let rstructs_used_by functions =
4636 (* ||| is a "logical OR" for rstructs_used_t *)
4640 | _, RStructAndList -> RStructAndList
4641 | RStructOnly, RStructListOnly
4642 | RStructListOnly, RStructOnly -> RStructAndList
4643 | RStructOnly, RStructOnly -> RStructOnly
4644 | RStructListOnly, RStructListOnly -> RStructListOnly
4647 let h = Hashtbl.create 13 in
4649 (* if elem->oldv exists, update entry using ||| operator,
4650 * else just add elem->newv to the hash
4652 let update elem newv =
4653 try let oldv = Hashtbl.find h elem in
4654 Hashtbl.replace h elem (newv ||| oldv)
4655 with Not_found -> Hashtbl.add h elem newv
4659 fun (_, style, _, _, _, _, _) ->
4660 match fst style with
4661 | RStruct (_, structname) -> update structname RStructOnly
4662 | RStructList (_, structname) -> update structname RStructListOnly
4666 (* return key->values as a list of (key,value) *)
4667 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4669 (* Used for testing language bindings. *)
4671 | CallString of string
4672 | CallOptString of string option
4673 | CallStringList of string list
4675 | CallInt64 of int64
4678 (* Used to memoize the result of pod2text. *)
4679 let pod2text_memo_filename = "src/.pod2text.data"
4680 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4682 let chan = open_in pod2text_memo_filename in
4683 let v = input_value chan in
4687 _ -> Hashtbl.create 13
4688 let pod2text_memo_updated () =
4689 let chan = open_out pod2text_memo_filename in
4690 output_value chan pod2text_memo;
4693 (* Useful functions.
4694 * Note we don't want to use any external OCaml libraries which
4695 * makes this a bit harder than it should be.
4697 module StringMap = Map.Make (String)
4699 let failwithf fs = ksprintf failwith fs
4701 let unique = let i = ref 0 in fun () -> incr i; !i
4703 let replace_char s c1 c2 =
4704 let s2 = String.copy s in
4705 let r = ref false in
4706 for i = 0 to String.length s2 - 1 do
4707 if String.unsafe_get s2 i = c1 then (
4708 String.unsafe_set s2 i c2;
4712 if not !r then s else s2
4716 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4718 let triml ?(test = isspace) str =
4720 let n = ref (String.length str) in
4721 while !n > 0 && test str.[!i]; do
4726 else String.sub str !i !n
4728 let trimr ?(test = isspace) str =
4729 let n = ref (String.length str) in
4730 while !n > 0 && test str.[!n-1]; do
4733 if !n = String.length str then str
4734 else String.sub str 0 !n
4736 let trim ?(test = isspace) str =
4737 trimr ~test (triml ~test str)
4739 let rec find s sub =
4740 let len = String.length s in
4741 let sublen = String.length sub in
4743 if i <= len-sublen then (
4745 if j < sublen then (
4746 if s.[i+j] = sub.[j] then loop2 (j+1)
4752 if r = -1 then loop (i+1) else r
4758 let rec replace_str s s1 s2 =
4759 let len = String.length s in
4760 let sublen = String.length s1 in
4761 let i = find s s1 in
4764 let s' = String.sub s 0 i in
4765 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4766 s' ^ s2 ^ replace_str s'' s1 s2
4769 let rec string_split sep str =
4770 let len = String.length str in
4771 let seplen = String.length sep in
4772 let i = find str sep in
4773 if i = -1 then [str]
4775 let s' = String.sub str 0 i in
4776 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4777 s' :: string_split sep s''
4780 let files_equal n1 n2 =
4781 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4782 match Sys.command cmd with
4785 | i -> failwithf "%s: failed with error code %d" cmd i
4787 let rec filter_map f = function
4791 | Some y -> y :: filter_map f xs
4792 | None -> filter_map f xs
4794 let rec find_map f = function
4795 | [] -> raise Not_found
4799 | None -> find_map f xs
4802 let rec loop i = function
4804 | x :: xs -> f i x; loop (i+1) xs
4809 let rec loop i = function
4811 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4815 let count_chars c str =
4816 let count = ref 0 in
4817 for i = 0 to String.length str - 1 do
4818 if c = String.unsafe_get str i then incr count
4822 let name_of_argt = function
4823 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4824 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4825 | FileIn n | FileOut n -> n
4827 let java_name_of_struct typ =
4828 try List.assoc typ java_structs
4831 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4833 let cols_of_struct typ =
4834 try List.assoc typ structs
4836 failwithf "cols_of_struct: unknown struct %s" typ
4838 let seq_of_test = function
4839 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4840 | TestOutputListOfDevices (s, _)
4841 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4842 | TestOutputTrue s | TestOutputFalse s
4843 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4844 | TestOutputStruct (s, _)
4845 | TestLastFail s -> s
4847 (* Handling for function flags. *)
4848 let protocol_limit_warning =
4849 "Because of the message protocol, there is a transfer limit
4850 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4852 let danger_will_robinson =
4853 "B<This command is dangerous. Without careful use you
4854 can easily destroy all your data>."
4856 let deprecation_notice flags =
4859 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4861 sprintf "This function is deprecated.
4862 In new code, use the C<%s> call instead.
4864 Deprecated functions will not be removed from the API, but the
4865 fact that they are deprecated indicates that there are problems
4866 with correct use of these functions." alt in
4871 (* Create list of optional groups. *)
4873 let h = Hashtbl.create 13 in
4875 fun (name, _, _, flags, _, _, _) ->
4879 let names = try Hashtbl.find h group with Not_found -> [] in
4880 Hashtbl.replace h group (name :: names)
4884 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4887 fun group -> group, List.sort compare (Hashtbl.find h group)
4889 List.sort (fun x y -> compare (fst x) (fst y)) groups
4891 (* Check function names etc. for consistency. *)
4892 let check_functions () =
4893 let contains_uppercase str =
4894 let len = String.length str in
4896 if i >= len then false
4899 if c >= 'A' && c <= 'Z' then true
4906 (* Check function names. *)
4908 fun (name, _, _, _, _, _, _) ->
4909 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4910 failwithf "function name %s does not need 'guestfs' prefix" name;
4912 failwithf "function name is empty";
4913 if name.[0] < 'a' || name.[0] > 'z' then
4914 failwithf "function name %s must start with lowercase a-z" name;
4915 if String.contains name '-' then
4916 failwithf "function name %s should not contain '-', use '_' instead."
4920 (* Check function parameter/return names. *)
4922 fun (name, style, _, _, _, _, _) ->
4923 let check_arg_ret_name n =
4924 if contains_uppercase n then
4925 failwithf "%s param/ret %s should not contain uppercase chars"
4927 if String.contains n '-' || String.contains n '_' then
4928 failwithf "%s param/ret %s should not contain '-' or '_'"
4931 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;
4932 if n = "int" || n = "char" || n = "short" || n = "long" then
4933 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4934 if n = "i" || n = "n" then
4935 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4936 if n = "argv" || n = "args" then
4937 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4939 (* List Haskell, OCaml and C keywords here.
4940 * http://www.haskell.org/haskellwiki/Keywords
4941 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4942 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4943 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4944 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4945 * Omitting _-containing words, since they're handled above.
4946 * Omitting the OCaml reserved word, "val", is ok,
4947 * and saves us from renaming several parameters.
4950 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4951 "char"; "class"; "const"; "constraint"; "continue"; "data";
4952 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4953 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4954 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4955 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4956 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4958 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4959 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4960 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4961 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4962 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4963 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4964 "volatile"; "when"; "where"; "while";
4966 if List.mem n reserved then
4967 failwithf "%s has param/ret using reserved word %s" name n;
4970 (match fst style with
4972 | RInt n | RInt64 n | RBool n
4973 | RConstString n | RConstOptString n | RString n
4974 | RStringList n | RStruct (n, _) | RStructList (n, _)
4975 | RHashtable n | RBufferOut n ->
4976 check_arg_ret_name n
4978 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4981 (* Check short descriptions. *)
4983 fun (name, _, _, _, _, shortdesc, _) ->
4984 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4985 failwithf "short description of %s should begin with lowercase." name;
4986 let c = shortdesc.[String.length shortdesc-1] in
4987 if c = '\n' || c = '.' then
4988 failwithf "short description of %s should not end with . or \\n." name
4991 (* Check long descriptions. *)
4993 fun (name, _, _, _, _, _, longdesc) ->
4994 if longdesc.[String.length longdesc-1] = '\n' then
4995 failwithf "long description of %s should not end with \\n." name
4998 (* Check proc_nrs. *)
5000 fun (name, _, proc_nr, _, _, _, _) ->
5001 if proc_nr <= 0 then
5002 failwithf "daemon function %s should have proc_nr > 0" name
5006 fun (name, _, proc_nr, _, _, _, _) ->
5007 if proc_nr <> -1 then
5008 failwithf "non-daemon function %s should have proc_nr -1" name
5009 ) non_daemon_functions;
5012 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5015 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5016 let rec loop = function
5019 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5021 | (name1,nr1) :: (name2,nr2) :: _ ->
5022 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5030 (* Ignore functions that have no tests. We generate a
5031 * warning when the user does 'make check' instead.
5033 | name, _, _, _, [], _, _ -> ()
5034 | name, _, _, _, tests, _, _ ->
5038 match seq_of_test test with
5040 failwithf "%s has a test containing an empty sequence" name
5041 | cmds -> List.map List.hd cmds
5043 let funcs = List.flatten funcs in
5045 let tested = List.mem name funcs in
5048 failwithf "function %s has tests but does not test itself" name
5051 (* 'pr' prints to the current output file. *)
5052 let chan = ref Pervasives.stdout
5057 let i = count_chars '\n' str in
5058 lines := !lines + i;
5059 output_string !chan str
5062 let copyright_years =
5063 let this_year = 1900 + (localtime (time ())).tm_year in
5064 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5066 (* Generate a header block in a number of standard styles. *)
5067 type comment_style =
5068 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5069 type license = GPLv2plus | LGPLv2plus
5071 let generate_header ?(extra_inputs = []) comment license =
5072 let inputs = "src/generator.ml" :: extra_inputs in
5073 let c = match comment with
5074 | CStyle -> pr "/* "; " *"
5075 | CPlusPlusStyle -> pr "// "; "//"
5076 | HashStyle -> pr "# "; "#"
5077 | OCamlStyle -> pr "(* "; " *"
5078 | HaskellStyle -> pr "{- "; " " in
5079 pr "libguestfs generated file\n";
5080 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5081 List.iter (pr "%s %s\n" c) inputs;
5082 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5084 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5088 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5089 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5090 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5091 pr "%s (at your option) any later version.\n" c;
5093 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5094 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5095 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5096 pr "%s GNU General Public License for more details.\n" c;
5098 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5099 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5100 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5103 pr "%s This library is free software; you can redistribute it and/or\n" c;
5104 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5105 pr "%s License as published by the Free Software Foundation; either\n" c;
5106 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5108 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5109 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5110 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5111 pr "%s Lesser General Public License for more details.\n" c;
5113 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5114 pr "%s License along with this library; if not, write to the Free Software\n" c;
5115 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5118 | CStyle -> pr " */\n"
5121 | OCamlStyle -> pr " *)\n"
5122 | HaskellStyle -> pr "-}\n"
5126 (* Start of main code generation functions below this line. *)
5128 (* Generate the pod documentation for the C API. *)
5129 let rec generate_actions_pod () =
5131 fun (shortname, style, _, flags, _, _, longdesc) ->
5132 if not (List.mem NotInDocs flags) then (
5133 let name = "guestfs_" ^ shortname in
5134 pr "=head2 %s\n\n" name;
5136 generate_prototype ~extern:false ~handle:"g" name style;
5138 pr "%s\n\n" longdesc;
5139 (match fst style with
5141 pr "This function returns 0 on success or -1 on error.\n\n"
5143 pr "On error this function returns -1.\n\n"
5145 pr "On error this function returns -1.\n\n"
5147 pr "This function returns a C truth value on success or -1 on error.\n\n"
5149 pr "This function returns a string, or NULL on error.
5150 The string is owned by the guest handle and must I<not> be freed.\n\n"
5151 | RConstOptString _ ->
5152 pr "This function returns a string which may be NULL.
5153 There is way to return an error from this function.
5154 The string is owned by the guest handle and must I<not> be freed.\n\n"
5156 pr "This function returns a string, or NULL on error.
5157 I<The caller must free the returned string after use>.\n\n"
5159 pr "This function returns a NULL-terminated array of strings
5160 (like L<environ(3)>), or NULL if there was an error.
5161 I<The caller must free the strings and the array after use>.\n\n"
5162 | RStruct (_, typ) ->
5163 pr "This function returns a C<struct guestfs_%s *>,
5164 or NULL if there was an error.
5165 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5166 | RStructList (_, typ) ->
5167 pr "This function returns a C<struct guestfs_%s_list *>
5168 (see E<lt>guestfs-structs.hE<gt>),
5169 or NULL if there was an error.
5170 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5172 pr "This function returns a NULL-terminated array of
5173 strings, or NULL if there was an error.
5174 The array of strings will always have length C<2n+1>, where
5175 C<n> keys and values alternate, followed by the trailing NULL entry.
5176 I<The caller must free the strings and the array after use>.\n\n"
5178 pr "This function returns a buffer, or NULL on error.
5179 The size of the returned buffer is written to C<*size_r>.
5180 I<The caller must free the returned buffer after use>.\n\n"
5182 if List.mem ProtocolLimitWarning flags then
5183 pr "%s\n\n" protocol_limit_warning;
5184 if List.mem DangerWillRobinson flags then
5185 pr "%s\n\n" danger_will_robinson;
5186 match deprecation_notice flags with
5188 | Some txt -> pr "%s\n\n" txt
5190 ) all_functions_sorted
5192 and generate_structs_pod () =
5193 (* Structs documentation. *)
5196 pr "=head2 guestfs_%s\n" typ;
5198 pr " struct guestfs_%s {\n" typ;
5201 | name, FChar -> pr " char %s;\n" name
5202 | name, FUInt32 -> pr " uint32_t %s;\n" name
5203 | name, FInt32 -> pr " int32_t %s;\n" name
5204 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5205 | name, FInt64 -> pr " int64_t %s;\n" name
5206 | name, FString -> pr " char *%s;\n" name
5208 pr " /* The next two fields describe a byte array. */\n";
5209 pr " uint32_t %s_len;\n" name;
5210 pr " char *%s;\n" name
5212 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5213 pr " char %s[32];\n" name
5214 | name, FOptPercent ->
5215 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5216 pr " float %s;\n" name
5220 pr " struct guestfs_%s_list {\n" typ;
5221 pr " uint32_t len; /* Number of elements in list. */\n";
5222 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5225 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5226 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5231 and generate_availability_pod () =
5232 (* Availability documentation. *)
5236 fun (group, functions) ->
5237 pr "=item B<%s>\n" group;
5239 pr "The following functions:\n";
5240 List.iter (pr "L</guestfs_%s>\n") functions;
5246 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5247 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5249 * We have to use an underscore instead of a dash because otherwise
5250 * rpcgen generates incorrect code.
5252 * This header is NOT exported to clients, but see also generate_structs_h.
5254 and generate_xdr () =
5255 generate_header CStyle LGPLv2plus;
5257 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5258 pr "typedef string str<>;\n";
5261 (* Internal structures. *)
5265 pr "struct guestfs_int_%s {\n" typ;
5267 | name, FChar -> pr " char %s;\n" name
5268 | name, FString -> pr " string %s<>;\n" name
5269 | name, FBuffer -> pr " opaque %s<>;\n" name
5270 | name, FUUID -> pr " opaque %s[32];\n" name
5271 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5272 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5273 | name, FOptPercent -> pr " float %s;\n" name
5277 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5282 fun (shortname, style, _, _, _, _, _) ->
5283 let name = "guestfs_" ^ shortname in
5285 (match snd style with
5288 pr "struct %s_args {\n" name;
5291 | Pathname n | Device n | Dev_or_Path n | String n ->
5292 pr " string %s<>;\n" n
5293 | OptString n -> pr " str *%s;\n" n
5294 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5295 | Bool n -> pr " bool %s;\n" n
5296 | Int n -> pr " int %s;\n" n
5297 | Int64 n -> pr " hyper %s;\n" n
5298 | FileIn _ | FileOut _ -> ()
5302 (match fst style with
5305 pr "struct %s_ret {\n" name;
5309 pr "struct %s_ret {\n" name;
5310 pr " hyper %s;\n" n;
5313 pr "struct %s_ret {\n" name;
5316 | RConstString _ | RConstOptString _ ->
5317 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5319 pr "struct %s_ret {\n" name;
5320 pr " string %s<>;\n" n;
5323 pr "struct %s_ret {\n" name;
5324 pr " str %s<>;\n" n;
5326 | RStruct (n, typ) ->
5327 pr "struct %s_ret {\n" name;
5328 pr " guestfs_int_%s %s;\n" typ n;
5330 | RStructList (n, typ) ->
5331 pr "struct %s_ret {\n" name;
5332 pr " guestfs_int_%s_list %s;\n" typ n;
5335 pr "struct %s_ret {\n" name;
5336 pr " str %s<>;\n" n;
5339 pr "struct %s_ret {\n" name;
5340 pr " opaque %s<>;\n" n;
5345 (* Table of procedure numbers. *)
5346 pr "enum guestfs_procedure {\n";
5348 fun (shortname, _, proc_nr, _, _, _, _) ->
5349 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5351 pr " GUESTFS_PROC_NR_PROCS\n";
5355 (* Having to choose a maximum message size is annoying for several
5356 * reasons (it limits what we can do in the API), but it (a) makes
5357 * the protocol a lot simpler, and (b) provides a bound on the size
5358 * of the daemon which operates in limited memory space.
5360 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5363 (* Message header, etc. *)
5365 /* The communication protocol is now documented in the guestfs(3)
5369 const GUESTFS_PROGRAM = 0x2000F5F5;
5370 const GUESTFS_PROTOCOL_VERSION = 1;
5372 /* These constants must be larger than any possible message length. */
5373 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5374 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5376 enum guestfs_message_direction {
5377 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5378 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5381 enum guestfs_message_status {
5382 GUESTFS_STATUS_OK = 0,
5383 GUESTFS_STATUS_ERROR = 1
5386 const GUESTFS_ERROR_LEN = 256;
5388 struct guestfs_message_error {
5389 string error_message<GUESTFS_ERROR_LEN>;
5392 struct guestfs_message_header {
5393 unsigned prog; /* GUESTFS_PROGRAM */
5394 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5395 guestfs_procedure proc; /* GUESTFS_PROC_x */
5396 guestfs_message_direction direction;
5397 unsigned serial; /* message serial number */
5398 guestfs_message_status status;
5401 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5403 struct guestfs_chunk {
5404 int cancel; /* if non-zero, transfer is cancelled */
5405 /* data size is 0 bytes if the transfer has finished successfully */
5406 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5410 (* Generate the guestfs-structs.h file. *)
5411 and generate_structs_h () =
5412 generate_header CStyle LGPLv2plus;
5414 (* This is a public exported header file containing various
5415 * structures. The structures are carefully written to have
5416 * exactly the same in-memory format as the XDR structures that
5417 * we use on the wire to the daemon. The reason for creating
5418 * copies of these structures here is just so we don't have to
5419 * export the whole of guestfs_protocol.h (which includes much
5420 * unrelated and XDR-dependent stuff that we don't want to be
5421 * public, or required by clients).
5423 * To reiterate, we will pass these structures to and from the
5424 * client with a simple assignment or memcpy, so the format
5425 * must be identical to what rpcgen / the RFC defines.
5428 (* Public structures. *)
5431 pr "struct guestfs_%s {\n" typ;
5434 | name, FChar -> pr " char %s;\n" name
5435 | name, FString -> pr " char *%s;\n" name
5437 pr " uint32_t %s_len;\n" name;
5438 pr " char *%s;\n" name
5439 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5440 | name, FUInt32 -> pr " uint32_t %s;\n" name
5441 | name, FInt32 -> pr " int32_t %s;\n" name
5442 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5443 | name, FInt64 -> pr " int64_t %s;\n" name
5444 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5448 pr "struct guestfs_%s_list {\n" typ;
5449 pr " uint32_t len;\n";
5450 pr " struct guestfs_%s *val;\n" typ;
5453 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5454 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5458 (* Generate the guestfs-actions.h file. *)
5459 and generate_actions_h () =
5460 generate_header CStyle LGPLv2plus;
5462 fun (shortname, style, _, _, _, _, _) ->
5463 let name = "guestfs_" ^ shortname in
5464 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5468 (* Generate the guestfs-internal-actions.h file. *)
5469 and generate_internal_actions_h () =
5470 generate_header CStyle LGPLv2plus;
5472 fun (shortname, style, _, _, _, _, _) ->
5473 let name = "guestfs__" ^ shortname in
5474 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5476 ) non_daemon_functions
5478 (* Generate the client-side dispatch stubs. *)
5479 and generate_client_actions () =
5480 generate_header CStyle LGPLv2plus;
5487 #include <inttypes.h>
5489 #include \"guestfs.h\"
5490 #include \"guestfs-internal.h\"
5491 #include \"guestfs-internal-actions.h\"
5492 #include \"guestfs_protocol.h\"
5494 #define error guestfs_error
5495 //#define perrorf guestfs_perrorf
5496 #define safe_malloc guestfs_safe_malloc
5497 #define safe_realloc guestfs_safe_realloc
5498 //#define safe_strdup guestfs_safe_strdup
5499 #define safe_memdup guestfs_safe_memdup
5501 /* Check the return message from a call for validity. */
5503 check_reply_header (guestfs_h *g,
5504 const struct guestfs_message_header *hdr,
5505 unsigned int proc_nr, unsigned int serial)
5507 if (hdr->prog != GUESTFS_PROGRAM) {
5508 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5511 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5512 error (g, \"wrong protocol version (%%d/%%d)\",
5513 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5516 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5517 error (g, \"unexpected message direction (%%d/%%d)\",
5518 hdr->direction, GUESTFS_DIRECTION_REPLY);
5521 if (hdr->proc != proc_nr) {
5522 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5525 if (hdr->serial != serial) {
5526 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5533 /* Check we are in the right state to run a high-level action. */
5535 check_state (guestfs_h *g, const char *caller)
5537 if (!guestfs__is_ready (g)) {
5538 if (guestfs__is_config (g) || guestfs__is_launching (g))
5539 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5542 error (g, \"%%s called from the wrong state, %%d != READY\",
5543 caller, guestfs__get_state (g));
5551 (* Generate code to generate guestfish call traces. *)
5552 let trace_call shortname style =
5553 pr " if (guestfs__get_trace (g)) {\n";
5556 List.exists (function
5557 | StringList _ | DeviceList _ -> true
5558 | _ -> false) (snd style) in
5564 pr " printf (\"%s\");\n" shortname;
5567 | String n (* strings *)
5573 (* guestfish doesn't support string escaping, so neither do we *)
5574 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5575 | OptString n -> (* string option *)
5576 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5577 pr " else printf (\" null\");\n"
5579 | DeviceList n -> (* string list *)
5580 pr " putchar (' ');\n";
5581 pr " putchar ('\"');\n";
5582 pr " for (i = 0; %s[i]; ++i) {\n" n;
5583 pr " if (i > 0) putchar (' ');\n";
5584 pr " fputs (%s[i], stdout);\n" n;
5586 pr " putchar ('\"');\n";
5587 | Bool n -> (* boolean *)
5588 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5589 | Int n -> (* int *)
5590 pr " printf (\" %%d\", %s);\n" n
5592 pr " printf (\" %%\" PRIi64, %s);\n" n
5594 pr " putchar ('\\n');\n";
5599 (* For non-daemon functions, generate a wrapper around each function. *)
5601 fun (shortname, style, _, _, _, _, _) ->
5602 let name = "guestfs_" ^ shortname in
5604 generate_prototype ~extern:false ~semicolon:false ~newline:true
5605 ~handle:"g" name style;
5607 trace_call shortname style;
5608 pr " return guestfs__%s " shortname;
5609 generate_c_call_args ~handle:"g" style;
5613 ) non_daemon_functions;
5615 (* Client-side stubs for each function. *)
5617 fun (shortname, style, _, _, _, _, _) ->
5618 let name = "guestfs_" ^ shortname in
5620 (* Generate the action stub. *)
5621 generate_prototype ~extern:false ~semicolon:false ~newline:true
5622 ~handle:"g" name style;
5625 match fst style with
5626 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5627 | RConstString _ | RConstOptString _ ->
5628 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5629 | RString _ | RStringList _
5630 | RStruct _ | RStructList _
5631 | RHashtable _ | RBufferOut _ ->
5636 (match snd style with
5638 | _ -> pr " struct %s_args args;\n" name
5641 pr " guestfs_message_header hdr;\n";
5642 pr " guestfs_message_error err;\n";
5644 match fst style with
5646 | RConstString _ | RConstOptString _ ->
5647 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5649 | RBool _ | RString _ | RStringList _
5650 | RStruct _ | RStructList _
5651 | RHashtable _ | RBufferOut _ ->
5652 pr " struct %s_ret ret;\n" name;
5655 pr " int serial;\n";
5658 trace_call shortname style;
5659 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5660 pr " guestfs___set_busy (g);\n";
5663 (* Send the main header and arguments. *)
5664 (match snd style with
5666 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5667 (String.uppercase shortname)
5671 | Pathname n | Device n | Dev_or_Path n | String n ->
5672 pr " args.%s = (char *) %s;\n" n n
5674 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5675 | StringList n | DeviceList n ->
5676 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5677 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5679 pr " args.%s = %s;\n" n n
5681 pr " args.%s = %s;\n" n n
5683 pr " args.%s = %s;\n" n n
5684 | FileIn _ | FileOut _ -> ()
5686 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5687 (String.uppercase shortname);
5688 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5691 pr " if (serial == -1) {\n";
5692 pr " guestfs___end_busy (g);\n";
5693 pr " return %s;\n" error_code;
5697 (* Send any additional files (FileIn) requested. *)
5698 let need_read_reply_label = ref false in
5702 pr " r = guestfs___send_file (g, %s);\n" n;
5703 pr " if (r == -1) {\n";
5704 pr " guestfs___end_busy (g);\n";
5705 pr " return %s;\n" error_code;
5707 pr " if (r == -2) /* daemon cancelled */\n";
5708 pr " goto read_reply;\n";
5709 need_read_reply_label := true;
5714 (* Wait for the reply from the remote end. *)
5715 if !need_read_reply_label then pr " read_reply:\n";
5716 pr " memset (&hdr, 0, sizeof hdr);\n";
5717 pr " memset (&err, 0, sizeof err);\n";
5718 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5720 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5724 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5727 pr " if (r == -1) {\n";
5728 pr " guestfs___end_busy (g);\n";
5729 pr " return %s;\n" error_code;
5733 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5734 (String.uppercase shortname);
5735 pr " guestfs___end_busy (g);\n";
5736 pr " return %s;\n" error_code;
5740 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5741 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5742 pr " free (err.error_message);\n";
5743 pr " guestfs___end_busy (g);\n";
5744 pr " return %s;\n" error_code;
5748 (* Expecting to receive further files (FileOut)? *)
5752 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5753 pr " guestfs___end_busy (g);\n";
5754 pr " return %s;\n" error_code;
5760 pr " guestfs___end_busy (g);\n";
5762 (match fst style with
5763 | RErr -> pr " return 0;\n"
5764 | RInt n | RInt64 n | RBool n ->
5765 pr " return ret.%s;\n" n
5766 | RConstString _ | RConstOptString _ ->
5767 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5769 pr " return ret.%s; /* caller will free */\n" n
5770 | RStringList n | RHashtable n ->
5771 pr " /* caller will free this, but we need to add a NULL entry */\n";
5772 pr " ret.%s.%s_val =\n" n n;
5773 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5774 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5776 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5777 pr " return ret.%s.%s_val;\n" n n
5779 pr " /* caller will free this */\n";
5780 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5781 | RStructList (n, _) ->
5782 pr " /* caller will free this */\n";
5783 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5785 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5786 pr " * _val might be NULL here. To make the API saner for\n";
5787 pr " * callers, we turn this case into a unique pointer (using\n";
5788 pr " * malloc(1)).\n";
5790 pr " if (ret.%s.%s_len > 0) {\n" n n;
5791 pr " *size_r = ret.%s.%s_len;\n" n n;
5792 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5794 pr " free (ret.%s.%s_val);\n" n n;
5795 pr " char *p = safe_malloc (g, 1);\n";
5796 pr " *size_r = ret.%s.%s_len;\n" n n;
5804 (* Functions to free structures. *)
5805 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5806 pr " * structure format is identical to the XDR format. See note in\n";
5807 pr " * generator.ml.\n";
5814 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5816 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5822 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5824 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5831 (* Generate daemon/actions.h. *)
5832 and generate_daemon_actions_h () =
5833 generate_header CStyle GPLv2plus;
5835 pr "#include \"../src/guestfs_protocol.h\"\n";
5839 fun (name, style, _, _, _, _, _) ->
5841 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5845 (* Generate the linker script which controls the visibility of
5846 * symbols in the public ABI and ensures no other symbols get
5847 * exported accidentally.
5849 and generate_linker_script () =
5850 generate_header HashStyle GPLv2plus;
5855 "guestfs_get_error_handler";
5856 "guestfs_get_out_of_memory_handler";
5857 "guestfs_last_error";
5858 "guestfs_set_error_handler";
5859 "guestfs_set_launch_done_callback";
5860 "guestfs_set_log_message_callback";
5861 "guestfs_set_out_of_memory_handler";
5862 "guestfs_set_subprocess_quit_callback";
5864 (* Unofficial parts of the API: the bindings code use these
5865 * functions, so it is useful to export them.
5867 "guestfs_safe_calloc";
5868 "guestfs_safe_malloc";
5871 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5875 List.map (fun (typ, _) ->
5876 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5879 let globals = List.sort compare (globals @ functions @ structs) in
5883 List.iter (pr " %s;\n") globals;
5890 (* Generate the server-side stubs. *)
5891 and generate_daemon_actions () =
5892 generate_header CStyle GPLv2plus;
5894 pr "#include <config.h>\n";
5896 pr "#include <stdio.h>\n";
5897 pr "#include <stdlib.h>\n";
5898 pr "#include <string.h>\n";
5899 pr "#include <inttypes.h>\n";
5900 pr "#include <rpc/types.h>\n";
5901 pr "#include <rpc/xdr.h>\n";
5903 pr "#include \"daemon.h\"\n";
5904 pr "#include \"c-ctype.h\"\n";
5905 pr "#include \"../src/guestfs_protocol.h\"\n";
5906 pr "#include \"actions.h\"\n";
5910 fun (name, style, _, _, _, _, _) ->
5911 (* Generate server-side stubs. *)
5912 pr "static void %s_stub (XDR *xdr_in)\n" name;
5915 match fst style with
5916 | RErr | RInt _ -> pr " int r;\n"; "-1"
5917 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5918 | RBool _ -> pr " int r;\n"; "-1"
5919 | RConstString _ | RConstOptString _ ->
5920 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5921 | RString _ -> pr " char *r;\n"; "NULL"
5922 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5923 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5924 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5926 pr " size_t size = 1;\n";
5930 (match snd style with
5933 pr " struct guestfs_%s_args args;\n" name;
5936 | Device n | Dev_or_Path n
5939 | OptString n -> pr " char *%s;\n" n
5940 | StringList n | DeviceList n -> pr " char **%s;\n" n
5941 | Bool n -> pr " int %s;\n" n
5942 | Int n -> pr " int %s;\n" n
5943 | Int64 n -> pr " int64_t %s;\n" n
5944 | FileIn _ | FileOut _ -> ()
5949 (match snd style with
5952 pr " memset (&args, 0, sizeof args);\n";
5954 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5955 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5959 pr " char *%s = args.%s;\n" n n
5961 let pr_list_handling_code n =
5962 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5963 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5964 pr " if (%s == NULL) {\n" n;
5965 pr " reply_with_perror (\"realloc\");\n";
5968 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5969 pr " args.%s.%s_val = %s;\n" n n n;
5975 pr " ABS_PATH (%s, goto done);\n" n;
5978 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5981 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5982 | String n -> pr_args n
5983 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5985 pr_list_handling_code n;
5987 pr_list_handling_code n;
5988 pr " /* Ensure that each is a device,\n";
5989 pr " * and perform device name translation. */\n";
5990 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5991 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5993 | Bool n -> pr " %s = args.%s;\n" n n
5994 | Int n -> pr " %s = args.%s;\n" n n
5995 | Int64 n -> pr " %s = args.%s;\n" n n
5996 | FileIn _ | FileOut _ -> ()
6002 (* this is used at least for do_equal *)
6003 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6004 (* Emit NEED_ROOT just once, even when there are two or
6005 more Pathname args *)
6006 pr " NEED_ROOT (goto done);\n";
6009 (* Don't want to call the impl with any FileIn or FileOut
6010 * parameters, since these go "outside" the RPC protocol.
6013 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6015 pr " r = do_%s " name;
6016 generate_c_call_args (fst style, args');
6019 (match fst style with
6020 | RErr | RInt _ | RInt64 _ | RBool _
6021 | RConstString _ | RConstOptString _
6022 | RString _ | RStringList _ | RHashtable _
6023 | RStruct (_, _) | RStructList (_, _) ->
6024 pr " if (r == %s)\n" error_code;
6025 pr " /* do_%s has already called reply_with_error */\n" name;
6029 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6030 pr " * an ordinary zero-length buffer), so be careful ...\n";
6032 pr " if (size == 1 && r == %s)\n" error_code;
6033 pr " /* do_%s has already called reply_with_error */\n" name;
6038 (* If there are any FileOut parameters, then the impl must
6039 * send its own reply.
6042 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6044 pr " /* do_%s has already sent a reply */\n" name
6046 match fst style with
6047 | RErr -> pr " reply (NULL, NULL);\n"
6048 | RInt n | RInt64 n | RBool n ->
6049 pr " struct guestfs_%s_ret ret;\n" name;
6050 pr " ret.%s = r;\n" n;
6051 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6053 | RConstString _ | RConstOptString _ ->
6054 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6056 pr " struct guestfs_%s_ret ret;\n" name;
6057 pr " ret.%s = r;\n" n;
6058 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6061 | RStringList n | RHashtable n ->
6062 pr " struct guestfs_%s_ret ret;\n" name;
6063 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6064 pr " ret.%s.%s_val = r;\n" n n;
6065 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6067 pr " free_strings (r);\n"
6069 pr " struct guestfs_%s_ret ret;\n" name;
6070 pr " ret.%s = *r;\n" n;
6071 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6073 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6075 | RStructList (n, _) ->
6076 pr " struct guestfs_%s_ret ret;\n" name;
6077 pr " ret.%s = *r;\n" n;
6078 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6080 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6083 pr " struct guestfs_%s_ret ret;\n" name;
6084 pr " ret.%s.%s_val = r;\n" n n;
6085 pr " ret.%s.%s_len = size;\n" n n;
6086 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6091 (* Free the args. *)
6092 (match snd style with
6097 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6104 (* Dispatch function. *)
6105 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6107 pr " switch (proc_nr) {\n";
6110 fun (name, style, _, _, _, _, _) ->
6111 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6112 pr " %s_stub (xdr_in);\n" name;
6117 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";
6122 (* LVM columns and tokenization functions. *)
6123 (* XXX This generates crap code. We should rethink how we
6129 pr "static const char *lvm_%s_cols = \"%s\";\n"
6130 typ (String.concat "," (List.map fst cols));
6133 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6135 pr " char *tok, *p, *next;\n";
6139 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6142 pr " if (!str) {\n";
6143 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6146 pr " if (!*str || c_isspace (*str)) {\n";
6147 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6152 fun (name, coltype) ->
6153 pr " if (!tok) {\n";
6154 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6157 pr " p = strchrnul (tok, ',');\n";
6158 pr " if (*p) next = p+1; else next = NULL;\n";
6159 pr " *p = '\\0';\n";
6162 pr " r->%s = strdup (tok);\n" name;
6163 pr " if (r->%s == NULL) {\n" name;
6164 pr " perror (\"strdup\");\n";
6168 pr " for (i = j = 0; i < 32; ++j) {\n";
6169 pr " if (tok[j] == '\\0') {\n";
6170 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6172 pr " } else if (tok[j] != '-')\n";
6173 pr " r->%s[i++] = tok[j];\n" name;
6176 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6177 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6181 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6182 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6186 pr " if (tok[0] == '\\0')\n";
6187 pr " r->%s = -1;\n" name;
6188 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6189 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6192 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6193 assert false (* can never be an LVM column *)
6195 pr " tok = next;\n";
6198 pr " if (tok != NULL) {\n";
6199 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6206 pr "guestfs_int_lvm_%s_list *\n" typ;
6207 pr "parse_command_line_%ss (void)\n" typ;
6209 pr " char *out, *err;\n";
6210 pr " char *p, *pend;\n";
6212 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6213 pr " void *newp;\n";
6215 pr " ret = malloc (sizeof *ret);\n";
6216 pr " if (!ret) {\n";
6217 pr " reply_with_perror (\"malloc\");\n";
6218 pr " return NULL;\n";
6221 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6222 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6224 pr " r = command (&out, &err,\n";
6225 pr " \"lvm\", \"%ss\",\n" typ;
6226 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6227 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6228 pr " if (r == -1) {\n";
6229 pr " reply_with_error (\"%%s\", err);\n";
6230 pr " free (out);\n";
6231 pr " free (err);\n";
6232 pr " free (ret);\n";
6233 pr " return NULL;\n";
6236 pr " free (err);\n";
6238 pr " /* Tokenize each line of the output. */\n";
6241 pr " while (p) {\n";
6242 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6243 pr " if (pend) {\n";
6244 pr " *pend = '\\0';\n";
6248 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6251 pr " if (!*p) { /* Empty line? Skip it. */\n";
6256 pr " /* Allocate some space to store this next entry. */\n";
6257 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6258 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6259 pr " if (newp == NULL) {\n";
6260 pr " reply_with_perror (\"realloc\");\n";
6261 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6262 pr " free (ret);\n";
6263 pr " free (out);\n";
6264 pr " return NULL;\n";
6266 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6268 pr " /* Tokenize the next entry. */\n";
6269 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6270 pr " if (r == -1) {\n";
6271 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6272 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6273 pr " free (ret);\n";
6274 pr " free (out);\n";
6275 pr " return NULL;\n";
6282 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6284 pr " free (out);\n";
6285 pr " return ret;\n";
6288 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6290 (* Generate a list of function names, for debugging in the daemon.. *)
6291 and generate_daemon_names () =
6292 generate_header CStyle GPLv2plus;
6294 pr "#include <config.h>\n";
6296 pr "#include \"daemon.h\"\n";
6299 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6300 pr "const char *function_names[] = {\n";
6302 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6306 (* Generate the optional groups for the daemon to implement
6307 * guestfs_available.
6309 and generate_daemon_optgroups_c () =
6310 generate_header CStyle GPLv2plus;
6312 pr "#include <config.h>\n";
6314 pr "#include \"daemon.h\"\n";
6315 pr "#include \"optgroups.h\"\n";
6318 pr "struct optgroup optgroups[] = {\n";
6321 pr " { \"%s\", optgroup_%s_available },\n" group group
6323 pr " { NULL, NULL }\n";
6326 and generate_daemon_optgroups_h () =
6327 generate_header CStyle GPLv2plus;
6331 pr "extern int optgroup_%s_available (void);\n" group
6334 (* Generate the tests. *)
6335 and generate_tests () =
6336 generate_header CStyle GPLv2plus;
6343 #include <sys/types.h>
6346 #include \"guestfs.h\"
6347 #include \"guestfs-internal.h\"
6349 static guestfs_h *g;
6350 static int suppress_error = 0;
6352 static void print_error (guestfs_h *g, void *data, const char *msg)
6354 if (!suppress_error)
6355 fprintf (stderr, \"%%s\\n\", msg);
6358 /* FIXME: nearly identical code appears in fish.c */
6359 static void print_strings (char *const *argv)
6363 for (argc = 0; argv[argc] != NULL; ++argc)
6364 printf (\"\\t%%s\\n\", argv[argc]);
6368 static void print_table (char const *const *argv)
6372 for (i = 0; argv[i] != NULL; i += 2)
6373 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6379 (* Generate a list of commands which are not tested anywhere. *)
6380 pr "static void no_test_warnings (void)\n";
6383 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6385 fun (_, _, _, _, tests, _, _) ->
6386 let tests = filter_map (
6388 | (_, (Always|If _|Unless _), test) -> Some test
6389 | (_, Disabled, _) -> None
6391 let seq = List.concat (List.map seq_of_test tests) in
6392 let cmds_tested = List.map List.hd seq in
6393 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6397 fun (name, _, _, _, _, _, _) ->
6398 if not (Hashtbl.mem hash name) then
6399 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6405 (* Generate the actual tests. Note that we generate the tests
6406 * in reverse order, deliberately, so that (in general) the
6407 * newest tests run first. This makes it quicker and easier to
6412 fun (name, _, _, flags, tests, _, _) ->
6413 mapi (generate_one_test name flags) tests
6414 ) (List.rev all_functions) in
6415 let test_names = List.concat test_names in
6416 let nr_tests = List.length test_names in
6419 int main (int argc, char *argv[])
6422 unsigned long int n_failed = 0;
6423 const char *filename;
6425 int nr_tests, test_num = 0;
6427 setbuf (stdout, NULL);
6429 no_test_warnings ();
6431 g = guestfs_create ();
6433 printf (\"guestfs_create FAILED\\n\");
6434 exit (EXIT_FAILURE);
6437 guestfs_set_error_handler (g, print_error, NULL);
6439 guestfs_set_path (g, \"../appliance\");
6441 filename = \"test1.img\";
6442 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6445 exit (EXIT_FAILURE);
6447 if (lseek (fd, %d, SEEK_SET) == -1) {
6451 exit (EXIT_FAILURE);
6453 if (write (fd, &c, 1) == -1) {
6457 exit (EXIT_FAILURE);
6459 if (close (fd) == -1) {
6462 exit (EXIT_FAILURE);
6464 if (guestfs_add_drive (g, filename) == -1) {
6465 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6466 exit (EXIT_FAILURE);
6469 filename = \"test2.img\";
6470 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6473 exit (EXIT_FAILURE);
6475 if (lseek (fd, %d, SEEK_SET) == -1) {
6479 exit (EXIT_FAILURE);
6481 if (write (fd, &c, 1) == -1) {
6485 exit (EXIT_FAILURE);
6487 if (close (fd) == -1) {
6490 exit (EXIT_FAILURE);
6492 if (guestfs_add_drive (g, filename) == -1) {
6493 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6494 exit (EXIT_FAILURE);
6497 filename = \"test3.img\";
6498 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6501 exit (EXIT_FAILURE);
6503 if (lseek (fd, %d, SEEK_SET) == -1) {
6507 exit (EXIT_FAILURE);
6509 if (write (fd, &c, 1) == -1) {
6513 exit (EXIT_FAILURE);
6515 if (close (fd) == -1) {
6518 exit (EXIT_FAILURE);
6520 if (guestfs_add_drive (g, filename) == -1) {
6521 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6522 exit (EXIT_FAILURE);
6525 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6526 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6527 exit (EXIT_FAILURE);
6530 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6533 if (guestfs_launch (g) == -1) {
6534 printf (\"guestfs_launch FAILED\\n\");
6535 exit (EXIT_FAILURE);
6538 /* Cancel previous alarm. */
6543 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6547 pr " test_num++;\n";
6548 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6549 pr " if (%s () == -1) {\n" test_name;
6550 pr " printf (\"%s FAILED\\n\");\n" test_name;
6551 pr " n_failed++;\n";
6556 pr " guestfs_close (g);\n";
6557 pr " unlink (\"test1.img\");\n";
6558 pr " unlink (\"test2.img\");\n";
6559 pr " unlink (\"test3.img\");\n";
6562 pr " if (n_failed > 0) {\n";
6563 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6564 pr " exit (EXIT_FAILURE);\n";
6568 pr " exit (EXIT_SUCCESS);\n";
6571 and generate_one_test name flags i (init, prereq, test) =
6572 let test_name = sprintf "test_%s_%d" name i in
6575 static int %s_skip (void)
6579 str = getenv (\"TEST_ONLY\");
6581 return strstr (str, \"%s\") == NULL;
6582 str = getenv (\"SKIP_%s\");
6583 if (str && STREQ (str, \"1\")) return 1;
6584 str = getenv (\"SKIP_TEST_%s\");
6585 if (str && STREQ (str, \"1\")) return 1;
6589 " test_name name (String.uppercase test_name) (String.uppercase name);
6592 | Disabled | Always -> ()
6593 | If code | Unless code ->
6594 pr "static int %s_prereq (void)\n" test_name;
6602 static int %s (void)
6605 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6609 " test_name test_name test_name;
6611 (* Optional functions should only be tested if the relevant
6612 * support is available in the daemon.
6618 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6620 pr " suppress_error = 1;\n";
6621 pr " r = guestfs_available (g, (char **) groups);\n";
6622 pr " suppress_error = 0;\n";
6623 pr " if (r == -1) {\n";
6624 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6633 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6635 pr " if (! %s_prereq ()) {\n" test_name;
6636 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6640 generate_one_test_body name i test_name init test;
6642 pr " if (%s_prereq ()) {\n" test_name;
6643 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6647 generate_one_test_body name i test_name init test;
6649 generate_one_test_body name i test_name init test
6657 and generate_one_test_body name i test_name init test =
6659 | InitNone (* XXX at some point, InitNone and InitEmpty became
6660 * folded together as the same thing. Really we should
6661 * make InitNone do nothing at all, but the tests may
6662 * need to be checked to make sure this is OK.
6665 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6666 List.iter (generate_test_command_call test_name)
6667 [["blockdev_setrw"; "/dev/sda"];
6671 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6672 List.iter (generate_test_command_call test_name)
6673 [["blockdev_setrw"; "/dev/sda"];
6676 ["part_disk"; "/dev/sda"; "mbr"]]
6678 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6679 List.iter (generate_test_command_call test_name)
6680 [["blockdev_setrw"; "/dev/sda"];
6683 ["part_disk"; "/dev/sda"; "mbr"];
6684 ["mkfs"; "ext2"; "/dev/sda1"];
6685 ["mount_options"; ""; "/dev/sda1"; "/"]]
6686 | InitBasicFSonLVM ->
6687 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6689 List.iter (generate_test_command_call test_name)
6690 [["blockdev_setrw"; "/dev/sda"];
6693 ["part_disk"; "/dev/sda"; "mbr"];
6694 ["pvcreate"; "/dev/sda1"];
6695 ["vgcreate"; "VG"; "/dev/sda1"];
6696 ["lvcreate"; "LV"; "VG"; "8"];
6697 ["mkfs"; "ext2"; "/dev/VG/LV"];
6698 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6700 pr " /* InitISOFS for %s */\n" test_name;
6701 List.iter (generate_test_command_call test_name)
6702 [["blockdev_setrw"; "/dev/sda"];
6705 ["mount_ro"; "/dev/sdd"; "/"]]
6708 let get_seq_last = function
6710 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6713 let seq = List.rev seq in
6714 List.rev (List.tl seq), List.hd seq
6719 pr " /* TestRun for %s (%d) */\n" name i;
6720 List.iter (generate_test_command_call test_name) seq
6721 | TestOutput (seq, expected) ->
6722 pr " /* TestOutput for %s (%d) */\n" name i;
6723 pr " const char *expected = \"%s\";\n" (c_quote expected);
6724 let seq, last = get_seq_last seq in
6726 pr " if (STRNEQ (r, expected)) {\n";
6727 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6731 List.iter (generate_test_command_call test_name) seq;
6732 generate_test_command_call ~test test_name last
6733 | TestOutputList (seq, expected) ->
6734 pr " /* TestOutputList for %s (%d) */\n" name i;
6735 let seq, last = get_seq_last seq in
6739 pr " if (!r[%d]) {\n" i;
6740 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6741 pr " print_strings (r);\n";
6745 pr " const char *expected = \"%s\";\n" (c_quote str);
6746 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6747 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6752 pr " if (r[%d] != NULL) {\n" (List.length expected);
6753 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6755 pr " print_strings (r);\n";
6759 List.iter (generate_test_command_call test_name) seq;
6760 generate_test_command_call ~test test_name last
6761 | TestOutputListOfDevices (seq, expected) ->
6762 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6763 let seq, last = get_seq_last seq in
6767 pr " if (!r[%d]) {\n" i;
6768 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6769 pr " print_strings (r);\n";
6773 pr " const char *expected = \"%s\";\n" (c_quote str);
6774 pr " r[%d][5] = 's';\n" i;
6775 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6776 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6781 pr " if (r[%d] != NULL) {\n" (List.length expected);
6782 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6784 pr " print_strings (r);\n";
6788 List.iter (generate_test_command_call test_name) seq;
6789 generate_test_command_call ~test test_name last
6790 | TestOutputInt (seq, expected) ->
6791 pr " /* TestOutputInt for %s (%d) */\n" name i;
6792 let seq, last = get_seq_last seq in
6794 pr " if (r != %d) {\n" expected;
6795 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6801 List.iter (generate_test_command_call test_name) seq;
6802 generate_test_command_call ~test test_name last
6803 | TestOutputIntOp (seq, op, expected) ->
6804 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6805 let seq, last = get_seq_last seq in
6807 pr " if (! (r %s %d)) {\n" op expected;
6808 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6809 test_name op expected;
6814 List.iter (generate_test_command_call test_name) seq;
6815 generate_test_command_call ~test test_name last
6816 | TestOutputTrue seq ->
6817 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6818 let seq, last = get_seq_last seq in
6821 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6826 List.iter (generate_test_command_call test_name) seq;
6827 generate_test_command_call ~test test_name last
6828 | TestOutputFalse seq ->
6829 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6830 let seq, last = get_seq_last seq in
6833 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6838 List.iter (generate_test_command_call test_name) seq;
6839 generate_test_command_call ~test test_name last
6840 | TestOutputLength (seq, expected) ->
6841 pr " /* TestOutputLength for %s (%d) */\n" name i;
6842 let seq, last = get_seq_last seq in
6845 pr " for (j = 0; j < %d; ++j)\n" expected;
6846 pr " if (r[j] == NULL) {\n";
6847 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6849 pr " print_strings (r);\n";
6852 pr " if (r[j] != NULL) {\n";
6853 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6855 pr " print_strings (r);\n";
6859 List.iter (generate_test_command_call test_name) seq;
6860 generate_test_command_call ~test test_name last
6861 | TestOutputBuffer (seq, expected) ->
6862 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6863 pr " const char *expected = \"%s\";\n" (c_quote expected);
6864 let seq, last = get_seq_last seq in
6865 let len = String.length expected in
6867 pr " if (size != %d) {\n" len;
6868 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6871 pr " if (STRNEQLEN (r, expected, size)) {\n";
6872 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6876 List.iter (generate_test_command_call test_name) seq;
6877 generate_test_command_call ~test test_name last
6878 | TestOutputStruct (seq, checks) ->
6879 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6880 let seq, last = get_seq_last seq in
6884 | CompareWithInt (field, expected) ->
6885 pr " if (r->%s != %d) {\n" field expected;
6886 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6887 test_name field expected;
6888 pr " (int) r->%s);\n" field;
6891 | CompareWithIntOp (field, op, expected) ->
6892 pr " if (!(r->%s %s %d)) {\n" field op expected;
6893 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6894 test_name field op expected;
6895 pr " (int) r->%s);\n" field;
6898 | CompareWithString (field, expected) ->
6899 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6900 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6901 test_name field expected;
6902 pr " r->%s);\n" field;
6905 | CompareFieldsIntEq (field1, field2) ->
6906 pr " if (r->%s != r->%s) {\n" field1 field2;
6907 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6908 test_name field1 field2;
6909 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6912 | CompareFieldsStrEq (field1, field2) ->
6913 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6914 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6915 test_name field1 field2;
6916 pr " r->%s, r->%s);\n" field1 field2;
6921 List.iter (generate_test_command_call test_name) seq;
6922 generate_test_command_call ~test test_name last
6923 | TestLastFail seq ->
6924 pr " /* TestLastFail for %s (%d) */\n" name i;
6925 let seq, last = get_seq_last seq in
6926 List.iter (generate_test_command_call test_name) seq;
6927 generate_test_command_call test_name ~expect_error:true last
6929 (* Generate the code to run a command, leaving the result in 'r'.
6930 * If you expect to get an error then you should set expect_error:true.
6932 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6934 | [] -> assert false
6936 (* Look up the command to find out what args/ret it has. *)
6939 let _, style, _, _, _, _, _ =
6940 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6943 failwithf "%s: in test, command %s was not found" test_name name in
6945 if List.length (snd style) <> List.length args then
6946 failwithf "%s: in test, wrong number of args given to %s"
6953 | OptString n, "NULL" -> ()
6956 | Dev_or_Path n, arg
6958 | OptString n, arg ->
6959 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6963 | FileIn _, _ | FileOut _, _ -> ()
6964 | StringList n, "" | DeviceList n, "" ->
6965 pr " const char *const %s[1] = { NULL };\n" n
6966 | StringList n, arg | DeviceList n, arg ->
6967 let strs = string_split " " arg in
6970 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
6972 pr " const char *const %s[] = {\n" n;
6974 fun i _ -> pr " %s_%d,\n" n i
6978 ) (List.combine (snd style) args);
6981 match fst style with
6982 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6983 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6984 | RConstString _ | RConstOptString _ ->
6985 pr " const char *r;\n"; "NULL"
6986 | RString _ -> pr " char *r;\n"; "NULL"
6987 | RStringList _ | RHashtable _ ->
6991 | RStruct (_, typ) ->
6992 pr " struct guestfs_%s *r;\n" typ; "NULL"
6993 | RStructList (_, typ) ->
6994 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6997 pr " size_t size;\n";
7000 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7001 pr " r = guestfs_%s (g" name;
7003 (* Generate the parameters. *)
7006 | OptString _, "NULL" -> pr ", NULL"
7008 | Device n, _ | Dev_or_Path n, _
7012 | FileIn _, arg | FileOut _, arg ->
7013 pr ", \"%s\"" (c_quote arg)
7014 | StringList n, _ | DeviceList n, _ ->
7015 pr ", (char **) %s" n
7018 try int_of_string arg
7019 with Failure "int_of_string" ->
7020 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7024 try Int64.of_string arg
7025 with Failure "int_of_string" ->
7026 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7029 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7030 ) (List.combine (snd style) args);
7032 (match fst style with
7033 | RBufferOut _ -> pr ", &size"
7039 if not expect_error then
7040 pr " if (r == %s)\n" error_code
7042 pr " if (r != %s)\n" error_code;
7045 (* Insert the test code. *)
7051 (match fst style with
7052 | RErr | RInt _ | RInt64 _ | RBool _
7053 | RConstString _ | RConstOptString _ -> ()
7054 | RString _ | RBufferOut _ -> pr " free (r);\n"
7055 | RStringList _ | RHashtable _ ->
7056 pr " for (i = 0; r[i] != NULL; ++i)\n";
7057 pr " free (r[i]);\n";
7059 | RStruct (_, typ) ->
7060 pr " guestfs_free_%s (r);\n" typ
7061 | RStructList (_, typ) ->
7062 pr " guestfs_free_%s_list (r);\n" typ
7068 let str = replace_str str "\r" "\\r" in
7069 let str = replace_str str "\n" "\\n" in
7070 let str = replace_str str "\t" "\\t" in
7071 let str = replace_str str "\000" "\\0" in
7074 (* Generate a lot of different functions for guestfish. *)
7075 and generate_fish_cmds () =
7076 generate_header CStyle GPLv2plus;
7080 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7082 let all_functions_sorted =
7084 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7085 ) all_functions_sorted in
7087 pr "#include <config.h>\n";
7089 pr "#include <stdio.h>\n";
7090 pr "#include <stdlib.h>\n";
7091 pr "#include <string.h>\n";
7092 pr "#include <inttypes.h>\n";
7094 pr "#include <guestfs.h>\n";
7095 pr "#include \"c-ctype.h\"\n";
7096 pr "#include \"full-write.h\"\n";
7097 pr "#include \"xstrtol.h\"\n";
7098 pr "#include \"fish.h\"\n";
7101 (* list_commands function, which implements guestfish -h *)
7102 pr "void list_commands (void)\n";
7104 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7105 pr " list_builtin_commands ();\n";
7107 fun (name, _, _, flags, _, shortdesc, _) ->
7108 let name = replace_char name '_' '-' in
7109 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7111 ) all_functions_sorted;
7112 pr " printf (\" %%s\\n\",";
7113 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7117 (* display_command function, which implements guestfish -h cmd *)
7118 pr "void display_command (const char *cmd)\n";
7121 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7122 let name2 = replace_char name '_' '-' in
7124 try find_map (function FishAlias n -> Some n | _ -> None) flags
7125 with Not_found -> name in
7126 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7128 match snd style with
7132 name2 (String.concat " " (List.map name_of_argt args)) in
7135 if List.mem ProtocolLimitWarning flags then
7136 ("\n\n" ^ protocol_limit_warning)
7139 (* For DangerWillRobinson commands, we should probably have
7140 * guestfish prompt before allowing you to use them (especially
7141 * in interactive mode). XXX
7145 if List.mem DangerWillRobinson flags then
7146 ("\n\n" ^ danger_will_robinson)
7151 match deprecation_notice flags with
7153 | Some txt -> "\n\n" ^ txt in
7155 let describe_alias =
7156 if name <> alias then
7157 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7161 pr "STRCASEEQ (cmd, \"%s\")" name;
7162 if name <> name2 then
7163 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7164 if name <> alias then
7165 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7167 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7169 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7170 "=head1 DESCRIPTION\n\n" ^
7171 longdesc ^ warnings ^ describe_alias);
7174 pr " display_builtin_command (cmd);\n";
7178 let emit_print_list_function typ =
7179 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7182 pr " unsigned int i;\n";
7184 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7185 pr " printf (\"[%%d] = {\\n\", i);\n";
7186 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7187 pr " printf (\"}\\n\");\n";
7193 (* print_* functions *)
7197 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7199 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7202 pr " unsigned int i;\n";
7208 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7210 pr " printf (\"%%s%s: \", indent);\n" name;
7211 pr " for (i = 0; i < 32; ++i)\n";
7212 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7213 pr " printf (\"\\n\");\n"
7215 pr " printf (\"%%s%s: \", indent);\n" name;
7216 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7217 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7218 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7220 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7221 pr " printf (\"\\n\");\n"
7222 | name, (FUInt64|FBytes) ->
7223 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7226 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7229 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7232 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7235 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7237 | name, FOptPercent ->
7238 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7239 typ name name typ name;
7240 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7246 (* Emit a print_TYPE_list function definition only if that function is used. *)
7249 | typ, (RStructListOnly | RStructAndList) ->
7250 (* generate the function for typ *)
7251 emit_print_list_function typ
7252 | typ, _ -> () (* empty *)
7253 ) (rstructs_used_by all_functions);
7255 (* Emit a print_TYPE function definition only if that function is used. *)
7258 | typ, (RStructOnly | RStructAndList) ->
7259 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7261 pr " print_%s_indent (%s, \"\");\n" typ typ;
7264 | typ, _ -> () (* empty *)
7265 ) (rstructs_used_by all_functions);
7267 (* run_<action> actions *)
7269 fun (name, style, _, flags, _, _, _) ->
7270 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7272 (match fst style with
7275 | RBool _ -> pr " int r;\n"
7276 | RInt64 _ -> pr " int64_t r;\n"
7277 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7278 | RString _ -> pr " char *r;\n"
7279 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7280 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7281 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7284 pr " size_t size;\n";
7292 | FileOut n -> pr " const char *%s;\n" n
7294 | Dev_or_Path n -> pr " char *%s;\n" n
7295 | StringList n | DeviceList n -> pr " char **%s;\n" n
7296 | Bool n -> pr " int %s;\n" n
7297 | Int n -> pr " int %s;\n" n
7298 | Int64 n -> pr " int64_t %s;\n" n
7301 (* Check and convert parameters. *)
7302 let argc_expected = List.length (snd style) in
7303 pr " if (argc != %d) {\n" argc_expected;
7304 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7306 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7310 let parse_integer fn fntyp rtyp range name i =
7312 pr " strtol_error xerr;\n";
7313 pr " %s r;\n" fntyp;
7315 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7316 pr " if (xerr != LONGINT_OK) {\n";
7317 pr " fprintf (stderr,\n";
7318 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7319 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7324 | Some (min, max, comment) ->
7325 pr " /* %s */\n" comment;
7326 pr " if (r < %s || r > %s) {\n" min max;
7327 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7331 pr " /* The check above should ensure this assignment does not overflow. */\n";
7333 pr " %s = r;\n" name;
7342 pr " %s = argv[%d];\n" name i
7344 | Dev_or_Path name ->
7345 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7346 pr " if (%s == NULL) return -1;\n" name
7348 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7351 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7354 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7356 | StringList name | DeviceList name ->
7357 pr " %s = parse_string_list (argv[%d]);\n" name i;
7358 pr " if (%s == NULL) return -1;\n" name;
7360 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7363 let min = "(-(2LL<<30))"
7364 and max = "((2LL<<30)-1)"
7366 "The Int type in the generator is a signed 31 bit int." in
7367 Some (min, max, comment) in
7368 parse_integer "xstrtoll" "long long" "int" range name i
7370 parse_integer "xstrtoll" "long long" "int64_t" None name i
7373 (* Call C API function. *)
7375 try find_map (function FishAction n -> Some n | _ -> None) flags
7376 with Not_found -> sprintf "guestfs_%s" name in
7378 generate_c_call_args ~handle:"g" style;
7383 | Device name | String name
7384 | OptString name | FileIn name | FileOut name | Bool name
7385 | Int name | Int64 name -> ()
7386 | Pathname name | Dev_or_Path name ->
7387 pr " free (%s);\n" name
7388 | StringList name | DeviceList name ->
7389 pr " free_strings (%s);\n" name
7392 (* Check return value for errors and display command results. *)
7393 (match fst style with
7394 | RErr -> pr " return r;\n"
7396 pr " if (r == -1) return -1;\n";
7397 pr " printf (\"%%d\\n\", r);\n";
7400 pr " if (r == -1) return -1;\n";
7401 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7404 pr " if (r == -1) return -1;\n";
7405 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7408 pr " if (r == NULL) return -1;\n";
7409 pr " printf (\"%%s\\n\", r);\n";
7411 | RConstOptString _ ->
7412 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7415 pr " if (r == NULL) return -1;\n";
7416 pr " printf (\"%%s\\n\", r);\n";
7420 pr " if (r == NULL) return -1;\n";
7421 pr " print_strings (r);\n";
7422 pr " free_strings (r);\n";
7424 | RStruct (_, typ) ->
7425 pr " if (r == NULL) return -1;\n";
7426 pr " print_%s (r);\n" typ;
7427 pr " guestfs_free_%s (r);\n" typ;
7429 | RStructList (_, typ) ->
7430 pr " if (r == NULL) return -1;\n";
7431 pr " print_%s_list (r);\n" typ;
7432 pr " guestfs_free_%s_list (r);\n" typ;
7435 pr " if (r == NULL) return -1;\n";
7436 pr " print_table (r);\n";
7437 pr " free_strings (r);\n";
7440 pr " if (r == NULL) return -1;\n";
7441 pr " if (full_write (1, r, size) != size) {\n";
7442 pr " perror (\"write\");\n";
7453 (* run_action function *)
7454 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7457 fun (name, _, _, flags, _, _, _) ->
7458 let name2 = replace_char name '_' '-' in
7460 try find_map (function FishAlias n -> Some n | _ -> None) flags
7461 with Not_found -> name in
7463 pr "STRCASEEQ (cmd, \"%s\")" name;
7464 if name <> name2 then
7465 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7466 if name <> alias then
7467 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7469 pr " return run_%s (cmd, argc, argv);\n" name;
7473 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7474 pr " if (command_num == 1)\n";
7475 pr " extended_help_message ();\n";
7482 (* Readline completion for guestfish. *)
7483 and generate_fish_completion () =
7484 generate_header CStyle GPLv2plus;
7488 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7498 #ifdef HAVE_LIBREADLINE
7499 #include <readline/readline.h>
7504 #ifdef HAVE_LIBREADLINE
7506 static const char *const commands[] = {
7507 BUILTIN_COMMANDS_FOR_COMPLETION,
7510 (* Get the commands, including the aliases. They don't need to be
7511 * sorted - the generator() function just does a dumb linear search.
7515 fun (name, _, _, flags, _, _, _) ->
7516 let name2 = replace_char name '_' '-' in
7518 try find_map (function FishAlias n -> Some n | _ -> None) flags
7519 with Not_found -> name in
7521 if name <> alias then [name2; alias] else [name2]
7523 let commands = List.flatten commands in
7525 List.iter (pr " \"%s\",\n") commands;
7531 generator (const char *text, int state)
7533 static int index, len;
7538 len = strlen (text);
7541 rl_attempted_completion_over = 1;
7543 while ((name = commands[index]) != NULL) {
7545 if (STRCASEEQLEN (name, text, len))
7546 return strdup (name);
7552 #endif /* HAVE_LIBREADLINE */
7554 #ifdef HAVE_RL_COMPLETION_MATCHES
7555 #define RL_COMPLETION_MATCHES rl_completion_matches
7557 #ifdef HAVE_COMPLETION_MATCHES
7558 #define RL_COMPLETION_MATCHES completion_matches
7560 #endif /* else just fail if we don't have either symbol */
7563 do_completion (const char *text, int start, int end)
7565 char **matches = NULL;
7567 #ifdef HAVE_LIBREADLINE
7568 rl_completion_append_character = ' ';
7571 matches = RL_COMPLETION_MATCHES (text, generator);
7572 else if (complete_dest_paths)
7573 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7580 (* Generate the POD documentation for guestfish. *)
7581 and generate_fish_actions_pod () =
7582 let all_functions_sorted =
7584 fun (_, _, _, flags, _, _, _) ->
7585 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7586 ) all_functions_sorted in
7588 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7591 fun (name, style, _, flags, _, _, longdesc) ->
7593 Str.global_substitute rex (
7596 try Str.matched_group 1 s
7598 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7599 "C<" ^ replace_char sub '_' '-' ^ ">"
7601 let name = replace_char name '_' '-' in
7603 try find_map (function FishAlias n -> Some n | _ -> None) flags
7604 with Not_found -> name in
7606 pr "=head2 %s" name;
7607 if name <> alias then
7614 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7615 | OptString n -> pr " %s" n
7616 | StringList n | DeviceList n -> pr " '%s ...'" n
7617 | Bool _ -> pr " true|false"
7618 | Int n -> pr " %s" n
7619 | Int64 n -> pr " %s" n
7620 | FileIn n | FileOut n -> pr " (%s|-)" n
7624 pr "%s\n\n" longdesc;
7626 if List.exists (function FileIn _ | FileOut _ -> true
7627 | _ -> false) (snd style) then
7628 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7630 if List.mem ProtocolLimitWarning flags then
7631 pr "%s\n\n" protocol_limit_warning;
7633 if List.mem DangerWillRobinson flags then
7634 pr "%s\n\n" danger_will_robinson;
7636 match deprecation_notice flags with
7638 | Some txt -> pr "%s\n\n" txt
7639 ) all_functions_sorted
7641 (* Generate a C function prototype. *)
7642 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7643 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7645 ?handle name style =
7646 if extern then pr "extern ";
7647 if static then pr "static ";
7648 (match fst style with
7650 | RInt _ -> pr "int "
7651 | RInt64 _ -> pr "int64_t "
7652 | RBool _ -> pr "int "
7653 | RConstString _ | RConstOptString _ -> pr "const char *"
7654 | RString _ | RBufferOut _ -> pr "char *"
7655 | RStringList _ | RHashtable _ -> pr "char **"
7656 | RStruct (_, typ) ->
7657 if not in_daemon then pr "struct guestfs_%s *" typ
7658 else pr "guestfs_int_%s *" typ
7659 | RStructList (_, typ) ->
7660 if not in_daemon then pr "struct guestfs_%s_list *" typ
7661 else pr "guestfs_int_%s_list *" typ
7663 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7664 pr "%s%s (" prefix name;
7665 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7668 let comma = ref false in
7671 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7675 if single_line then pr ", " else pr ",\n\t\t"
7682 | Device n | Dev_or_Path n
7686 pr "const char *%s" n
7687 | StringList n | DeviceList n ->
7689 pr "char *const *%s" n
7690 | Bool n -> next (); pr "int %s" n
7691 | Int n -> next (); pr "int %s" n
7692 | Int64 n -> next (); pr "int64_t %s" n
7695 if not in_daemon then (next (); pr "const char *%s" n)
7697 if is_RBufferOut then (next (); pr "size_t *size_r");
7700 if semicolon then pr ";";
7701 if newline then pr "\n"
7703 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7704 and generate_c_call_args ?handle ?(decl = false) style =
7706 let comma = ref false in
7708 if !comma then pr ", ";
7713 | Some handle -> pr "%s" handle; comma := true
7718 pr "%s" (name_of_argt arg)
7720 (* For RBufferOut calls, add implicit &size parameter. *)
7722 match fst style with
7730 (* Generate the OCaml bindings interface. *)
7731 and generate_ocaml_mli () =
7732 generate_header OCamlStyle LGPLv2plus;
7735 (** For API documentation you should refer to the C API
7736 in the guestfs(3) manual page. The OCaml API uses almost
7737 exactly the same calls. *)
7740 (** A [guestfs_h] handle. *)
7742 exception Error of string
7743 (** This exception is raised when there is an error. *)
7745 exception Handle_closed of string
7746 (** This exception is raised if you use a {!Guestfs.t} handle
7747 after calling {!close} on it. The string is the name of
7750 val create : unit -> t
7751 (** Create a {!Guestfs.t} handle. *)
7753 val close : t -> unit
7754 (** Close the {!Guestfs.t} handle and free up all resources used
7757 Handles are closed by the garbage collector when they become
7758 unreferenced, but callers can call this in order to provide
7759 predictable cleanup. *)
7762 generate_ocaml_structure_decls ();
7766 fun (name, style, _, _, _, shortdesc, _) ->
7767 generate_ocaml_prototype name style;
7768 pr "(** %s *)\n" shortdesc;
7770 ) all_functions_sorted
7772 (* Generate the OCaml bindings implementation. *)
7773 and generate_ocaml_ml () =
7774 generate_header OCamlStyle LGPLv2plus;
7779 exception Error of string
7780 exception Handle_closed of string
7782 external create : unit -> t = \"ocaml_guestfs_create\"
7783 external close : t -> unit = \"ocaml_guestfs_close\"
7785 (* Give the exceptions names, so they can be raised from the C code. *)
7787 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7788 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7792 generate_ocaml_structure_decls ();
7796 fun (name, style, _, _, _, shortdesc, _) ->
7797 generate_ocaml_prototype ~is_external:true name style;
7798 ) all_functions_sorted
7800 (* Generate the OCaml bindings C implementation. *)
7801 and generate_ocaml_c () =
7802 generate_header CStyle LGPLv2plus;
7809 #include <caml/config.h>
7810 #include <caml/alloc.h>
7811 #include <caml/callback.h>
7812 #include <caml/fail.h>
7813 #include <caml/memory.h>
7814 #include <caml/mlvalues.h>
7815 #include <caml/signals.h>
7817 #include <guestfs.h>
7819 #include \"guestfs_c.h\"
7821 /* Copy a hashtable of string pairs into an assoc-list. We return
7822 * the list in reverse order, but hashtables aren't supposed to be
7825 static CAMLprim value
7826 copy_table (char * const * argv)
7829 CAMLlocal5 (rv, pairv, kv, vv, cons);
7833 for (i = 0; argv[i] != NULL; i += 2) {
7834 kv = caml_copy_string (argv[i]);
7835 vv = caml_copy_string (argv[i+1]);
7836 pairv = caml_alloc (2, 0);
7837 Store_field (pairv, 0, kv);
7838 Store_field (pairv, 1, vv);
7839 cons = caml_alloc (2, 0);
7840 Store_field (cons, 1, rv);
7842 Store_field (cons, 0, pairv);
7850 (* Struct copy functions. *)
7852 let emit_ocaml_copy_list_function typ =
7853 pr "static CAMLprim value\n";
7854 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7856 pr " CAMLparam0 ();\n";
7857 pr " CAMLlocal2 (rv, v);\n";
7858 pr " unsigned int i;\n";
7860 pr " if (%ss->len == 0)\n" typ;
7861 pr " CAMLreturn (Atom (0));\n";
7863 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7864 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7865 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7866 pr " caml_modify (&Field (rv, i), v);\n";
7868 pr " CAMLreturn (rv);\n";
7876 let has_optpercent_col =
7877 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7879 pr "static CAMLprim value\n";
7880 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7882 pr " CAMLparam0 ();\n";
7883 if has_optpercent_col then
7884 pr " CAMLlocal3 (rv, v, v2);\n"
7886 pr " CAMLlocal2 (rv, v);\n";
7888 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7893 pr " v = caml_copy_string (%s->%s);\n" typ name
7895 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7896 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7899 pr " v = caml_alloc_string (32);\n";
7900 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7901 | name, (FBytes|FInt64|FUInt64) ->
7902 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7903 | name, (FInt32|FUInt32) ->
7904 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7905 | name, FOptPercent ->
7906 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7907 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7908 pr " v = caml_alloc (1, 0);\n";
7909 pr " Store_field (v, 0, v2);\n";
7910 pr " } else /* None */\n";
7911 pr " v = Val_int (0);\n";
7913 pr " v = Val_int (%s->%s);\n" typ name
7915 pr " Store_field (rv, %d, v);\n" i
7917 pr " CAMLreturn (rv);\n";
7922 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7925 | typ, (RStructListOnly | RStructAndList) ->
7926 (* generate the function for typ *)
7927 emit_ocaml_copy_list_function typ
7928 | typ, _ -> () (* empty *)
7929 ) (rstructs_used_by all_functions);
7933 fun (name, style, _, _, _, _, _) ->
7934 pr "/* Automatically generated wrapper for function\n";
7936 generate_ocaml_prototype name style;
7941 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7943 let needs_extra_vs =
7944 match fst style with RConstOptString _ -> true | _ -> false in
7946 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7947 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7948 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7951 pr "CAMLprim value\n";
7952 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7953 List.iter (pr ", value %s") (List.tl params);
7958 | [p1; p2; p3; p4; p5] ->
7959 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7960 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7961 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7962 pr " CAMLxparam%d (%s);\n"
7963 (List.length rest) (String.concat ", " rest)
7965 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7967 if not needs_extra_vs then
7968 pr " CAMLlocal1 (rv);\n"
7970 pr " CAMLlocal3 (rv, v, v2);\n";
7973 pr " guestfs_h *g = Guestfs_val (gv);\n";
7974 pr " if (g == NULL)\n";
7975 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
7981 | Device n | Dev_or_Path n
7985 pr " const char *%s = String_val (%sv);\n" n n
7987 pr " const char *%s =\n" n;
7988 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7990 | StringList n | DeviceList n ->
7991 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7993 pr " int %s = Bool_val (%sv);\n" n n
7995 pr " int %s = Int_val (%sv);\n" n n
7997 pr " int64_t %s = Int64_val (%sv);\n" n n
8000 match fst style with
8001 | RErr -> pr " int r;\n"; "-1"
8002 | RInt _ -> pr " int r;\n"; "-1"
8003 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8004 | RBool _ -> pr " int r;\n"; "-1"
8005 | RConstString _ | RConstOptString _ ->
8006 pr " const char *r;\n"; "NULL"
8007 | RString _ -> pr " char *r;\n"; "NULL"
8012 | RStruct (_, typ) ->
8013 pr " struct guestfs_%s *r;\n" typ; "NULL"
8014 | RStructList (_, typ) ->
8015 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8022 pr " size_t size;\n";
8026 pr " caml_enter_blocking_section ();\n";
8027 pr " r = guestfs_%s " name;
8028 generate_c_call_args ~handle:"g" style;
8030 pr " caml_leave_blocking_section ();\n";
8034 | StringList n | DeviceList n ->
8035 pr " ocaml_guestfs_free_strings (%s);\n" n;
8036 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8037 | Bool _ | Int _ | Int64 _
8038 | FileIn _ | FileOut _ -> ()
8041 pr " if (r == %s)\n" error_code;
8042 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8045 (match fst style with
8046 | RErr -> pr " rv = Val_unit;\n"
8047 | RInt _ -> pr " rv = Val_int (r);\n"
8049 pr " rv = caml_copy_int64 (r);\n"
8050 | RBool _ -> pr " rv = Val_bool (r);\n"
8052 pr " rv = caml_copy_string (r);\n"
8053 | RConstOptString _ ->
8054 pr " if (r) { /* Some string */\n";
8055 pr " v = caml_alloc (1, 0);\n";
8056 pr " v2 = caml_copy_string (r);\n";
8057 pr " Store_field (v, 0, v2);\n";
8058 pr " } else /* None */\n";
8059 pr " v = Val_int (0);\n";
8061 pr " rv = caml_copy_string (r);\n";
8064 pr " rv = caml_copy_string_array ((const char **) r);\n";
8065 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8067 | RStruct (_, typ) ->
8068 pr " rv = copy_%s (r);\n" typ;
8069 pr " guestfs_free_%s (r);\n" typ;
8070 | RStructList (_, typ) ->
8071 pr " rv = copy_%s_list (r);\n" typ;
8072 pr " guestfs_free_%s_list (r);\n" typ;
8074 pr " rv = copy_table (r);\n";
8075 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8078 pr " rv = caml_alloc_string (size);\n";
8079 pr " memcpy (String_val (rv), r, size);\n";
8082 pr " CAMLreturn (rv);\n";
8086 if List.length params > 5 then (
8087 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8088 pr "CAMLprim value ";
8089 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8090 pr "CAMLprim value\n";
8091 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8093 pr " return ocaml_guestfs_%s (argv[0]" name;
8094 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8099 ) all_functions_sorted
8101 and generate_ocaml_structure_decls () =
8104 pr "type %s = {\n" typ;
8107 | name, FString -> pr " %s : string;\n" name
8108 | name, FBuffer -> pr " %s : string;\n" name
8109 | name, FUUID -> pr " %s : string;\n" name
8110 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8111 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8112 | name, FChar -> pr " %s : char;\n" name
8113 | name, FOptPercent -> pr " %s : float option;\n" name
8119 and generate_ocaml_prototype ?(is_external = false) name style =
8120 if is_external then pr "external " else pr "val ";
8121 pr "%s : t -> " name;
8124 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8125 | OptString _ -> pr "string option -> "
8126 | StringList _ | DeviceList _ -> pr "string array -> "
8127 | Bool _ -> pr "bool -> "
8128 | Int _ -> pr "int -> "
8129 | Int64 _ -> pr "int64 -> "
8131 (match fst style with
8132 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8133 | RInt _ -> pr "int"
8134 | RInt64 _ -> pr "int64"
8135 | RBool _ -> pr "bool"
8136 | RConstString _ -> pr "string"
8137 | RConstOptString _ -> pr "string option"
8138 | RString _ | RBufferOut _ -> pr "string"
8139 | RStringList _ -> pr "string array"
8140 | RStruct (_, typ) -> pr "%s" typ
8141 | RStructList (_, typ) -> pr "%s array" typ
8142 | RHashtable _ -> pr "(string * string) list"
8144 if is_external then (
8146 if List.length (snd style) + 1 > 5 then
8147 pr "\"ocaml_guestfs_%s_byte\" " name;
8148 pr "\"ocaml_guestfs_%s\"" name
8152 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8153 and generate_perl_xs () =
8154 generate_header CStyle LGPLv2plus;
8157 #include \"EXTERN.h\"
8161 #include <guestfs.h>
8164 #define PRId64 \"lld\"
8168 my_newSVll(long long val) {
8169 #ifdef USE_64_BIT_ALL
8170 return newSViv(val);
8174 len = snprintf(buf, 100, \"%%\" PRId64, val);
8175 return newSVpv(buf, len);
8180 #define PRIu64 \"llu\"
8184 my_newSVull(unsigned long long val) {
8185 #ifdef USE_64_BIT_ALL
8186 return newSVuv(val);
8190 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8191 return newSVpv(buf, len);
8195 /* http://www.perlmonks.org/?node_id=680842 */
8197 XS_unpack_charPtrPtr (SV *arg) {
8202 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8203 croak (\"array reference expected\");
8205 av = (AV *)SvRV (arg);
8206 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8208 croak (\"malloc failed\");
8210 for (i = 0; i <= av_len (av); i++) {
8211 SV **elem = av_fetch (av, i, 0);
8213 if (!elem || !*elem)
8214 croak (\"missing element in list\");
8216 ret[i] = SvPV_nolen (*elem);
8224 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8231 RETVAL = guestfs_create ();
8233 croak (\"could not create guestfs handle\");
8234 guestfs_set_error_handler (RETVAL, NULL, NULL);
8247 fun (name, style, _, _, _, _, _) ->
8248 (match fst style with
8249 | RErr -> pr "void\n"
8250 | RInt _ -> pr "SV *\n"
8251 | RInt64 _ -> pr "SV *\n"
8252 | RBool _ -> pr "SV *\n"
8253 | RConstString _ -> pr "SV *\n"
8254 | RConstOptString _ -> pr "SV *\n"
8255 | RString _ -> pr "SV *\n"
8256 | RBufferOut _ -> pr "SV *\n"
8258 | RStruct _ | RStructList _
8260 pr "void\n" (* all lists returned implictly on the stack *)
8262 (* Call and arguments. *)
8264 generate_c_call_args ~handle:"g" ~decl:true style;
8266 pr " guestfs_h *g;\n";
8270 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8273 (* http://www.perlmonks.org/?node_id=554277
8274 * Note that the implicit handle argument means we have
8275 * to add 1 to the ST(x) operator.
8277 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8278 | StringList n | DeviceList n -> pr " char **%s;\n" n
8279 | Bool n -> pr " int %s;\n" n
8280 | Int n -> pr " int %s;\n" n
8281 | Int64 n -> pr " int64_t %s;\n" n
8284 let do_cleanups () =
8287 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8288 | Bool _ | Int _ | Int64 _
8289 | FileIn _ | FileOut _ -> ()
8290 | StringList n | DeviceList n -> pr " free (%s);\n" n
8295 (match fst style with
8300 pr " r = guestfs_%s " name;
8301 generate_c_call_args ~handle:"g" style;
8304 pr " if (r == -1)\n";
8305 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8311 pr " %s = guestfs_%s " n name;
8312 generate_c_call_args ~handle:"g" style;
8315 pr " if (%s == -1)\n" n;
8316 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8317 pr " RETVAL = newSViv (%s);\n" n;
8322 pr " int64_t %s;\n" n;
8324 pr " %s = guestfs_%s " n name;
8325 generate_c_call_args ~handle:"g" style;
8328 pr " if (%s == -1)\n" n;
8329 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8330 pr " RETVAL = my_newSVll (%s);\n" n;
8335 pr " const char *%s;\n" n;
8337 pr " %s = guestfs_%s " n name;
8338 generate_c_call_args ~handle:"g" style;
8341 pr " if (%s == NULL)\n" n;
8342 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8343 pr " RETVAL = newSVpv (%s, 0);\n" n;
8346 | RConstOptString n ->
8348 pr " const char *%s;\n" n;
8350 pr " %s = guestfs_%s " n name;
8351 generate_c_call_args ~handle:"g" style;
8354 pr " if (%s == NULL)\n" n;
8355 pr " RETVAL = &PL_sv_undef;\n";
8357 pr " RETVAL = newSVpv (%s, 0);\n" n;
8362 pr " char *%s;\n" n;
8364 pr " %s = guestfs_%s " n name;
8365 generate_c_call_args ~handle:"g" style;
8368 pr " if (%s == NULL)\n" n;
8369 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8370 pr " RETVAL = newSVpv (%s, 0);\n" n;
8371 pr " free (%s);\n" n;
8374 | RStringList n | RHashtable n ->
8376 pr " char **%s;\n" n;
8379 pr " %s = guestfs_%s " n name;
8380 generate_c_call_args ~handle:"g" style;
8383 pr " if (%s == NULL)\n" n;
8384 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8385 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8386 pr " EXTEND (SP, n);\n";
8387 pr " for (i = 0; i < n; ++i) {\n";
8388 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8389 pr " free (%s[i]);\n" n;
8391 pr " free (%s);\n" n;
8392 | RStruct (n, typ) ->
8393 let cols = cols_of_struct typ in
8394 generate_perl_struct_code typ cols name style n do_cleanups
8395 | RStructList (n, typ) ->
8396 let cols = cols_of_struct typ in
8397 generate_perl_struct_list_code typ cols name style n do_cleanups
8400 pr " char *%s;\n" n;
8401 pr " size_t size;\n";
8403 pr " %s = guestfs_%s " n name;
8404 generate_c_call_args ~handle:"g" style;
8407 pr " if (%s == NULL)\n" n;
8408 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8409 pr " RETVAL = newSVpvn (%s, size);\n" n;
8410 pr " free (%s);\n" n;
8418 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8420 pr " struct guestfs_%s_list *%s;\n" typ n;
8424 pr " %s = guestfs_%s " n name;
8425 generate_c_call_args ~handle:"g" style;
8428 pr " if (%s == NULL)\n" n;
8429 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8430 pr " EXTEND (SP, %s->len);\n" n;
8431 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8432 pr " hv = newHV ();\n";
8436 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8437 name (String.length name) n name
8439 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8440 name (String.length name) n name
8442 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8443 name (String.length name) n name n name
8444 | name, (FBytes|FUInt64) ->
8445 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8446 name (String.length name) n name
8448 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8449 name (String.length name) n name
8450 | name, (FInt32|FUInt32) ->
8451 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8452 name (String.length name) n name
8454 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8455 name (String.length name) n name
8456 | name, FOptPercent ->
8457 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8458 name (String.length name) n name
8460 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8462 pr " guestfs_free_%s_list (%s);\n" typ n
8464 and generate_perl_struct_code typ cols name style n do_cleanups =
8466 pr " struct guestfs_%s *%s;\n" typ n;
8468 pr " %s = guestfs_%s " n name;
8469 generate_c_call_args ~handle:"g" style;
8472 pr " if (%s == NULL)\n" n;
8473 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8474 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8476 fun ((name, _) as col) ->
8477 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8481 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8484 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8487 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8489 | name, (FBytes|FUInt64) ->
8490 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8493 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8495 | name, (FInt32|FUInt32) ->
8496 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8499 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8501 | name, FOptPercent ->
8502 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8505 pr " free (%s);\n" n
8507 (* Generate Sys/Guestfs.pm. *)
8508 and generate_perl_pm () =
8509 generate_header HashStyle LGPLv2plus;
8516 Sys::Guestfs - Perl bindings for libguestfs
8522 my $h = Sys::Guestfs->new ();
8523 $h->add_drive ('guest.img');
8525 $h->mount ('/dev/sda1', '/');
8526 $h->touch ('/hello');
8531 The C<Sys::Guestfs> module provides a Perl XS binding to the
8532 libguestfs API for examining and modifying virtual machine
8535 Amongst the things this is good for: making batch configuration
8536 changes to guests, getting disk used/free statistics (see also:
8537 virt-df), migrating between virtualization systems (see also:
8538 virt-p2v), performing partial backups, performing partial guest
8539 clones, cloning guests and changing registry/UUID/hostname info, and
8542 Libguestfs uses Linux kernel and qemu code, and can access any type of
8543 guest filesystem that Linux and qemu can, including but not limited
8544 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8545 schemes, qcow, qcow2, vmdk.
8547 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8548 LVs, what filesystem is in each LV, etc.). It can also run commands
8549 in the context of the guest. Also you can access filesystems over
8552 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8553 functions for using libguestfs from Perl, including integration
8558 All errors turn into calls to C<croak> (see L<Carp(3)>).
8566 package Sys::Guestfs;
8572 XSLoader::load ('Sys::Guestfs');
8574 =item $h = Sys::Guestfs->new ();
8576 Create a new guestfs handle.
8582 my $class = ref ($proto) || $proto;
8584 my $self = Sys::Guestfs::_create ();
8585 bless $self, $class;
8591 (* Actions. We only need to print documentation for these as
8592 * they are pulled in from the XS code automatically.
8595 fun (name, style, _, flags, _, _, longdesc) ->
8596 if not (List.mem NotInDocs flags) then (
8597 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8599 generate_perl_prototype name style;
8601 pr "%s\n\n" longdesc;
8602 if List.mem ProtocolLimitWarning flags then
8603 pr "%s\n\n" protocol_limit_warning;
8604 if List.mem DangerWillRobinson flags then
8605 pr "%s\n\n" danger_will_robinson;
8606 match deprecation_notice flags with
8608 | Some txt -> pr "%s\n\n" txt
8610 ) all_functions_sorted;
8622 Copyright (C) %s Red Hat Inc.
8626 Please see the file COPYING.LIB for the full license.
8632 L<http://libguestfs.org>,
8633 L<Sys::Guestfs::Lib(3)>.
8638 and generate_perl_prototype name style =
8639 (match fst style with
8647 | RBufferOut n -> pr "$%s = " n
8649 | RHashtable n -> pr "%%%s = " n
8651 | RStructList (n,_) -> pr "@%s = " n
8654 let comma = ref false in
8657 if !comma then pr ", ";
8660 | Pathname n | Device n | Dev_or_Path n | String n
8661 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8663 | StringList n | DeviceList n ->
8668 (* Generate Python C module. *)
8669 and generate_python_c () =
8670 generate_header CStyle LGPLv2plus;
8679 #include \"guestfs.h\"
8687 get_handle (PyObject *obj)
8690 assert (obj != Py_None);
8691 return ((Pyguestfs_Object *) obj)->g;
8695 put_handle (guestfs_h *g)
8699 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8702 /* This list should be freed (but not the strings) after use. */
8704 get_string_list (PyObject *obj)
8711 if (!PyList_Check (obj)) {
8712 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8716 len = PyList_Size (obj);
8717 r = malloc (sizeof (char *) * (len+1));
8719 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8723 for (i = 0; i < len; ++i)
8724 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8731 put_string_list (char * const * const argv)
8736 for (argc = 0; argv[argc] != NULL; ++argc)
8739 list = PyList_New (argc);
8740 for (i = 0; i < argc; ++i)
8741 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8747 put_table (char * const * const argv)
8749 PyObject *list, *item;
8752 for (argc = 0; argv[argc] != NULL; ++argc)
8755 list = PyList_New (argc >> 1);
8756 for (i = 0; i < argc; i += 2) {
8757 item = PyTuple_New (2);
8758 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8759 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8760 PyList_SetItem (list, i >> 1, item);
8767 free_strings (char **argv)
8771 for (argc = 0; argv[argc] != NULL; ++argc)
8777 py_guestfs_create (PyObject *self, PyObject *args)
8781 g = guestfs_create ();
8783 PyErr_SetString (PyExc_RuntimeError,
8784 \"guestfs.create: failed to allocate handle\");
8787 guestfs_set_error_handler (g, NULL, NULL);
8788 return put_handle (g);
8792 py_guestfs_close (PyObject *self, PyObject *args)
8797 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8799 g = get_handle (py_g);
8803 Py_INCREF (Py_None);
8809 let emit_put_list_function typ =
8810 pr "static PyObject *\n";
8811 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8813 pr " PyObject *list;\n";
8816 pr " list = PyList_New (%ss->len);\n" typ;
8817 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8818 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8819 pr " return list;\n";
8824 (* Structures, turned into Python dictionaries. *)
8827 pr "static PyObject *\n";
8828 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8830 pr " PyObject *dict;\n";
8832 pr " dict = PyDict_New ();\n";
8836 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8837 pr " PyString_FromString (%s->%s));\n"
8840 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8841 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8844 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8845 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8847 | name, (FBytes|FUInt64) ->
8848 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8849 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8852 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8853 pr " PyLong_FromLongLong (%s->%s));\n"
8856 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8857 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8860 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8861 pr " PyLong_FromLong (%s->%s));\n"
8863 | name, FOptPercent ->
8864 pr " if (%s->%s >= 0)\n" typ name;
8865 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8866 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8869 pr " Py_INCREF (Py_None);\n";
8870 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8873 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8874 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8876 pr " return dict;\n";
8882 (* Emit a put_TYPE_list function definition only if that function is used. *)
8885 | typ, (RStructListOnly | RStructAndList) ->
8886 (* generate the function for typ *)
8887 emit_put_list_function typ
8888 | typ, _ -> () (* empty *)
8889 ) (rstructs_used_by all_functions);
8891 (* Python wrapper functions. *)
8893 fun (name, style, _, _, _, _, _) ->
8894 pr "static PyObject *\n";
8895 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8898 pr " PyObject *py_g;\n";
8899 pr " guestfs_h *g;\n";
8900 pr " PyObject *py_r;\n";
8903 match fst style with
8904 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8905 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8906 | RConstString _ | RConstOptString _ ->
8907 pr " const char *r;\n"; "NULL"
8908 | RString _ -> pr " char *r;\n"; "NULL"
8909 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8910 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8911 | RStructList (_, typ) ->
8912 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8915 pr " size_t size;\n";
8920 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8921 pr " const char *%s;\n" n
8922 | OptString n -> pr " const char *%s;\n" n
8923 | StringList n | DeviceList n ->
8924 pr " PyObject *py_%s;\n" n;
8925 pr " char **%s;\n" n
8926 | Bool n -> pr " int %s;\n" n
8927 | Int n -> pr " int %s;\n" n
8928 | Int64 n -> pr " long long %s;\n" n
8933 (* Convert the parameters. *)
8934 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8937 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8938 | OptString _ -> pr "z"
8939 | StringList _ | DeviceList _ -> pr "O"
8940 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8942 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8943 * emulate C's int/long/long long in Python?
8946 pr ":guestfs_%s\",\n" name;
8950 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8951 | OptString n -> pr ", &%s" n
8952 | StringList n | DeviceList n -> pr ", &py_%s" n
8953 | Bool n -> pr ", &%s" n
8954 | Int n -> pr ", &%s" n
8955 | Int64 n -> pr ", &%s" n
8959 pr " return NULL;\n";
8961 pr " g = get_handle (py_g);\n";
8964 | Pathname _ | Device _ | Dev_or_Path _ | String _
8965 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8966 | StringList n | DeviceList n ->
8967 pr " %s = get_string_list (py_%s);\n" n n;
8968 pr " if (!%s) return NULL;\n" n
8973 pr " r = guestfs_%s " name;
8974 generate_c_call_args ~handle:"g" style;
8979 | Pathname _ | Device _ | Dev_or_Path _ | String _
8980 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8981 | StringList n | DeviceList n ->
8982 pr " free (%s);\n" n
8985 pr " if (r == %s) {\n" error_code;
8986 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8987 pr " return NULL;\n";
8991 (match fst style with
8993 pr " Py_INCREF (Py_None);\n";
8994 pr " py_r = Py_None;\n"
8996 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
8997 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
8998 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
8999 | RConstOptString _ ->
9001 pr " py_r = PyString_FromString (r);\n";
9003 pr " Py_INCREF (Py_None);\n";
9004 pr " py_r = Py_None;\n";
9007 pr " py_r = PyString_FromString (r);\n";
9010 pr " py_r = put_string_list (r);\n";
9011 pr " free_strings (r);\n"
9012 | RStruct (_, typ) ->
9013 pr " py_r = put_%s (r);\n" typ;
9014 pr " guestfs_free_%s (r);\n" typ
9015 | RStructList (_, typ) ->
9016 pr " py_r = put_%s_list (r);\n" typ;
9017 pr " guestfs_free_%s_list (r);\n" typ
9019 pr " py_r = put_table (r);\n";
9020 pr " free_strings (r);\n"
9022 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9026 pr " return py_r;\n";
9031 (* Table of functions. *)
9032 pr "static PyMethodDef methods[] = {\n";
9033 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9034 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9036 fun (name, _, _, _, _, _, _) ->
9037 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9040 pr " { NULL, NULL, 0, NULL }\n";
9044 (* Init function. *)
9047 initlibguestfsmod (void)
9049 static int initialized = 0;
9051 if (initialized) return;
9052 Py_InitModule ((char *) \"libguestfsmod\", methods);
9057 (* Generate Python module. *)
9058 and generate_python_py () =
9059 generate_header HashStyle LGPLv2plus;
9062 u\"\"\"Python bindings for libguestfs
9065 g = guestfs.GuestFS ()
9066 g.add_drive (\"guest.img\")
9068 parts = g.list_partitions ()
9070 The guestfs module provides a Python binding to the libguestfs API
9071 for examining and modifying virtual machine disk images.
9073 Amongst the things this is good for: making batch configuration
9074 changes to guests, getting disk used/free statistics (see also:
9075 virt-df), migrating between virtualization systems (see also:
9076 virt-p2v), performing partial backups, performing partial guest
9077 clones, cloning guests and changing registry/UUID/hostname info, and
9080 Libguestfs uses Linux kernel and qemu code, and can access any type of
9081 guest filesystem that Linux and qemu can, including but not limited
9082 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9083 schemes, qcow, qcow2, vmdk.
9085 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9086 LVs, what filesystem is in each LV, etc.). It can also run commands
9087 in the context of the guest. Also you can access filesystems over
9090 Errors which happen while using the API are turned into Python
9091 RuntimeError exceptions.
9093 To create a guestfs handle you usually have to perform the following
9096 # Create the handle, call add_drive at least once, and possibly
9097 # several times if the guest has multiple block devices:
9098 g = guestfs.GuestFS ()
9099 g.add_drive (\"guest.img\")
9101 # Launch the qemu subprocess and wait for it to become ready:
9104 # Now you can issue commands, for example:
9109 import libguestfsmod
9112 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9114 def __init__ (self):
9115 \"\"\"Create a new libguestfs handle.\"\"\"
9116 self._o = libguestfsmod.create ()
9119 libguestfsmod.close (self._o)
9124 fun (name, style, _, flags, _, _, longdesc) ->
9126 generate_py_call_args ~handle:"self" (snd style);
9129 if not (List.mem NotInDocs flags) then (
9130 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9132 match fst style with
9133 | RErr | RInt _ | RInt64 _ | RBool _
9134 | RConstOptString _ | RConstString _
9135 | RString _ | RBufferOut _ -> doc
9137 doc ^ "\n\nThis function returns a list of strings."
9138 | RStruct (_, typ) ->
9139 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9140 | RStructList (_, typ) ->
9141 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9143 doc ^ "\n\nThis function returns a dictionary." in
9145 if List.mem ProtocolLimitWarning flags then
9146 doc ^ "\n\n" ^ protocol_limit_warning
9149 if List.mem DangerWillRobinson flags then
9150 doc ^ "\n\n" ^ danger_will_robinson
9153 match deprecation_notice flags with
9155 | Some txt -> doc ^ "\n\n" ^ txt in
9156 let doc = pod2text ~width:60 name doc in
9157 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9158 let doc = String.concat "\n " doc in
9159 pr " u\"\"\"%s\"\"\"\n" doc;
9161 pr " return libguestfsmod.%s " name;
9162 generate_py_call_args ~handle:"self._o" (snd style);
9167 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9168 and generate_py_call_args ~handle args =
9170 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9173 (* Useful if you need the longdesc POD text as plain text. Returns a
9176 * Because this is very slow (the slowest part of autogeneration),
9177 * we memoize the results.
9179 and pod2text ~width name longdesc =
9180 let key = width, name, longdesc in
9181 try Hashtbl.find pod2text_memo key
9183 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9184 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9186 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9187 let chan = open_process_in cmd in
9188 let lines = ref [] in
9190 let line = input_line chan in
9191 if i = 1 then (* discard the first line of output *)
9194 let line = triml line in
9195 lines := line :: !lines;
9198 let lines = try loop 1 with End_of_file -> List.rev !lines in
9200 (match close_process_in chan with
9203 failwithf "pod2text: process exited with non-zero status (%d)" i
9204 | WSIGNALED i | WSTOPPED i ->
9205 failwithf "pod2text: process signalled or stopped by signal %d" i
9207 Hashtbl.add pod2text_memo key lines;
9208 pod2text_memo_updated ();
9211 (* Generate ruby bindings. *)
9212 and generate_ruby_c () =
9213 generate_header CStyle LGPLv2plus;
9221 #include \"guestfs.h\"
9223 #include \"extconf.h\"
9225 /* For Ruby < 1.9 */
9227 #define RARRAY_LEN(r) (RARRAY((r))->len)
9230 static VALUE m_guestfs; /* guestfs module */
9231 static VALUE c_guestfs; /* guestfs_h handle */
9232 static VALUE e_Error; /* used for all errors */
9234 static void ruby_guestfs_free (void *p)
9237 guestfs_close ((guestfs_h *) p);
9240 static VALUE ruby_guestfs_create (VALUE m)
9244 g = guestfs_create ();
9246 rb_raise (e_Error, \"failed to create guestfs handle\");
9248 /* Don't print error messages to stderr by default. */
9249 guestfs_set_error_handler (g, NULL, NULL);
9251 /* Wrap it, and make sure the close function is called when the
9254 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9257 static VALUE ruby_guestfs_close (VALUE gv)
9260 Data_Get_Struct (gv, guestfs_h, g);
9262 ruby_guestfs_free (g);
9263 DATA_PTR (gv) = NULL;
9271 fun (name, style, _, _, _, _, _) ->
9272 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9273 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9276 pr " guestfs_h *g;\n";
9277 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9279 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9285 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9286 pr " Check_Type (%sv, T_STRING);\n" n;
9287 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9289 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9290 pr " \"%s\", \"%s\");\n" n name
9292 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9293 | StringList n | DeviceList n ->
9294 pr " char **%s;\n" n;
9295 pr " Check_Type (%sv, T_ARRAY);\n" n;
9297 pr " int i, len;\n";
9298 pr " len = RARRAY_LEN (%sv);\n" n;
9299 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9301 pr " for (i = 0; i < len; ++i) {\n";
9302 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9303 pr " %s[i] = StringValueCStr (v);\n" n;
9305 pr " %s[len] = NULL;\n" n;
9308 pr " int %s = RTEST (%sv);\n" n n
9310 pr " int %s = NUM2INT (%sv);\n" n n
9312 pr " long long %s = NUM2LL (%sv);\n" n n
9317 match fst style with
9318 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9319 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9320 | RConstString _ | RConstOptString _ ->
9321 pr " const char *r;\n"; "NULL"
9322 | RString _ -> pr " char *r;\n"; "NULL"
9323 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9324 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9325 | RStructList (_, typ) ->
9326 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9329 pr " size_t size;\n";
9333 pr " r = guestfs_%s " name;
9334 generate_c_call_args ~handle:"g" style;
9339 | Pathname _ | Device _ | Dev_or_Path _ | String _
9340 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9341 | StringList n | DeviceList n ->
9342 pr " free (%s);\n" n
9345 pr " if (r == %s)\n" error_code;
9346 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9349 (match fst style with
9351 pr " return Qnil;\n"
9352 | RInt _ | RBool _ ->
9353 pr " return INT2NUM (r);\n"
9355 pr " return ULL2NUM (r);\n"
9357 pr " return rb_str_new2 (r);\n";
9358 | RConstOptString _ ->
9360 pr " return rb_str_new2 (r);\n";
9362 pr " return Qnil;\n";
9364 pr " VALUE rv = rb_str_new2 (r);\n";
9368 pr " int i, len = 0;\n";
9369 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9370 pr " VALUE rv = rb_ary_new2 (len);\n";
9371 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9372 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9373 pr " free (r[i]);\n";
9377 | RStruct (_, typ) ->
9378 let cols = cols_of_struct typ in
9379 generate_ruby_struct_code typ cols
9380 | RStructList (_, typ) ->
9381 let cols = cols_of_struct typ in
9382 generate_ruby_struct_list_code typ cols
9384 pr " VALUE rv = rb_hash_new ();\n";
9386 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9387 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9388 pr " free (r[i]);\n";
9389 pr " free (r[i+1]);\n";
9394 pr " VALUE rv = rb_str_new (r, size);\n";
9404 /* Initialize the module. */
9405 void Init__guestfs ()
9407 m_guestfs = rb_define_module (\"Guestfs\");
9408 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9409 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9411 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9412 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9415 (* Define the rest of the methods. *)
9417 fun (name, style, _, _, _, _, _) ->
9418 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9419 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9424 (* Ruby code to return a struct. *)
9425 and generate_ruby_struct_code typ cols =
9426 pr " VALUE rv = rb_hash_new ();\n";
9430 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9432 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9434 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9435 | name, (FBytes|FUInt64) ->
9436 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9438 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9440 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9442 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9443 | name, FOptPercent ->
9444 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9445 | name, FChar -> (* XXX wrong? *)
9446 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9448 pr " guestfs_free_%s (r);\n" typ;
9451 (* Ruby code to return a struct list. *)
9452 and generate_ruby_struct_list_code typ cols =
9453 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9455 pr " for (i = 0; i < r->len; ++i) {\n";
9456 pr " VALUE hv = rb_hash_new ();\n";
9460 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9462 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
9464 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9465 | name, (FBytes|FUInt64) ->
9466 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9468 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9470 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9472 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9473 | name, FOptPercent ->
9474 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9475 | name, FChar -> (* XXX wrong? *)
9476 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9478 pr " rb_ary_push (rv, hv);\n";
9480 pr " guestfs_free_%s_list (r);\n" typ;
9483 (* Generate Java bindings GuestFS.java file. *)
9484 and generate_java_java () =
9485 generate_header CStyle LGPLv2plus;
9488 package com.redhat.et.libguestfs;
9490 import java.util.HashMap;
9491 import com.redhat.et.libguestfs.LibGuestFSException;
9492 import com.redhat.et.libguestfs.PV;
9493 import com.redhat.et.libguestfs.VG;
9494 import com.redhat.et.libguestfs.LV;
9495 import com.redhat.et.libguestfs.Stat;
9496 import com.redhat.et.libguestfs.StatVFS;
9497 import com.redhat.et.libguestfs.IntBool;
9498 import com.redhat.et.libguestfs.Dirent;
9501 * The GuestFS object is a libguestfs handle.
9505 public class GuestFS {
9506 // Load the native code.
9508 System.loadLibrary (\"guestfs_jni\");
9512 * The native guestfs_h pointer.
9517 * Create a libguestfs handle.
9519 * @throws LibGuestFSException
9521 public GuestFS () throws LibGuestFSException
9525 private native long _create () throws LibGuestFSException;
9528 * Close a libguestfs handle.
9530 * You can also leave handles to be collected by the garbage
9531 * collector, but this method ensures that the resources used
9532 * by the handle are freed up immediately. If you call any
9533 * other methods after closing the handle, you will get an
9536 * @throws LibGuestFSException
9538 public void close () throws LibGuestFSException
9544 private native void _close (long g) throws LibGuestFSException;
9546 public void finalize () throws LibGuestFSException
9554 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9555 if not (List.mem NotInDocs flags); then (
9556 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9558 if List.mem ProtocolLimitWarning flags then
9559 doc ^ "\n\n" ^ protocol_limit_warning
9562 if List.mem DangerWillRobinson flags then
9563 doc ^ "\n\n" ^ danger_will_robinson
9566 match deprecation_notice flags with
9568 | Some txt -> doc ^ "\n\n" ^ txt in
9569 let doc = pod2text ~width:60 name doc in
9570 let doc = List.map ( (* RHBZ#501883 *)
9573 | nonempty -> nonempty
9575 let doc = String.concat "\n * " doc in
9578 pr " * %s\n" shortdesc;
9581 pr " * @throws LibGuestFSException\n";
9585 generate_java_prototype ~public:true ~semicolon:false name style;
9588 pr " if (g == 0)\n";
9589 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9592 if fst style <> RErr then pr "return ";
9594 generate_java_call_args ~handle:"g" (snd style);
9598 generate_java_prototype ~privat:true ~native:true name style;
9605 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9606 and generate_java_call_args ~handle args =
9608 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9611 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9612 ?(semicolon=true) name style =
9613 if privat then pr "private ";
9614 if public then pr "public ";
9615 if native then pr "native ";
9618 (match fst style with
9619 | RErr -> pr "void ";
9620 | RInt _ -> pr "int ";
9621 | RInt64 _ -> pr "long ";
9622 | RBool _ -> pr "boolean ";
9623 | RConstString _ | RConstOptString _ | RString _
9624 | RBufferOut _ -> pr "String ";
9625 | RStringList _ -> pr "String[] ";
9626 | RStruct (_, typ) ->
9627 let name = java_name_of_struct typ in
9629 | RStructList (_, typ) ->
9630 let name = java_name_of_struct typ in
9632 | RHashtable _ -> pr "HashMap<String,String> ";
9635 if native then pr "_%s " name else pr "%s " name;
9637 let needs_comma = ref false in
9646 if !needs_comma then pr ", ";
9647 needs_comma := true;
9651 | Device n | Dev_or_Path n
9657 | StringList n | DeviceList n ->
9668 pr " throws LibGuestFSException";
9669 if semicolon then pr ";"
9671 and generate_java_struct jtyp cols () =
9672 generate_header CStyle LGPLv2plus;
9675 package com.redhat.et.libguestfs;
9678 * Libguestfs %s structure.
9690 | name, FBuffer -> pr " public String %s;\n" name
9691 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9692 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9693 | name, FChar -> pr " public char %s;\n" name
9694 | name, FOptPercent ->
9695 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9696 pr " public float %s;\n" name
9701 and generate_java_c () =
9702 generate_header CStyle LGPLv2plus;
9709 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9710 #include \"guestfs.h\"
9712 /* Note that this function returns. The exception is not thrown
9713 * until after the wrapper function returns.
9716 throw_exception (JNIEnv *env, const char *msg)
9719 cl = (*env)->FindClass (env,
9720 \"com/redhat/et/libguestfs/LibGuestFSException\");
9721 (*env)->ThrowNew (env, cl, msg);
9724 JNIEXPORT jlong JNICALL
9725 Java_com_redhat_et_libguestfs_GuestFS__1create
9726 (JNIEnv *env, jobject obj)
9730 g = guestfs_create ();
9732 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9735 guestfs_set_error_handler (g, NULL, NULL);
9736 return (jlong) (long) g;
9739 JNIEXPORT void JNICALL
9740 Java_com_redhat_et_libguestfs_GuestFS__1close
9741 (JNIEnv *env, jobject obj, jlong jg)
9743 guestfs_h *g = (guestfs_h *) (long) jg;
9750 fun (name, style, _, _, _, _, _) ->
9752 (match fst style with
9753 | RErr -> pr "void ";
9754 | RInt _ -> pr "jint ";
9755 | RInt64 _ -> pr "jlong ";
9756 | RBool _ -> pr "jboolean ";
9757 | RConstString _ | RConstOptString _ | RString _
9758 | RBufferOut _ -> pr "jstring ";
9759 | RStruct _ | RHashtable _ ->
9761 | RStringList _ | RStructList _ ->
9765 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9766 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9768 pr " (JNIEnv *env, jobject obj, jlong jg";
9772 | Device n | Dev_or_Path n
9777 pr ", jstring j%s" n
9778 | StringList n | DeviceList n ->
9779 pr ", jobjectArray j%s" n
9781 pr ", jboolean j%s" n
9789 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9790 let error_code, no_ret =
9791 match fst style with
9792 | RErr -> pr " int r;\n"; "-1", ""
9794 | RInt _ -> pr " int r;\n"; "-1", "0"
9795 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9796 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9797 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9799 pr " jstring jr;\n";
9800 pr " char *r;\n"; "NULL", "NULL"
9802 pr " jobjectArray jr;\n";
9805 pr " jstring jstr;\n";
9806 pr " char **r;\n"; "NULL", "NULL"
9807 | RStruct (_, typ) ->
9808 pr " jobject jr;\n";
9810 pr " jfieldID fl;\n";
9811 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9812 | RStructList (_, typ) ->
9813 pr " jobjectArray jr;\n";
9815 pr " jfieldID fl;\n";
9816 pr " jobject jfl;\n";
9817 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9818 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9820 pr " jstring jr;\n";
9822 pr " size_t size;\n";
9827 | Device n | Dev_or_Path n
9832 pr " const char *%s;\n" n
9833 | StringList n | DeviceList n ->
9834 pr " int %s_len;\n" n;
9835 pr " const char **%s;\n" n
9840 pr " int64_t %s;\n" n
9844 (match fst style with
9845 | RStringList _ | RStructList _ -> true
9846 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9848 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9849 List.exists (function
9850 | StringList _ -> true
9851 | DeviceList _ -> true
9852 | _ -> false) (snd style) in
9858 (* Get the parameters. *)
9862 | Device n | Dev_or_Path n
9866 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9868 (* This is completely undocumented, but Java null becomes
9871 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9872 | StringList n | DeviceList n ->
9873 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9874 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9875 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9876 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9878 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9880 pr " %s[%s_len] = NULL;\n" n n;
9884 pr " %s = j%s;\n" n n
9887 (* Make the call. *)
9888 pr " r = guestfs_%s " name;
9889 generate_c_call_args ~handle:"g" style;
9892 (* Release the parameters. *)
9896 | Device n | Dev_or_Path n
9900 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9903 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9904 | StringList n | DeviceList n ->
9905 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9906 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9908 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9910 pr " free (%s);\n" n
9916 (* Check for errors. *)
9917 pr " if (r == %s) {\n" error_code;
9918 pr " throw_exception (env, guestfs_last_error (g));\n";
9919 pr " return %s;\n" no_ret;
9923 (match fst style with
9925 | RInt _ -> pr " return (jint) r;\n"
9926 | RBool _ -> pr " return (jboolean) r;\n"
9927 | RInt64 _ -> pr " return (jlong) r;\n"
9928 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9929 | RConstOptString _ ->
9930 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9932 pr " jr = (*env)->NewStringUTF (env, r);\n";
9936 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9937 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9938 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9939 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9940 pr " for (i = 0; i < r_len; ++i) {\n";
9941 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9942 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9943 pr " free (r[i]);\n";
9947 | RStruct (_, typ) ->
9948 let jtyp = java_name_of_struct typ in
9949 let cols = cols_of_struct typ in
9950 generate_java_struct_return typ jtyp cols
9951 | RStructList (_, typ) ->
9952 let jtyp = java_name_of_struct typ in
9953 let cols = cols_of_struct typ in
9954 generate_java_struct_list_return typ jtyp cols
9957 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9958 pr " return NULL;\n"
9960 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9969 and generate_java_struct_return typ jtyp cols =
9970 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9971 pr " jr = (*env)->AllocObject (env, cl);\n";
9975 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9976 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9979 pr " char s[33];\n";
9980 pr " memcpy (s, r->%s, 32);\n" name;
9982 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9983 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9987 pr " int len = r->%s_len;\n" name;
9988 pr " char s[len+1];\n";
9989 pr " memcpy (s, r->%s, len);\n" name;
9990 pr " s[len] = 0;\n";
9991 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9992 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9994 | name, (FBytes|FUInt64|FInt64) ->
9995 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9996 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9997 | name, (FUInt32|FInt32) ->
9998 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9999 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10000 | name, FOptPercent ->
10001 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10002 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10004 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10005 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10010 and generate_java_struct_list_return typ jtyp cols =
10011 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10012 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10013 pr " for (i = 0; i < r->len; ++i) {\n";
10014 pr " jfl = (*env)->AllocObject (env, cl);\n";
10018 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10019 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10022 pr " char s[33];\n";
10023 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10024 pr " s[32] = 0;\n";
10025 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10026 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10030 pr " int len = r->val[i].%s_len;\n" name;
10031 pr " char s[len+1];\n";
10032 pr " memcpy (s, r->val[i].%s, len);\n" name;
10033 pr " s[len] = 0;\n";
10034 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10035 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10037 | name, (FBytes|FUInt64|FInt64) ->
10038 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10039 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10040 | name, (FUInt32|FInt32) ->
10041 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10042 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10043 | name, FOptPercent ->
10044 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10045 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10047 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10048 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10050 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10052 pr " guestfs_free_%s_list (r);\n" typ;
10055 and generate_java_makefile_inc () =
10056 generate_header HashStyle GPLv2plus;
10058 pr "java_built_sources = \\\n";
10061 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10063 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10065 and generate_haskell_hs () =
10066 generate_header HaskellStyle LGPLv2plus;
10068 (* XXX We only know how to generate partial FFI for Haskell
10069 * at the moment. Please help out!
10071 let can_generate style =
10075 | RInt64 _, _ -> true
10077 | RConstString _, _
10078 | RConstOptString _, _
10084 | RBufferOut _, _ -> false in
10087 {-# INCLUDE <guestfs.h> #-}
10088 {-# LANGUAGE ForeignFunctionInterface #-}
10093 (* List out the names of the actions we want to export. *)
10095 fun (name, style, _, _, _, _, _) ->
10096 if can_generate style then pr ",\n %s" name
10102 -- Unfortunately some symbols duplicate ones already present
10103 -- in Prelude. We don't know which, so we hard-code a list
10105 import Prelude hiding (truncate)
10109 import Foreign.C.Types
10111 import Control.Exception
10112 import Data.Typeable
10114 data GuestfsS = GuestfsS -- represents the opaque C struct
10115 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10116 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10118 -- XXX define properly later XXX
10122 data IntBool = IntBool
10124 data StatVFS = StatVFS
10125 data Hashtable = Hashtable
10127 foreign import ccall unsafe \"guestfs_create\" c_create
10129 foreign import ccall unsafe \"&guestfs_close\" c_close
10130 :: FunPtr (GuestfsP -> IO ())
10131 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10132 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10134 create :: IO GuestfsH
10137 c_set_error_handler p nullPtr nullPtr
10138 h <- newForeignPtr c_close p
10141 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10142 :: GuestfsP -> IO CString
10144 -- last_error :: GuestfsH -> IO (Maybe String)
10145 -- last_error h = do
10146 -- str <- withForeignPtr h (\\p -> c_last_error p)
10147 -- maybePeek peekCString str
10149 last_error :: GuestfsH -> IO (String)
10151 str <- withForeignPtr h (\\p -> c_last_error p)
10152 if (str == nullPtr)
10153 then return \"no error\"
10154 else peekCString str
10158 (* Generate wrappers for each foreign function. *)
10160 fun (name, style, _, _, _, _, _) ->
10161 if can_generate style then (
10162 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10164 generate_haskell_prototype ~handle:"GuestfsP" style;
10168 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10170 pr "%s %s = do\n" name
10171 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10173 (* Convert pointer arguments using with* functions. *)
10178 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10179 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10180 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10181 | Bool _ | Int _ | Int64 _ -> ()
10183 (* Convert integer arguments. *)
10187 | Bool n -> sprintf "(fromBool %s)" n
10188 | Int n -> sprintf "(fromIntegral %s)" n
10189 | Int64 n -> sprintf "(fromIntegral %s)" n
10190 | FileIn n | FileOut n
10191 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10193 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10194 (String.concat " " ("p" :: args));
10195 (match fst style with
10196 | RErr | RInt _ | RInt64 _ | RBool _ ->
10197 pr " if (r == -1)\n";
10199 pr " err <- last_error h\n";
10201 | RConstString _ | RConstOptString _ | RString _
10202 | RStringList _ | RStruct _
10203 | RStructList _ | RHashtable _ | RBufferOut _ ->
10204 pr " if (r == nullPtr)\n";
10206 pr " err <- last_error h\n";
10209 (match fst style with
10211 pr " else return ()\n"
10213 pr " else return (fromIntegral r)\n"
10215 pr " else return (fromIntegral r)\n"
10217 pr " else return (toBool r)\n"
10219 | RConstOptString _
10226 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10232 and generate_haskell_prototype ~handle ?(hs = false) style =
10233 pr "%s -> " handle;
10234 let string = if hs then "String" else "CString" in
10235 let int = if hs then "Int" else "CInt" in
10236 let bool = if hs then "Bool" else "CInt" in
10237 let int64 = if hs then "Integer" else "Int64" in
10241 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10242 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10243 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10244 | Bool _ -> pr "%s" bool
10245 | Int _ -> pr "%s" int
10246 | Int64 _ -> pr "%s" int
10247 | FileIn _ -> pr "%s" string
10248 | FileOut _ -> pr "%s" string
10253 (match fst style with
10254 | RErr -> if not hs then pr "CInt"
10255 | RInt _ -> pr "%s" int
10256 | RInt64 _ -> pr "%s" int64
10257 | RBool _ -> pr "%s" bool
10258 | RConstString _ -> pr "%s" string
10259 | RConstOptString _ -> pr "Maybe %s" string
10260 | RString _ -> pr "%s" string
10261 | RStringList _ -> pr "[%s]" string
10262 | RStruct (_, typ) ->
10263 let name = java_name_of_struct typ in
10265 | RStructList (_, typ) ->
10266 let name = java_name_of_struct typ in
10268 | RHashtable _ -> pr "Hashtable"
10269 | RBufferOut _ -> pr "%s" string
10273 and generate_csharp () =
10274 generate_header CPlusPlusStyle LGPLv2plus;
10276 (* XXX Make this configurable by the C# assembly users. *)
10277 let library = "libguestfs.so.0" in
10280 // These C# bindings are highly experimental at present.
10282 // Firstly they only work on Linux (ie. Mono). In order to get them
10283 // to work on Windows (ie. .Net) you would need to port the library
10284 // itself to Windows first.
10286 // The second issue is that some calls are known to be incorrect and
10287 // can cause Mono to segfault. Particularly: calls which pass or
10288 // return string[], or return any structure value. This is because
10289 // we haven't worked out the correct way to do this from C#.
10291 // The third issue is that when compiling you get a lot of warnings.
10292 // We are not sure whether the warnings are important or not.
10294 // Fourthly we do not routinely build or test these bindings as part
10295 // of the make && make check cycle, which means that regressions might
10298 // Suggestions and patches are welcome.
10302 // gmcs Libguestfs.cs
10303 // mono Libguestfs.exe
10305 // (You'll probably want to add a Test class / static main function
10306 // otherwise this won't do anything useful).
10310 using System.Runtime.InteropServices;
10311 using System.Runtime.Serialization;
10312 using System.Collections;
10316 class Error : System.ApplicationException
10318 public Error (string message) : base (message) {}
10319 protected Error (SerializationInfo info, StreamingContext context) {}
10326 [DllImport (\"%s\")]
10327 static extern IntPtr guestfs_create ();
10331 _handle = guestfs_create ();
10332 if (_handle == IntPtr.Zero)
10333 throw new Error (\"could not create guestfs handle\");
10336 [DllImport (\"%s\")]
10337 static extern void guestfs_close (IntPtr h);
10341 guestfs_close (_handle);
10344 [DllImport (\"%s\")]
10345 static extern string guestfs_last_error (IntPtr h);
10347 " library library library;
10349 (* Generate C# structure bindings. We prefix struct names with
10350 * underscore because C# cannot have conflicting struct names and
10351 * method names (eg. "class stat" and "stat").
10355 pr " [StructLayout (LayoutKind.Sequential)]\n";
10356 pr " public class _%s {\n" typ;
10359 | name, FChar -> pr " char %s;\n" name
10360 | name, FString -> pr " string %s;\n" name
10362 pr " uint %s_len;\n" name;
10363 pr " string %s;\n" name
10365 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10366 pr " string %s;\n" name
10367 | name, FUInt32 -> pr " uint %s;\n" name
10368 | name, FInt32 -> pr " int %s;\n" name
10369 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10370 | name, FInt64 -> pr " long %s;\n" name
10371 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10377 (* Generate C# function bindings. *)
10379 fun (name, style, _, _, _, shortdesc, _) ->
10380 let rec csharp_return_type () =
10381 match fst style with
10383 | RBool n -> "bool"
10385 | RInt64 n -> "long"
10387 | RConstOptString n
10389 | RBufferOut n -> "string"
10390 | RStruct (_,n) -> "_" ^ n
10391 | RHashtable n -> "Hashtable"
10392 | RStringList n -> "string[]"
10393 | RStructList (_,n) -> sprintf "_%s[]" n
10395 and c_return_type () =
10396 match fst style with
10400 | RInt64 _ -> "long"
10402 | RConstOptString _
10404 | RBufferOut _ -> "string"
10405 | RStruct (_,n) -> "_" ^ n
10407 | RStringList _ -> "string[]"
10408 | RStructList (_,n) -> sprintf "_%s[]" n
10410 and c_error_comparison () =
10411 match fst style with
10415 | RInt64 _ -> "== -1"
10417 | RConstOptString _
10423 | RStructList (_,_) -> "== null"
10425 and generate_extern_prototype () =
10426 pr " static extern %s guestfs_%s (IntPtr h"
10427 (c_return_type ()) name;
10430 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10431 | FileIn n | FileOut n ->
10432 pr ", [In] string %s" n
10433 | StringList n | DeviceList n ->
10434 pr ", [In] string[] %s" n
10444 and generate_public_prototype () =
10445 pr " public %s %s (" (csharp_return_type ()) name;
10446 let comma = ref false in
10448 if !comma then pr ", ";
10453 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10454 | FileIn n | FileOut n ->
10455 next (); pr "string %s" n
10456 | StringList n | DeviceList n ->
10457 next (); pr "string[] %s" n
10459 next (); pr "bool %s" n
10461 next (); pr "int %s" n
10463 next (); pr "long %s" n
10467 and generate_call () =
10468 pr "guestfs_%s (_handle" name;
10469 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10473 pr " [DllImport (\"%s\")]\n" library;
10474 generate_extern_prototype ();
10476 pr " /// <summary>\n";
10477 pr " /// %s\n" shortdesc;
10478 pr " /// </summary>\n";
10479 generate_public_prototype ();
10481 pr " %s r;\n" (c_return_type ());
10484 pr " if (r %s)\n" (c_error_comparison ());
10485 pr " throw new Error (guestfs_last_error (_handle));\n";
10486 (match fst style with
10489 pr " return r != 0 ? true : false;\n"
10491 pr " Hashtable rr = new Hashtable ();\n";
10492 pr " for (int i = 0; i < r.Length; i += 2)\n";
10493 pr " rr.Add (r[i], r[i+1]);\n";
10495 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10496 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10502 ) all_functions_sorted;
10508 and generate_bindtests () =
10509 generate_header CStyle LGPLv2plus;
10513 #include <stdlib.h>
10514 #include <inttypes.h>
10515 #include <string.h>
10517 #include \"guestfs.h\"
10518 #include \"guestfs-internal.h\"
10519 #include \"guestfs-internal-actions.h\"
10520 #include \"guestfs_protocol.h\"
10522 #define error guestfs_error
10523 #define safe_calloc guestfs_safe_calloc
10524 #define safe_malloc guestfs_safe_malloc
10527 print_strings (char *const *argv)
10532 for (argc = 0; argv[argc] != NULL; ++argc) {
10533 if (argc > 0) printf (\", \");
10534 printf (\"\\\"%%s\\\"\", argv[argc]);
10539 /* The test0 function prints its parameters to stdout. */
10543 match test_functions with
10544 | [] -> assert false
10545 | test0 :: tests -> test0, tests in
10548 let (name, style, _, _, _, _, _) = test0 in
10549 generate_prototype ~extern:false ~semicolon:false ~newline:true
10550 ~handle:"g" ~prefix:"guestfs__" name style;
10555 | Device n | Dev_or_Path n
10558 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10559 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10560 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10561 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10562 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10563 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10565 pr " /* Java changes stdout line buffering so we need this: */\n";
10566 pr " fflush (stdout);\n";
10572 fun (name, style, _, _, _, _, _) ->
10573 if String.sub name (String.length name - 3) 3 <> "err" then (
10574 pr "/* Test normal return. */\n";
10575 generate_prototype ~extern:false ~semicolon:false ~newline:true
10576 ~handle:"g" ~prefix:"guestfs__" name style;
10578 (match fst style with
10583 pr " sscanf (val, \"%%d\", &r);\n";
10586 pr " int64_t r;\n";
10587 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10590 pr " return STREQ (val, \"true\");\n"
10592 | RConstOptString _ ->
10593 (* Can't return the input string here. Return a static
10594 * string so we ensure we get a segfault if the caller
10595 * tries to free it.
10597 pr " return \"static string\";\n"
10599 pr " return strdup (val);\n"
10601 pr " char **strs;\n";
10603 pr " sscanf (val, \"%%d\", &n);\n";
10604 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10605 pr " for (i = 0; i < n; ++i) {\n";
10606 pr " strs[i] = safe_malloc (g, 16);\n";
10607 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10609 pr " strs[n] = NULL;\n";
10610 pr " return strs;\n"
10611 | RStruct (_, typ) ->
10612 pr " struct guestfs_%s *r;\n" typ;
10613 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10615 | RStructList (_, typ) ->
10616 pr " struct guestfs_%s_list *r;\n" typ;
10617 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10618 pr " sscanf (val, \"%%d\", &r->len);\n";
10619 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10622 pr " char **strs;\n";
10624 pr " sscanf (val, \"%%d\", &n);\n";
10625 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10626 pr " for (i = 0; i < n; ++i) {\n";
10627 pr " strs[i*2] = safe_malloc (g, 16);\n";
10628 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10629 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10630 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10632 pr " strs[n*2] = NULL;\n";
10633 pr " return strs;\n"
10635 pr " return strdup (val);\n"
10640 pr "/* Test error return. */\n";
10641 generate_prototype ~extern:false ~semicolon:false ~newline:true
10642 ~handle:"g" ~prefix:"guestfs__" name style;
10644 pr " error (g, \"error\");\n";
10645 (match fst style with
10646 | RErr | RInt _ | RInt64 _ | RBool _ ->
10648 | RConstString _ | RConstOptString _
10649 | RString _ | RStringList _ | RStruct _
10653 pr " return NULL;\n"
10660 and generate_ocaml_bindtests () =
10661 generate_header OCamlStyle GPLv2plus;
10665 let g = Guestfs.create () in
10669 String.concat " " (
10672 | CallString s -> "\"" ^ s ^ "\""
10673 | CallOptString None -> "None"
10674 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10675 | CallStringList xs ->
10676 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10677 | CallInt i when i >= 0 -> string_of_int i
10678 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10679 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10680 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10681 | CallBool b -> string_of_bool b
10686 generate_lang_bindtests (
10687 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10690 pr "print_endline \"EOF\"\n"
10692 and generate_perl_bindtests () =
10693 pr "#!/usr/bin/perl -w\n";
10694 generate_header HashStyle GPLv2plus;
10701 my $g = Sys::Guestfs->new ();
10705 String.concat ", " (
10708 | CallString s -> "\"" ^ s ^ "\""
10709 | CallOptString None -> "undef"
10710 | CallOptString (Some s) -> sprintf "\"%s\"" s
10711 | CallStringList xs ->
10712 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10713 | CallInt i -> string_of_int i
10714 | CallInt64 i -> Int64.to_string i
10715 | CallBool b -> if b then "1" else "0"
10720 generate_lang_bindtests (
10721 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10724 pr "print \"EOF\\n\"\n"
10726 and generate_python_bindtests () =
10727 generate_header HashStyle GPLv2plus;
10732 g = guestfs.GuestFS ()
10736 String.concat ", " (
10739 | CallString s -> "\"" ^ s ^ "\""
10740 | CallOptString None -> "None"
10741 | CallOptString (Some s) -> sprintf "\"%s\"" s
10742 | CallStringList xs ->
10743 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10744 | CallInt i -> string_of_int i
10745 | CallInt64 i -> Int64.to_string i
10746 | CallBool b -> if b then "1" else "0"
10751 generate_lang_bindtests (
10752 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10755 pr "print \"EOF\"\n"
10757 and generate_ruby_bindtests () =
10758 generate_header HashStyle GPLv2plus;
10763 g = Guestfs::create()
10767 String.concat ", " (
10770 | CallString s -> "\"" ^ s ^ "\""
10771 | CallOptString None -> "nil"
10772 | CallOptString (Some s) -> sprintf "\"%s\"" s
10773 | CallStringList xs ->
10774 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10775 | CallInt i -> string_of_int i
10776 | CallInt64 i -> Int64.to_string i
10777 | CallBool b -> string_of_bool b
10782 generate_lang_bindtests (
10783 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10786 pr "print \"EOF\\n\"\n"
10788 and generate_java_bindtests () =
10789 generate_header CStyle GPLv2plus;
10792 import com.redhat.et.libguestfs.*;
10794 public class Bindtests {
10795 public static void main (String[] argv)
10798 GuestFS g = new GuestFS ();
10802 String.concat ", " (
10805 | CallString s -> "\"" ^ s ^ "\""
10806 | CallOptString None -> "null"
10807 | CallOptString (Some s) -> sprintf "\"%s\"" s
10808 | CallStringList xs ->
10810 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10811 | CallInt i -> string_of_int i
10812 | CallInt64 i -> Int64.to_string i
10813 | CallBool b -> string_of_bool b
10818 generate_lang_bindtests (
10819 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10823 System.out.println (\"EOF\");
10825 catch (Exception exn) {
10826 System.err.println (exn);
10833 and generate_haskell_bindtests () =
10834 generate_header HaskellStyle GPLv2plus;
10837 module Bindtests where
10838 import qualified Guestfs
10841 g <- Guestfs.create
10845 String.concat " " (
10848 | CallString s -> "\"" ^ s ^ "\""
10849 | CallOptString None -> "Nothing"
10850 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10851 | CallStringList xs ->
10852 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10853 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10854 | CallInt i -> string_of_int i
10855 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10856 | CallInt64 i -> Int64.to_string i
10857 | CallBool true -> "True"
10858 | CallBool false -> "False"
10863 generate_lang_bindtests (
10864 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10867 pr " putStrLn \"EOF\"\n"
10869 (* Language-independent bindings tests - we do it this way to
10870 * ensure there is parity in testing bindings across all languages.
10872 and generate_lang_bindtests call =
10873 call "test0" [CallString "abc"; CallOptString (Some "def");
10874 CallStringList []; CallBool false;
10875 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10876 call "test0" [CallString "abc"; CallOptString None;
10877 CallStringList []; CallBool false;
10878 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10879 call "test0" [CallString ""; CallOptString (Some "def");
10880 CallStringList []; CallBool false;
10881 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10882 call "test0" [CallString ""; CallOptString (Some "");
10883 CallStringList []; CallBool false;
10884 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10885 call "test0" [CallString "abc"; CallOptString (Some "def");
10886 CallStringList ["1"]; CallBool false;
10887 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10888 call "test0" [CallString "abc"; CallOptString (Some "def");
10889 CallStringList ["1"; "2"]; CallBool false;
10890 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10891 call "test0" [CallString "abc"; CallOptString (Some "def");
10892 CallStringList ["1"]; CallBool true;
10893 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10894 call "test0" [CallString "abc"; CallOptString (Some "def");
10895 CallStringList ["1"]; CallBool false;
10896 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10897 call "test0" [CallString "abc"; CallOptString (Some "def");
10898 CallStringList ["1"]; CallBool false;
10899 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10900 call "test0" [CallString "abc"; CallOptString (Some "def");
10901 CallStringList ["1"]; CallBool false;
10902 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10903 call "test0" [CallString "abc"; CallOptString (Some "def");
10904 CallStringList ["1"]; CallBool false;
10905 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10906 call "test0" [CallString "abc"; CallOptString (Some "def");
10907 CallStringList ["1"]; CallBool false;
10908 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10909 call "test0" [CallString "abc"; CallOptString (Some "def");
10910 CallStringList ["1"]; CallBool false;
10911 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10913 (* XXX Add here tests of the return and error functions. *)
10915 (* Code to generator bindings for virt-inspector. Currently only
10916 * implemented for OCaml code (for virt-p2v 2.0).
10918 let rng_input = "inspector/virt-inspector.rng"
10920 (* Read the input file and parse it into internal structures. This is
10921 * by no means a complete RELAX NG parser, but is just enough to be
10922 * able to parse the specific input file.
10925 | Element of string * rng list (* <element name=name/> *)
10926 | Attribute of string * rng list (* <attribute name=name/> *)
10927 | Interleave of rng list (* <interleave/> *)
10928 | ZeroOrMore of rng (* <zeroOrMore/> *)
10929 | OneOrMore of rng (* <oneOrMore/> *)
10930 | Optional of rng (* <optional/> *)
10931 | Choice of string list (* <choice><value/>*</choice> *)
10932 | Value of string (* <value>str</value> *)
10933 | Text (* <text/> *)
10935 let rec string_of_rng = function
10936 | Element (name, xs) ->
10937 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10938 | Attribute (name, xs) ->
10939 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10940 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10941 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10942 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10943 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10944 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10945 | Value value -> "Value \"" ^ value ^ "\""
10948 and string_of_rng_list xs =
10949 String.concat ", " (List.map string_of_rng xs)
10951 let rec parse_rng ?defines context = function
10953 | Xml.Element ("element", ["name", name], children) :: rest ->
10954 Element (name, parse_rng ?defines context children)
10955 :: parse_rng ?defines context rest
10956 | Xml.Element ("attribute", ["name", name], children) :: rest ->
10957 Attribute (name, parse_rng ?defines context children)
10958 :: parse_rng ?defines context rest
10959 | Xml.Element ("interleave", [], children) :: rest ->
10960 Interleave (parse_rng ?defines context children)
10961 :: parse_rng ?defines context rest
10962 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10963 let rng = parse_rng ?defines context [child] in
10965 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10967 failwithf "%s: <zeroOrMore> contains more than one child element"
10970 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10971 let rng = parse_rng ?defines context [child] in
10973 | [child] -> OneOrMore child :: parse_rng ?defines context rest
10975 failwithf "%s: <oneOrMore> contains more than one child element"
10978 | Xml.Element ("optional", [], [child]) :: rest ->
10979 let rng = parse_rng ?defines context [child] in
10981 | [child] -> Optional child :: parse_rng ?defines context rest
10983 failwithf "%s: <optional> contains more than one child element"
10986 | Xml.Element ("choice", [], children) :: rest ->
10987 let values = List.map (
10988 function Xml.Element ("value", [], [Xml.PCData value]) -> value
10990 failwithf "%s: can't handle anything except <value> in <choice>"
10994 :: parse_rng ?defines context rest
10995 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10996 Value value :: parse_rng ?defines context rest
10997 | Xml.Element ("text", [], []) :: rest ->
10998 Text :: parse_rng ?defines context rest
10999 | Xml.Element ("ref", ["name", name], []) :: rest ->
11000 (* Look up the reference. Because of limitations in this parser,
11001 * we can't handle arbitrarily nested <ref> yet. You can only
11002 * use <ref> from inside <start>.
11004 (match defines with
11006 failwithf "%s: contains <ref>, but no refs are defined yet" context
11008 let rng = StringMap.find name map in
11009 rng @ parse_rng ?defines context rest
11012 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11015 let xml = Xml.parse_file rng_input in
11017 | Xml.Element ("grammar", _,
11018 Xml.Element ("start", _, gram) :: defines) ->
11019 (* The <define/> elements are referenced in the <start> section,
11020 * so build a map of those first.
11022 let defines = List.fold_left (
11024 function Xml.Element ("define", ["name", name], defn) ->
11025 StringMap.add name defn map
11027 failwithf "%s: expected <define name=name/>" rng_input
11028 ) StringMap.empty defines in
11029 let defines = StringMap.mapi parse_rng defines in
11031 (* Parse the <start> clause, passing the defines. *)
11032 parse_rng ~defines "<start>" gram
11034 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11037 let name_of_field = function
11038 | Element (name, _) | Attribute (name, _)
11039 | ZeroOrMore (Element (name, _))
11040 | OneOrMore (Element (name, _))
11041 | Optional (Element (name, _)) -> name
11042 | Optional (Attribute (name, _)) -> name
11043 | Text -> (* an unnamed field in an element *)
11046 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11048 (* At the moment this function only generates OCaml types. However we
11049 * should parameterize it later so it can generate types/structs in a
11050 * variety of languages.
11052 let generate_types xs =
11053 (* A simple type is one that can be printed out directly, eg.
11054 * "string option". A complex type is one which has a name and has
11055 * to be defined via another toplevel definition, eg. a struct.
11057 * generate_type generates code for either simple or complex types.
11058 * In the simple case, it returns the string ("string option"). In
11059 * the complex case, it returns the name ("mountpoint"). In the
11060 * complex case it has to print out the definition before returning,
11061 * so it should only be called when we are at the beginning of a
11062 * new line (BOL context).
11064 let rec generate_type = function
11065 | Text -> (* string *)
11067 | Choice values -> (* [`val1|`val2|...] *)
11068 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11069 | ZeroOrMore rng -> (* <rng> list *)
11070 let t, is_simple = generate_type rng in
11071 t ^ " list (* 0 or more *)", is_simple
11072 | OneOrMore rng -> (* <rng> list *)
11073 let t, is_simple = generate_type rng in
11074 t ^ " list (* 1 or more *)", is_simple
11075 (* virt-inspector hack: bool *)
11076 | Optional (Attribute (name, [Value "1"])) ->
11078 | Optional rng -> (* <rng> list *)
11079 let t, is_simple = generate_type rng in
11080 t ^ " option", is_simple
11081 (* type name = { fields ... } *)
11082 | Element (name, fields) when is_attrs_interleave fields ->
11083 generate_type_struct name (get_attrs_interleave fields)
11084 | Element (name, [field]) (* type name = field *)
11085 | Attribute (name, [field]) ->
11086 let t, is_simple = generate_type field in
11087 if is_simple then (t, true)
11089 pr "type %s = %s\n" name t;
11092 | Element (name, fields) -> (* type name = { fields ... } *)
11093 generate_type_struct name fields
11095 failwithf "generate_type failed at: %s" (string_of_rng rng)
11097 and is_attrs_interleave = function
11098 | [Interleave _] -> true
11099 | Attribute _ :: fields -> is_attrs_interleave fields
11100 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11103 and get_attrs_interleave = function
11104 | [Interleave fields] -> fields
11105 | ((Attribute _) as field) :: fields
11106 | ((Optional (Attribute _)) as field) :: fields ->
11107 field :: get_attrs_interleave fields
11108 | _ -> assert false
11110 and generate_types xs =
11111 List.iter (fun x -> ignore (generate_type x)) xs
11113 and generate_type_struct name fields =
11114 (* Calculate the types of the fields first. We have to do this
11115 * before printing anything so we are still in BOL context.
11117 let types = List.map fst (List.map generate_type fields) in
11119 (* Special case of a struct containing just a string and another
11120 * field. Turn it into an assoc list.
11123 | ["string"; other] ->
11124 let fname1, fname2 =
11126 | [f1; f2] -> name_of_field f1, name_of_field f2
11127 | _ -> assert false in
11128 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11132 pr "type %s = {\n" name;
11134 fun (field, ftype) ->
11135 let fname = name_of_field field in
11136 pr " %s_%s : %s;\n" name fname ftype
11137 ) (List.combine fields types);
11139 (* Return the name of this type, and
11140 * false because it's not a simple type.
11147 let generate_parsers xs =
11148 (* As for generate_type above, generate_parser makes a parser for
11149 * some type, and returns the name of the parser it has generated.
11150 * Because it (may) need to print something, it should always be
11151 * called in BOL context.
11153 let rec generate_parser = function
11154 | Text -> (* string *)
11155 "string_child_or_empty"
11156 | Choice values -> (* [`val1|`val2|...] *)
11157 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11159 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11160 | ZeroOrMore rng -> (* <rng> list *)
11161 let pa = generate_parser rng in
11162 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11163 | OneOrMore rng -> (* <rng> list *)
11164 let pa = generate_parser rng in
11165 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11166 (* virt-inspector hack: bool *)
11167 | Optional (Attribute (name, [Value "1"])) ->
11168 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11169 | Optional rng -> (* <rng> list *)
11170 let pa = generate_parser rng in
11171 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11172 (* type name = { fields ... } *)
11173 | Element (name, fields) when is_attrs_interleave fields ->
11174 generate_parser_struct name (get_attrs_interleave fields)
11175 | Element (name, [field]) -> (* type name = field *)
11176 let pa = generate_parser field in
11177 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11178 pr "let %s =\n" parser_name;
11180 pr "let parse_%s = %s\n" name parser_name;
11182 | Attribute (name, [field]) ->
11183 let pa = generate_parser field in
11184 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11185 pr "let %s =\n" parser_name;
11187 pr "let parse_%s = %s\n" name parser_name;
11189 | Element (name, fields) -> (* type name = { fields ... } *)
11190 generate_parser_struct name ([], fields)
11192 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11194 and is_attrs_interleave = function
11195 | [Interleave _] -> true
11196 | Attribute _ :: fields -> is_attrs_interleave fields
11197 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11200 and get_attrs_interleave = function
11201 | [Interleave fields] -> [], fields
11202 | ((Attribute _) as field) :: fields
11203 | ((Optional (Attribute _)) as field) :: fields ->
11204 let attrs, interleaves = get_attrs_interleave fields in
11205 (field :: attrs), interleaves
11206 | _ -> assert false
11208 and generate_parsers xs =
11209 List.iter (fun x -> ignore (generate_parser x)) xs
11211 and generate_parser_struct name (attrs, interleaves) =
11212 (* Generate parsers for the fields first. We have to do this
11213 * before printing anything so we are still in BOL context.
11215 let fields = attrs @ interleaves in
11216 let pas = List.map generate_parser fields in
11218 (* Generate an intermediate tuple from all the fields first.
11219 * If the type is just a string + another field, then we will
11220 * return this directly, otherwise it is turned into a record.
11222 * RELAX NG note: This code treats <interleave> and plain lists of
11223 * fields the same. In other words, it doesn't bother enforcing
11224 * any ordering of fields in the XML.
11226 pr "let parse_%s x =\n" name;
11227 pr " let t = (\n ";
11228 let comma = ref false in
11231 if !comma then pr ",\n ";
11234 | Optional (Attribute (fname, [field])), pa ->
11236 | Optional (Element (fname, [field])), pa ->
11237 pr "%s (optional_child %S x)" pa fname
11238 | Attribute (fname, [Text]), _ ->
11239 pr "attribute %S x" fname
11240 | (ZeroOrMore _ | OneOrMore _), pa ->
11245 let fname = name_of_field field in
11246 pr "%s (child %S x)" pa fname
11247 ) (List.combine fields pas);
11251 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11255 pr " (Obj.magic t : %s)\n" name
11259 | (Optional (Attribute (fname, [field])), pa) ->
11260 pr " %s_%s =\n" name fname;
11262 | (Optional (Element (fname, [field])), pa) ->
11263 pr " %s_%s =\n" name fname;
11264 pr " (let x = optional_child %S x in\n" fname;
11267 let fname = name_of_field field in
11268 pr " %s_%s =\n" name fname;
11269 pr " (let x = child %S x in\n" fname;
11271 ) (List.combine fields pas);
11275 sprintf "parse_%s" name
11278 generate_parsers xs
11280 (* Generate ocaml/guestfs_inspector.mli. *)
11281 let generate_ocaml_inspector_mli () =
11282 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11285 (** This is an OCaml language binding to the external [virt-inspector]
11288 For more information, please read the man page [virt-inspector(1)].
11293 generate_types grammar;
11294 pr "(** The nested information returned from the {!inspect} function. *)\n";
11298 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11299 (** To inspect a libvirt domain called [name], pass a singleton
11300 list: [inspect [name]]. When using libvirt only, you may
11301 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11303 To inspect a disk image or images, pass a list of the filenames
11304 of the disk images: [inspect filenames]
11306 This function inspects the given guest or disk images and
11307 returns a list of operating system(s) found and a large amount
11308 of information about them. In the vast majority of cases,
11309 a virtual machine only contains a single operating system.
11311 If the optional [~xml] parameter is given, then this function
11312 skips running the external virt-inspector program and just
11313 parses the given XML directly (which is expected to be XML
11314 produced from a previous run of virt-inspector). The list of
11315 names and connect URI are ignored in this case.
11317 This function can throw a wide variety of exceptions, for example
11318 if the external virt-inspector program cannot be found, or if
11319 it doesn't generate valid XML.
11323 (* Generate ocaml/guestfs_inspector.ml. *)
11324 let generate_ocaml_inspector_ml () =
11325 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11330 generate_types grammar;
11334 (* Misc functions which are used by the parser code below. *)
11335 let first_child = function
11336 | Xml.Element (_, _, c::_) -> c
11337 | Xml.Element (name, _, []) ->
11338 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11339 | Xml.PCData str ->
11340 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11342 let string_child_or_empty = function
11343 | Xml.Element (_, _, [Xml.PCData s]) -> s
11344 | Xml.Element (_, _, []) -> \"\"
11345 | Xml.Element (x, _, _) ->
11346 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11348 | Xml.PCData str ->
11349 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11351 let optional_child name xml =
11352 let children = Xml.children xml in
11354 Some (List.find (function
11355 | Xml.Element (n, _, _) when n = name -> true
11356 | _ -> false) children)
11360 let child name xml =
11361 match optional_child name xml with
11364 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11366 let attribute name xml =
11367 try Xml.attrib xml name
11368 with Xml.No_attribute _ ->
11369 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11373 generate_parsers grammar;
11377 (* Run external virt-inspector, then use parser to parse the XML. *)
11378 let inspect ?connect ?xml names =
11382 if names = [] then invalid_arg \"inspect: no names given\";
11383 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11384 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11386 let cmd = List.map Filename.quote cmd in
11387 let cmd = String.concat \" \" cmd in
11388 let chan = open_process_in cmd in
11389 let xml = Xml.parse_in chan in
11390 (match close_process_in chan with
11392 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11393 | WSIGNALED i | WSTOPPED i ->
11394 failwith (\"external virt-inspector command died or stopped on sig \" ^
11399 Xml.parse_string doc in
11400 parse_operatingsystems xml
11403 (* This is used to generate the src/MAX_PROC_NR file which
11404 * contains the maximum procedure number, a surrogate for the
11405 * ABI version number. See src/Makefile.am for the details.
11407 and generate_max_proc_nr () =
11408 let proc_nrs = List.map (
11409 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11410 ) daemon_functions in
11412 let max_proc_nr = List.fold_left max 0 proc_nrs in
11414 pr "%d\n" max_proc_nr
11416 let output_to filename k =
11417 let filename_new = filename ^ ".new" in
11418 chan := open_out filename_new;
11421 chan := Pervasives.stdout;
11423 (* Is the new file different from the current file? *)
11424 if Sys.file_exists filename && files_equal filename filename_new then
11425 unlink filename_new (* same, so skip it *)
11427 (* different, overwrite old one *)
11428 (try chmod filename 0o644 with Unix_error _ -> ());
11429 rename filename_new filename;
11430 chmod filename 0o444;
11431 printf "written %s\n%!" filename;
11434 let perror msg = function
11435 | Unix_error (err, _, _) ->
11436 eprintf "%s: %s\n" msg (error_message err)
11438 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11440 (* Main program. *)
11443 try openfile "HACKING" [O_RDWR] 0
11445 | Unix_error (ENOENT, _, _) ->
11447 You are probably running this from the wrong directory.
11448 Run it from the top source directory using the command
11453 perror "open: HACKING" exn;
11456 (* Acquire a lock so parallel builds won't try to run the generator
11457 * twice at the same time. Subsequent builds will wait for the first
11458 * one to finish. Note the lock is released implicitly when the
11461 (try lockf lock_fd F_LOCK 1
11463 perror "lock: HACKING" exn;
11466 check_functions ();
11468 output_to "src/guestfs_protocol.x" generate_xdr;
11469 output_to "src/guestfs-structs.h" generate_structs_h;
11470 output_to "src/guestfs-actions.h" generate_actions_h;
11471 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11472 output_to "src/guestfs-actions.c" generate_client_actions;
11473 output_to "src/guestfs-bindtests.c" generate_bindtests;
11474 output_to "src/guestfs-structs.pod" generate_structs_pod;
11475 output_to "src/guestfs-actions.pod" generate_actions_pod;
11476 output_to "src/guestfs-availability.pod" generate_availability_pod;
11477 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11478 output_to "src/libguestfs.syms" generate_linker_script;
11479 output_to "daemon/actions.h" generate_daemon_actions_h;
11480 output_to "daemon/stubs.c" generate_daemon_actions;
11481 output_to "daemon/names.c" generate_daemon_names;
11482 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11483 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11484 output_to "capitests/tests.c" generate_tests;
11485 output_to "fish/cmds.c" generate_fish_cmds;
11486 output_to "fish/completion.c" generate_fish_completion;
11487 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11488 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11489 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11490 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11491 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11492 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11493 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11494 output_to "perl/Guestfs.xs" generate_perl_xs;
11495 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11496 output_to "perl/bindtests.pl" generate_perl_bindtests;
11497 output_to "python/guestfs-py.c" generate_python_c;
11498 output_to "python/guestfs.py" generate_python_py;
11499 output_to "python/bindtests.py" generate_python_bindtests;
11500 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11501 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11502 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11506 let cols = cols_of_struct typ in
11507 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11508 output_to filename (generate_java_struct jtyp cols);
11511 output_to "java/Makefile.inc" generate_java_makefile_inc;
11512 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11513 output_to "java/Bindtests.java" generate_java_bindtests;
11514 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11515 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11516 output_to "csharp/Libguestfs.cs" generate_csharp;
11518 (* Always generate this file last, and unconditionally. It's used
11519 * by the Makefile to know when we must re-run the generator.
11521 let chan = open_out "src/stamp-generator" in
11522 fprintf chan "1\n";
11525 printf "generated %d lines of code\n" !lines