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.
957 When you use this call, the filesystem options C<sync> and C<noatime>
958 are set implicitly. This was originally done because we thought it
959 would improve reliability, but it turns out that I<-o sync> has a
960 very large negative performance impact and negligible effect on
961 reliability. Therefore we recommend that you avoid using
962 C<guestfs_mount> in any code that needs performance, and instead
963 use C<guestfs_mount_options> (use an empty string for the first
964 parameter if you don't want any options).");
966 ("sync", (RErr, []), 2, [],
967 [ InitEmpty, Always, TestRun [["sync"]]],
968 "sync disks, writes are flushed through to the disk image",
970 This syncs the disk, so that any writes are flushed through to the
971 underlying disk image.
973 You should always call this if you have modified a disk image, before
974 closing the handle.");
976 ("touch", (RErr, [Pathname "path"]), 3, [],
977 [InitBasicFS, Always, TestOutputTrue (
979 ["exists"; "/new"]])],
980 "update file timestamps or create a new file",
982 Touch acts like the L<touch(1)> command. It can be used to
983 update the timestamps on a file, or, if the file does not exist,
984 to create a new zero-length file.");
986 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
987 [InitISOFS, Always, TestOutput (
988 [["cat"; "/known-2"]], "abcdef\n")],
989 "list the contents of a file",
991 Return the contents of the file named C<path>.
993 Note that this function cannot correctly handle binary files
994 (specifically, files containing C<\\0> character which is treated
995 as end of string). For those you need to use the C<guestfs_read_file>
996 or C<guestfs_download> functions which have a more complex interface.");
998 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
999 [], (* XXX Tricky to test because it depends on the exact format
1000 * of the 'ls -l' command, which changes between F10 and F11.
1002 "list the files in a directory (long format)",
1004 List the files in C<directory> (relative to the root directory,
1005 there is no cwd) in the format of 'ls -la'.
1007 This command is mostly useful for interactive sessions. It
1008 is I<not> intended that you try to parse the output string.");
1010 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1011 [InitBasicFS, Always, TestOutputList (
1013 ["touch"; "/newer"];
1014 ["touch"; "/newest"];
1015 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1016 "list the files in a directory",
1018 List the files in C<directory> (relative to the root directory,
1019 there is no cwd). The '.' and '..' entries are not returned, but
1020 hidden files are shown.
1022 This command is mostly useful for interactive sessions. Programs
1023 should probably use C<guestfs_readdir> instead.");
1025 ("list_devices", (RStringList "devices", []), 7, [],
1026 [InitEmpty, Always, TestOutputListOfDevices (
1027 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1028 "list the block devices",
1030 List all the block devices.
1032 The full block device names are returned, eg. C</dev/sda>");
1034 ("list_partitions", (RStringList "partitions", []), 8, [],
1035 [InitBasicFS, Always, TestOutputListOfDevices (
1036 [["list_partitions"]], ["/dev/sda1"]);
1037 InitEmpty, Always, TestOutputListOfDevices (
1038 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1039 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1040 "list the partitions",
1042 List all the partitions detected on all block devices.
1044 The full partition device names are returned, eg. C</dev/sda1>
1046 This does not return logical volumes. For that you will need to
1047 call C<guestfs_lvs>.");
1049 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1050 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1051 [["pvs"]], ["/dev/sda1"]);
1052 InitEmpty, Always, TestOutputListOfDevices (
1053 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1054 ["pvcreate"; "/dev/sda1"];
1055 ["pvcreate"; "/dev/sda2"];
1056 ["pvcreate"; "/dev/sda3"];
1057 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1058 "list the LVM physical volumes (PVs)",
1060 List all the physical volumes detected. This is the equivalent
1061 of the L<pvs(8)> command.
1063 This returns a list of just the device names that contain
1064 PVs (eg. C</dev/sda2>).
1066 See also C<guestfs_pvs_full>.");
1068 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1069 [InitBasicFSonLVM, Always, TestOutputList (
1071 InitEmpty, Always, TestOutputList (
1072 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1073 ["pvcreate"; "/dev/sda1"];
1074 ["pvcreate"; "/dev/sda2"];
1075 ["pvcreate"; "/dev/sda3"];
1076 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1077 ["vgcreate"; "VG2"; "/dev/sda3"];
1078 ["vgs"]], ["VG1"; "VG2"])],
1079 "list the LVM volume groups (VGs)",
1081 List all the volumes groups detected. This is the equivalent
1082 of the L<vgs(8)> command.
1084 This returns a list of just the volume group names that were
1085 detected (eg. C<VolGroup00>).
1087 See also C<guestfs_vgs_full>.");
1089 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1090 [InitBasicFSonLVM, Always, TestOutputList (
1091 [["lvs"]], ["/dev/VG/LV"]);
1092 InitEmpty, Always, TestOutputList (
1093 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1094 ["pvcreate"; "/dev/sda1"];
1095 ["pvcreate"; "/dev/sda2"];
1096 ["pvcreate"; "/dev/sda3"];
1097 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1098 ["vgcreate"; "VG2"; "/dev/sda3"];
1099 ["lvcreate"; "LV1"; "VG1"; "50"];
1100 ["lvcreate"; "LV2"; "VG1"; "50"];
1101 ["lvcreate"; "LV3"; "VG2"; "50"];
1102 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1103 "list the LVM logical volumes (LVs)",
1105 List all the logical volumes detected. This is the equivalent
1106 of the L<lvs(8)> command.
1108 This returns a list of the logical volume device names
1109 (eg. C</dev/VolGroup00/LogVol00>).
1111 See also C<guestfs_lvs_full>.");
1113 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1114 [], (* XXX how to test? *)
1115 "list the LVM physical volumes (PVs)",
1117 List all the physical volumes detected. This is the equivalent
1118 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1120 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1121 [], (* XXX how to test? *)
1122 "list the LVM volume groups (VGs)",
1124 List all the volumes groups detected. This is the equivalent
1125 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1127 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1128 [], (* XXX how to test? *)
1129 "list the LVM logical volumes (LVs)",
1131 List all the logical volumes detected. This is the equivalent
1132 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1134 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1135 [InitISOFS, Always, TestOutputList (
1136 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1137 InitISOFS, Always, TestOutputList (
1138 [["read_lines"; "/empty"]], [])],
1139 "read file as lines",
1141 Return the contents of the file named C<path>.
1143 The file contents are returned as a list of lines. Trailing
1144 C<LF> and C<CRLF> character sequences are I<not> returned.
1146 Note that this function cannot correctly handle binary files
1147 (specifically, files containing C<\\0> character which is treated
1148 as end of line). For those you need to use the C<guestfs_read_file>
1149 function which has a more complex interface.");
1151 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1152 [], (* XXX Augeas code needs tests. *)
1153 "create a new Augeas handle",
1155 Create a new Augeas handle for editing configuration files.
1156 If there was any previous Augeas handle associated with this
1157 guestfs session, then it is closed.
1159 You must call this before using any other C<guestfs_aug_*>
1162 C<root> is the filesystem root. C<root> must not be NULL,
1165 The flags are the same as the flags defined in
1166 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 =item C<AUG_SAVE_BACKUP> = 1
1173 Keep the original file with a C<.augsave> extension.
1175 =item C<AUG_SAVE_NEWFILE> = 2
1177 Save changes into a file with extension C<.augnew>, and
1178 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1180 =item C<AUG_TYPE_CHECK> = 4
1182 Typecheck lenses (can be expensive).
1184 =item C<AUG_NO_STDINC> = 8
1186 Do not use standard load path for modules.
1188 =item C<AUG_SAVE_NOOP> = 16
1190 Make save a no-op, just record what would have been changed.
1192 =item C<AUG_NO_LOAD> = 32
1194 Do not load the tree in C<guestfs_aug_init>.
1198 To close the handle, you can call C<guestfs_aug_close>.
1200 To find out more about Augeas, see L<http://augeas.net/>.");
1202 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1203 [], (* XXX Augeas code needs tests. *)
1204 "close the current Augeas handle",
1206 Close the current Augeas handle and free up any resources
1207 used by it. After calling this, you have to call
1208 C<guestfs_aug_init> again before you can use any other
1209 Augeas functions.");
1211 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1212 [], (* XXX Augeas code needs tests. *)
1213 "define an Augeas variable",
1215 Defines an Augeas variable C<name> whose value is the result
1216 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1219 On success this returns the number of nodes in C<expr>, or
1220 C<0> if C<expr> evaluates to something which is not a nodeset.");
1222 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1223 [], (* XXX Augeas code needs tests. *)
1224 "define an Augeas node",
1226 Defines a variable C<name> whose value is the result of
1229 If C<expr> evaluates to an empty nodeset, a node is created,
1230 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1231 C<name> will be the nodeset containing that single node.
1233 On success this returns a pair containing the
1234 number of nodes in the nodeset, and a boolean flag
1235 if a node was created.");
1237 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1238 [], (* XXX Augeas code needs tests. *)
1239 "look up the value of an Augeas path",
1241 Look up the value associated with C<path>. If C<path>
1242 matches exactly one node, the C<value> is returned.");
1244 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1245 [], (* XXX Augeas code needs tests. *)
1246 "set Augeas path to value",
1248 Set the value associated with C<path> to C<value>.");
1250 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1251 [], (* XXX Augeas code needs tests. *)
1252 "insert a sibling Augeas node",
1254 Create a new sibling C<label> for C<path>, inserting it into
1255 the tree before or after C<path> (depending on the boolean
1258 C<path> must match exactly one existing node in the tree, and
1259 C<label> must be a label, ie. not contain C</>, C<*> or end
1260 with a bracketed index C<[N]>.");
1262 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1263 [], (* XXX Augeas code needs tests. *)
1264 "remove an Augeas path",
1266 Remove C<path> and all of its children.
1268 On success this returns the number of entries which were removed.");
1270 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1271 [], (* XXX Augeas code needs tests. *)
1274 Move the node C<src> to C<dest>. C<src> must match exactly
1275 one node. C<dest> is overwritten if it exists.");
1277 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1278 [], (* XXX Augeas code needs tests. *)
1279 "return Augeas nodes which match augpath",
1281 Returns a list of paths which match the path expression C<path>.
1282 The returned paths are sufficiently qualified so that they match
1283 exactly one node in the current tree.");
1285 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1286 [], (* XXX Augeas code needs tests. *)
1287 "write all pending Augeas changes to disk",
1289 This writes all pending changes to disk.
1291 The flags which were passed to C<guestfs_aug_init> affect exactly
1292 how files are saved.");
1294 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1295 [], (* XXX Augeas code needs tests. *)
1296 "load files into the tree",
1298 Load files into the tree.
1300 See C<aug_load> in the Augeas documentation for the full gory
1303 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1304 [], (* XXX Augeas code needs tests. *)
1305 "list Augeas nodes under augpath",
1307 This is just a shortcut for listing C<guestfs_aug_match>
1308 C<path/*> and sorting the resulting nodes into alphabetical order.");
1310 ("rm", (RErr, [Pathname "path"]), 29, [],
1311 [InitBasicFS, Always, TestRun
1314 InitBasicFS, Always, TestLastFail
1316 InitBasicFS, Always, TestLastFail
1321 Remove the single file C<path>.");
1323 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1324 [InitBasicFS, Always, TestRun
1327 InitBasicFS, Always, TestLastFail
1328 [["rmdir"; "/new"]];
1329 InitBasicFS, Always, TestLastFail
1331 ["rmdir"; "/new"]]],
1332 "remove a directory",
1334 Remove the single directory C<path>.");
1336 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1337 [InitBasicFS, Always, TestOutputFalse
1339 ["mkdir"; "/new/foo"];
1340 ["touch"; "/new/foo/bar"];
1342 ["exists"; "/new"]]],
1343 "remove a file or directory recursively",
1345 Remove the file or directory C<path>, recursively removing the
1346 contents if its a directory. This is like the C<rm -rf> shell
1349 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1350 [InitBasicFS, Always, TestOutputTrue
1352 ["is_dir"; "/new"]];
1353 InitBasicFS, Always, TestLastFail
1354 [["mkdir"; "/new/foo/bar"]]],
1355 "create a directory",
1357 Create a directory named C<path>.");
1359 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1360 [InitBasicFS, Always, TestOutputTrue
1361 [["mkdir_p"; "/new/foo/bar"];
1362 ["is_dir"; "/new/foo/bar"]];
1363 InitBasicFS, Always, TestOutputTrue
1364 [["mkdir_p"; "/new/foo/bar"];
1365 ["is_dir"; "/new/foo"]];
1366 InitBasicFS, Always, TestOutputTrue
1367 [["mkdir_p"; "/new/foo/bar"];
1368 ["is_dir"; "/new"]];
1369 (* Regression tests for RHBZ#503133: *)
1370 InitBasicFS, Always, TestRun
1372 ["mkdir_p"; "/new"]];
1373 InitBasicFS, Always, TestLastFail
1375 ["mkdir_p"; "/new"]]],
1376 "create a directory and parents",
1378 Create a directory named C<path>, creating any parent directories
1379 as necessary. This is like the C<mkdir -p> shell command.");
1381 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1382 [], (* XXX Need stat command to test *)
1385 Change the mode (permissions) of C<path> to C<mode>. Only
1386 numeric modes are supported.
1388 I<Note>: When using this command from guestfish, C<mode>
1389 by default would be decimal, unless you prefix it with
1390 C<0> to get octal, ie. use C<0700> not C<700>.
1392 The mode actually set is affected by the umask.");
1394 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1395 [], (* XXX Need stat command to test *)
1396 "change file owner and group",
1398 Change the file owner to C<owner> and group to C<group>.
1400 Only numeric uid and gid are supported. If you want to use
1401 names, you will need to locate and parse the password file
1402 yourself (Augeas support makes this relatively easy).");
1404 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1405 [InitISOFS, Always, TestOutputTrue (
1406 [["exists"; "/empty"]]);
1407 InitISOFS, Always, TestOutputTrue (
1408 [["exists"; "/directory"]])],
1409 "test if file or directory exists",
1411 This returns C<true> if and only if there is a file, directory
1412 (or anything) with the given C<path> name.
1414 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1416 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1417 [InitISOFS, Always, TestOutputTrue (
1418 [["is_file"; "/known-1"]]);
1419 InitISOFS, Always, TestOutputFalse (
1420 [["is_file"; "/directory"]])],
1421 "test if file exists",
1423 This returns C<true> if and only if there is a file
1424 with the given C<path> name. Note that it returns false for
1425 other objects like directories.
1427 See also C<guestfs_stat>.");
1429 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1430 [InitISOFS, Always, TestOutputFalse (
1431 [["is_dir"; "/known-3"]]);
1432 InitISOFS, Always, TestOutputTrue (
1433 [["is_dir"; "/directory"]])],
1434 "test if file exists",
1436 This returns C<true> if and only if there is a directory
1437 with the given C<path> name. Note that it returns false for
1438 other objects like files.
1440 See also C<guestfs_stat>.");
1442 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1443 [InitEmpty, Always, TestOutputListOfDevices (
1444 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1445 ["pvcreate"; "/dev/sda1"];
1446 ["pvcreate"; "/dev/sda2"];
1447 ["pvcreate"; "/dev/sda3"];
1448 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1449 "create an LVM physical volume",
1451 This creates an LVM physical volume on the named C<device>,
1452 where C<device> should usually be a partition name such
1455 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1456 [InitEmpty, Always, TestOutputList (
1457 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458 ["pvcreate"; "/dev/sda1"];
1459 ["pvcreate"; "/dev/sda2"];
1460 ["pvcreate"; "/dev/sda3"];
1461 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1462 ["vgcreate"; "VG2"; "/dev/sda3"];
1463 ["vgs"]], ["VG1"; "VG2"])],
1464 "create an LVM volume group",
1466 This creates an LVM volume group called C<volgroup>
1467 from the non-empty list of physical volumes C<physvols>.");
1469 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1470 [InitEmpty, Always, TestOutputList (
1471 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1472 ["pvcreate"; "/dev/sda1"];
1473 ["pvcreate"; "/dev/sda2"];
1474 ["pvcreate"; "/dev/sda3"];
1475 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1476 ["vgcreate"; "VG2"; "/dev/sda3"];
1477 ["lvcreate"; "LV1"; "VG1"; "50"];
1478 ["lvcreate"; "LV2"; "VG1"; "50"];
1479 ["lvcreate"; "LV3"; "VG2"; "50"];
1480 ["lvcreate"; "LV4"; "VG2"; "50"];
1481 ["lvcreate"; "LV5"; "VG2"; "50"];
1483 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1484 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1485 "create an LVM logical volume",
1487 This creates an LVM logical volume called C<logvol>
1488 on the volume group C<volgroup>, with C<size> megabytes.");
1490 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1491 [InitEmpty, Always, TestOutput (
1492 [["part_disk"; "/dev/sda"; "mbr"];
1493 ["mkfs"; "ext2"; "/dev/sda1"];
1494 ["mount_options"; ""; "/dev/sda1"; "/"];
1495 ["write_file"; "/new"; "new file contents"; "0"];
1496 ["cat"; "/new"]], "new file contents")],
1497 "make a filesystem",
1499 This creates a filesystem on C<device> (usually a partition
1500 or LVM logical volume). The filesystem type is C<fstype>, for
1503 ("sfdisk", (RErr, [Device "device";
1504 Int "cyls"; Int "heads"; Int "sectors";
1505 StringList "lines"]), 43, [DangerWillRobinson],
1507 "create partitions on a block device",
1509 This is a direct interface to the L<sfdisk(8)> program for creating
1510 partitions on block devices.
1512 C<device> should be a block device, for example C</dev/sda>.
1514 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1515 and sectors on the device, which are passed directly to sfdisk as
1516 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1517 of these, then the corresponding parameter is omitted. Usually for
1518 'large' disks, you can just pass C<0> for these, but for small
1519 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1520 out the right geometry and you will need to tell it.
1522 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1523 information refer to the L<sfdisk(8)> manpage.
1525 To create a single partition occupying the whole disk, you would
1526 pass C<lines> as a single element list, when the single element being
1527 the string C<,> (comma).
1529 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1530 C<guestfs_part_init>");
1532 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1533 [InitBasicFS, Always, TestOutput (
1534 [["write_file"; "/new"; "new file contents"; "0"];
1535 ["cat"; "/new"]], "new file contents");
1536 InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1538 ["cat"; "/new"]], "\nnew file contents\n");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\n\n"; "0"];
1541 ["cat"; "/new"]], "\n\n");
1542 InitBasicFS, Always, TestOutput (
1543 [["write_file"; "/new"; ""; "0"];
1544 ["cat"; "/new"]], "");
1545 InitBasicFS, Always, TestOutput (
1546 [["write_file"; "/new"; "\n\n\n"; "0"];
1547 ["cat"; "/new"]], "\n\n\n");
1548 InitBasicFS, Always, TestOutput (
1549 [["write_file"; "/new"; "\n"; "0"];
1550 ["cat"; "/new"]], "\n")],
1553 This call creates a file called C<path>. The contents of the
1554 file is the string C<content> (which can contain any 8 bit data),
1555 with length C<size>.
1557 As a special case, if C<size> is C<0>
1558 then the length is calculated using C<strlen> (so in this case
1559 the content cannot contain embedded ASCII NULs).
1561 I<NB.> Owing to a bug, writing content containing ASCII NUL
1562 characters does I<not> work, even if the length is specified.
1563 We hope to resolve this bug in a future version. In the meantime
1564 use C<guestfs_upload>.");
1566 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567 [InitEmpty, Always, TestOutputListOfDevices (
1568 [["part_disk"; "/dev/sda"; "mbr"];
1569 ["mkfs"; "ext2"; "/dev/sda1"];
1570 ["mount_options"; ""; "/dev/sda1"; "/"];
1571 ["mounts"]], ["/dev/sda1"]);
1572 InitEmpty, Always, TestOutputList (
1573 [["part_disk"; "/dev/sda"; "mbr"];
1574 ["mkfs"; "ext2"; "/dev/sda1"];
1575 ["mount_options"; ""; "/dev/sda1"; "/"];
1578 "unmount a filesystem",
1580 This unmounts the given filesystem. The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1584 ("mounts", (RStringList "devices", []), 46, [],
1585 [InitBasicFS, Always, TestOutputListOfDevices (
1586 [["mounts"]], ["/dev/sda1"])],
1587 "show mounted filesystems",
1589 This returns the list of currently mounted filesystems. It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592 Some internal mounts are not shown.
1594 See also: C<guestfs_mountpoints>");
1596 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597 [InitBasicFS, Always, TestOutputList (
1600 (* check that umount_all can unmount nested mounts correctly: *)
1601 InitEmpty, Always, TestOutputList (
1602 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603 ["mkfs"; "ext2"; "/dev/sda1"];
1604 ["mkfs"; "ext2"; "/dev/sda2"];
1605 ["mkfs"; "ext2"; "/dev/sda3"];
1606 ["mount_options"; ""; "/dev/sda1"; "/"];
1608 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609 ["mkdir"; "/mp1/mp2"];
1610 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611 ["mkdir"; "/mp1/mp2/mp3"];
1614 "unmount all filesystems",
1616 This unmounts all mounted filesystems.
1618 Some internal mounts are not unmounted by this call.");
1620 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622 "remove all LVM LVs, VGs and PVs",
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1627 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628 [InitISOFS, Always, TestOutput (
1629 [["file"; "/empty"]], "empty");
1630 InitISOFS, Always, TestOutput (
1631 [["file"; "/known-1"]], "ASCII text");
1632 InitISOFS, Always, TestLastFail (
1633 [["file"; "/notexists"]])],
1634 "determine file type",
1636 This call uses the standard L<file(1)> command to determine
1637 the type or contents of the file. This also works on devices,
1638 for example to find out whether a partition contains a filesystem.
1640 This call will also transparently look inside various types
1643 The exact command which runs is C<file -zbsL path>. Note in
1644 particular that the filename is not prepended to the output
1645 (the C<-b> option).");
1647 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1648 [InitBasicFS, Always, TestOutput (
1649 [["upload"; "test-command"; "/test-command"];
1650 ["chmod"; "0o755"; "/test-command"];
1651 ["command"; "/test-command 1"]], "Result1");
1652 InitBasicFS, Always, TestOutput (
1653 [["upload"; "test-command"; "/test-command"];
1654 ["chmod"; "0o755"; "/test-command"];
1655 ["command"; "/test-command 2"]], "Result2\n");
1656 InitBasicFS, Always, TestOutput (
1657 [["upload"; "test-command"; "/test-command"];
1658 ["chmod"; "0o755"; "/test-command"];
1659 ["command"; "/test-command 3"]], "\nResult3");
1660 InitBasicFS, Always, TestOutput (
1661 [["upload"; "test-command"; "/test-command"];
1662 ["chmod"; "0o755"; "/test-command"];
1663 ["command"; "/test-command 4"]], "\nResult4\n");
1664 InitBasicFS, Always, TestOutput (
1665 [["upload"; "test-command"; "/test-command"];
1666 ["chmod"; "0o755"; "/test-command"];
1667 ["command"; "/test-command 5"]], "\nResult5\n\n");
1668 InitBasicFS, Always, TestOutput (
1669 [["upload"; "test-command"; "/test-command"];
1670 ["chmod"; "0o755"; "/test-command"];
1671 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1672 InitBasicFS, Always, TestOutput (
1673 [["upload"; "test-command"; "/test-command"];
1674 ["chmod"; "0o755"; "/test-command"];
1675 ["command"; "/test-command 7"]], "");
1676 InitBasicFS, Always, TestOutput (
1677 [["upload"; "test-command"; "/test-command"];
1678 ["chmod"; "0o755"; "/test-command"];
1679 ["command"; "/test-command 8"]], "\n");
1680 InitBasicFS, Always, TestOutput (
1681 [["upload"; "test-command"; "/test-command"];
1682 ["chmod"; "0o755"; "/test-command"];
1683 ["command"; "/test-command 9"]], "\n\n");
1684 InitBasicFS, Always, TestOutput (
1685 [["upload"; "test-command"; "/test-command"];
1686 ["chmod"; "0o755"; "/test-command"];
1687 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1688 InitBasicFS, Always, TestOutput (
1689 [["upload"; "test-command"; "/test-command"];
1690 ["chmod"; "0o755"; "/test-command"];
1691 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1692 InitBasicFS, Always, TestLastFail (
1693 [["upload"; "test-command"; "/test-command"];
1694 ["chmod"; "0o755"; "/test-command"];
1695 ["command"; "/test-command"]])],
1696 "run a command from the guest filesystem",
1698 This call runs a command from the guest filesystem. The
1699 filesystem must be mounted, and must contain a compatible
1700 operating system (ie. something Linux, with the same
1701 or compatible processor architecture).
1703 The single parameter is an argv-style list of arguments.
1704 The first element is the name of the program to run.
1705 Subsequent elements are parameters. The list must be
1706 non-empty (ie. must contain a program name). Note that
1707 the command runs directly, and is I<not> invoked via
1708 the shell (see C<guestfs_sh>).
1710 The return value is anything printed to I<stdout> by
1713 If the command returns a non-zero exit status, then
1714 this function returns an error message. The error message
1715 string is the content of I<stderr> from the command.
1717 The C<$PATH> environment variable will contain at least
1718 C</usr/bin> and C</bin>. If you require a program from
1719 another location, you should provide the full path in the
1722 Shared libraries and data files required by the program
1723 must be available on filesystems which are mounted in the
1724 correct places. It is the caller's responsibility to ensure
1725 all filesystems that are needed are mounted at the right
1728 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1729 [InitBasicFS, Always, TestOutputList (
1730 [["upload"; "test-command"; "/test-command"];
1731 ["chmod"; "0o755"; "/test-command"];
1732 ["command_lines"; "/test-command 1"]], ["Result1"]);
1733 InitBasicFS, Always, TestOutputList (
1734 [["upload"; "test-command"; "/test-command"];
1735 ["chmod"; "0o755"; "/test-command"];
1736 ["command_lines"; "/test-command 2"]], ["Result2"]);
1737 InitBasicFS, Always, TestOutputList (
1738 [["upload"; "test-command"; "/test-command"];
1739 ["chmod"; "0o755"; "/test-command"];
1740 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1741 InitBasicFS, Always, TestOutputList (
1742 [["upload"; "test-command"; "/test-command"];
1743 ["chmod"; "0o755"; "/test-command"];
1744 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1745 InitBasicFS, Always, TestOutputList (
1746 [["upload"; "test-command"; "/test-command"];
1747 ["chmod"; "0o755"; "/test-command"];
1748 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1749 InitBasicFS, Always, TestOutputList (
1750 [["upload"; "test-command"; "/test-command"];
1751 ["chmod"; "0o755"; "/test-command"];
1752 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1753 InitBasicFS, Always, TestOutputList (
1754 [["upload"; "test-command"; "/test-command"];
1755 ["chmod"; "0o755"; "/test-command"];
1756 ["command_lines"; "/test-command 7"]], []);
1757 InitBasicFS, Always, TestOutputList (
1758 [["upload"; "test-command"; "/test-command"];
1759 ["chmod"; "0o755"; "/test-command"];
1760 ["command_lines"; "/test-command 8"]], [""]);
1761 InitBasicFS, Always, TestOutputList (
1762 [["upload"; "test-command"; "/test-command"];
1763 ["chmod"; "0o755"; "/test-command"];
1764 ["command_lines"; "/test-command 9"]], ["";""]);
1765 InitBasicFS, Always, TestOutputList (
1766 [["upload"; "test-command"; "/test-command"];
1767 ["chmod"; "0o755"; "/test-command"];
1768 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1769 InitBasicFS, Always, TestOutputList (
1770 [["upload"; "test-command"; "/test-command"];
1771 ["chmod"; "0o755"; "/test-command"];
1772 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1773 "run a command, returning lines",
1775 This is the same as C<guestfs_command>, but splits the
1776 result into a list of lines.
1778 See also: C<guestfs_sh_lines>");
1780 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1781 [InitISOFS, Always, TestOutputStruct (
1782 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783 "get file information",
1785 Returns file information for the given C<path>.
1787 This is the same as the C<stat(2)> system call.");
1789 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1790 [InitISOFS, Always, TestOutputStruct (
1791 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1792 "get file information for a symbolic link",
1794 Returns file information for the given C<path>.
1796 This is the same as C<guestfs_stat> except that if C<path>
1797 is a symbolic link, then the link is stat-ed, not the file it
1800 This is the same as the C<lstat(2)> system call.");
1802 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1803 [InitISOFS, Always, TestOutputStruct (
1804 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1805 "get file system statistics",
1807 Returns file system statistics for any mounted file system.
1808 C<path> should be a file or directory in the mounted file system
1809 (typically it is the mount point itself, but it doesn't need to be).
1811 This is the same as the C<statvfs(2)> system call.");
1813 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1815 "get ext2/ext3/ext4 superblock details",
1817 This returns the contents of the ext2, ext3 or ext4 filesystem
1818 superblock on C<device>.
1820 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1821 manpage for more details. The list of fields returned isn't
1822 clearly defined, and depends on both the version of C<tune2fs>
1823 that libguestfs was built against, and the filesystem itself.");
1825 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1826 [InitEmpty, Always, TestOutputTrue (
1827 [["blockdev_setro"; "/dev/sda"];
1828 ["blockdev_getro"; "/dev/sda"]])],
1829 "set block device to read-only",
1831 Sets the block device named C<device> to read-only.
1833 This uses the L<blockdev(8)> command.");
1835 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1836 [InitEmpty, Always, TestOutputFalse (
1837 [["blockdev_setrw"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "set block device to read-write",
1841 Sets the block device named C<device> to read-write.
1843 This uses the L<blockdev(8)> command.");
1845 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1846 [InitEmpty, Always, TestOutputTrue (
1847 [["blockdev_setro"; "/dev/sda"];
1848 ["blockdev_getro"; "/dev/sda"]])],
1849 "is block device set to read-only",
1851 Returns a boolean indicating if the block device is read-only
1852 (true if read-only, false if not).
1854 This uses the L<blockdev(8)> command.");
1856 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1857 [InitEmpty, Always, TestOutputInt (
1858 [["blockdev_getss"; "/dev/sda"]], 512)],
1859 "get sectorsize of block device",
1861 This returns the size of sectors on a block device.
1862 Usually 512, but can be larger for modern devices.
1864 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1867 This uses the L<blockdev(8)> command.");
1869 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1870 [InitEmpty, Always, TestOutputInt (
1871 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1872 "get blocksize of block device",
1874 This returns the block size of a device.
1876 (Note this is different from both I<size in blocks> and
1877 I<filesystem block size>).
1879 This uses the L<blockdev(8)> command.");
1881 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1883 "set blocksize of block device",
1885 This sets the block size of a device.
1887 (Note this is different from both I<size in blocks> and
1888 I<filesystem block size>).
1890 This uses the L<blockdev(8)> command.");
1892 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1893 [InitEmpty, Always, TestOutputInt (
1894 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1895 "get total size of device in 512-byte sectors",
1897 This returns the size of the device in units of 512-byte sectors
1898 (even if the sectorsize isn't 512 bytes ... weird).
1900 See also C<guestfs_blockdev_getss> for the real sector size of
1901 the device, and C<guestfs_blockdev_getsize64> for the more
1902 useful I<size in bytes>.
1904 This uses the L<blockdev(8)> command.");
1906 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1907 [InitEmpty, Always, TestOutputInt (
1908 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1909 "get total size of device in bytes",
1911 This returns the size of the device in bytes.
1913 See also C<guestfs_blockdev_getsz>.
1915 This uses the L<blockdev(8)> command.");
1917 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1918 [InitEmpty, Always, TestRun
1919 [["blockdev_flushbufs"; "/dev/sda"]]],
1920 "flush device buffers",
1922 This tells the kernel to flush internal buffers associated
1925 This uses the L<blockdev(8)> command.");
1927 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1928 [InitEmpty, Always, TestRun
1929 [["blockdev_rereadpt"; "/dev/sda"]]],
1930 "reread partition table",
1932 Reread the partition table on C<device>.
1934 This uses the L<blockdev(8)> command.");
1936 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1937 [InitBasicFS, Always, TestOutput (
1938 (* Pick a file from cwd which isn't likely to change. *)
1939 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1940 ["checksum"; "md5"; "/COPYING.LIB"]],
1941 Digest.to_hex (Digest.file "COPYING.LIB"))],
1942 "upload a file from the local machine",
1944 Upload local file C<filename> to C<remotefilename> on the
1947 C<filename> can also be a named pipe.
1949 See also C<guestfs_download>.");
1951 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1952 [InitBasicFS, Always, TestOutput (
1953 (* Pick a file from cwd which isn't likely to change. *)
1954 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1955 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1956 ["upload"; "testdownload.tmp"; "/upload"];
1957 ["checksum"; "md5"; "/upload"]],
1958 Digest.to_hex (Digest.file "COPYING.LIB"))],
1959 "download a file to the local machine",
1961 Download file C<remotefilename> and save it as C<filename>
1962 on the local machine.
1964 C<filename> can also be a named pipe.
1966 See also C<guestfs_upload>, C<guestfs_cat>.");
1968 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1969 [InitISOFS, Always, TestOutput (
1970 [["checksum"; "crc"; "/known-3"]], "2891671662");
1971 InitISOFS, Always, TestLastFail (
1972 [["checksum"; "crc"; "/notexists"]]);
1973 InitISOFS, Always, TestOutput (
1974 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1975 InitISOFS, Always, TestOutput (
1976 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1977 InitISOFS, Always, TestOutput (
1978 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1979 InitISOFS, Always, TestOutput (
1980 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1981 InitISOFS, Always, TestOutput (
1982 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1983 InitISOFS, Always, TestOutput (
1984 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1985 "compute MD5, SHAx or CRC checksum of file",
1987 This call computes the MD5, SHAx or CRC checksum of the
1990 The type of checksum to compute is given by the C<csumtype>
1991 parameter which must have one of the following values:
1997 Compute the cyclic redundancy check (CRC) specified by POSIX
1998 for the C<cksum> command.
2002 Compute the MD5 hash (using the C<md5sum> program).
2006 Compute the SHA1 hash (using the C<sha1sum> program).
2010 Compute the SHA224 hash (using the C<sha224sum> program).
2014 Compute the SHA256 hash (using the C<sha256sum> program).
2018 Compute the SHA384 hash (using the C<sha384sum> program).
2022 Compute the SHA512 hash (using the C<sha512sum> program).
2026 The checksum is returned as a printable string.");
2028 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2029 [InitBasicFS, Always, TestOutput (
2030 [["tar_in"; "../images/helloworld.tar"; "/"];
2031 ["cat"; "/hello"]], "hello\n")],
2032 "unpack tarfile to directory",
2034 This command uploads and unpacks local file C<tarfile> (an
2035 I<uncompressed> tar file) into C<directory>.
2037 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2039 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2041 "pack directory into tarfile",
2043 This command packs the contents of C<directory> and downloads
2044 it to local file C<tarfile>.
2046 To download a compressed tarball, use C<guestfs_tgz_out>.");
2048 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2049 [InitBasicFS, Always, TestOutput (
2050 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2051 ["cat"; "/hello"]], "hello\n")],
2052 "unpack compressed tarball to directory",
2054 This command uploads and unpacks local file C<tarball> (a
2055 I<gzip compressed> tar file) into C<directory>.
2057 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2059 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2061 "pack directory into compressed tarball",
2063 This command packs the contents of C<directory> and downloads
2064 it to local file C<tarball>.
2066 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2068 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2069 [InitBasicFS, Always, TestLastFail (
2071 ["mount_ro"; "/dev/sda1"; "/"];
2072 ["touch"; "/new"]]);
2073 InitBasicFS, Always, TestOutput (
2074 [["write_file"; "/new"; "data"; "0"];
2076 ["mount_ro"; "/dev/sda1"; "/"];
2077 ["cat"; "/new"]], "data")],
2078 "mount a guest disk, read-only",
2080 This is the same as the C<guestfs_mount> command, but it
2081 mounts the filesystem with the read-only (I<-o ro>) flag.");
2083 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2085 "mount a guest disk with mount options",
2087 This is the same as the C<guestfs_mount> command, but it
2088 allows you to set the mount options as for the
2089 L<mount(8)> I<-o> flag.
2091 If the C<options> parameter is an empty string, then
2092 no options are passed (all options default to whatever
2093 the filesystem uses).");
2095 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097 "mount a guest disk with mount options and vfstype",
2099 This is the same as the C<guestfs_mount> command, but it
2100 allows you to set both the mount options and the vfstype
2101 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105 "debugging and internals",
2107 The C<guestfs_debug> command exposes some internals of
2108 C<guestfsd> (the guestfs daemon) that runs inside the
2111 There is no comprehensive help for this command. You have
2112 to look at the file C<daemon/debug.c> in the libguestfs source
2113 to find out what you can do.");
2115 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2116 [InitEmpty, Always, TestOutputList (
2117 [["part_disk"; "/dev/sda"; "mbr"];
2118 ["pvcreate"; "/dev/sda1"];
2119 ["vgcreate"; "VG"; "/dev/sda1"];
2120 ["lvcreate"; "LV1"; "VG"; "50"];
2121 ["lvcreate"; "LV2"; "VG"; "50"];
2122 ["lvremove"; "/dev/VG/LV1"];
2123 ["lvs"]], ["/dev/VG/LV2"]);
2124 InitEmpty, Always, TestOutputList (
2125 [["part_disk"; "/dev/sda"; "mbr"];
2126 ["pvcreate"; "/dev/sda1"];
2127 ["vgcreate"; "VG"; "/dev/sda1"];
2128 ["lvcreate"; "LV1"; "VG"; "50"];
2129 ["lvcreate"; "LV2"; "VG"; "50"];
2130 ["lvremove"; "/dev/VG"];
2132 InitEmpty, Always, TestOutputList (
2133 [["part_disk"; "/dev/sda"; "mbr"];
2134 ["pvcreate"; "/dev/sda1"];
2135 ["vgcreate"; "VG"; "/dev/sda1"];
2136 ["lvcreate"; "LV1"; "VG"; "50"];
2137 ["lvcreate"; "LV2"; "VG"; "50"];
2138 ["lvremove"; "/dev/VG"];
2140 "remove an LVM logical volume",
2142 Remove an LVM logical volume C<device>, where C<device> is
2143 the path to the LV, such as C</dev/VG/LV>.
2145 You can also remove all LVs in a volume group by specifying
2146 the VG name, C</dev/VG>.");
2148 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2149 [InitEmpty, Always, TestOutputList (
2150 [["part_disk"; "/dev/sda"; "mbr"];
2151 ["pvcreate"; "/dev/sda1"];
2152 ["vgcreate"; "VG"; "/dev/sda1"];
2153 ["lvcreate"; "LV1"; "VG"; "50"];
2154 ["lvcreate"; "LV2"; "VG"; "50"];
2157 InitEmpty, Always, TestOutputList (
2158 [["part_disk"; "/dev/sda"; "mbr"];
2159 ["pvcreate"; "/dev/sda1"];
2160 ["vgcreate"; "VG"; "/dev/sda1"];
2161 ["lvcreate"; "LV1"; "VG"; "50"];
2162 ["lvcreate"; "LV2"; "VG"; "50"];
2165 "remove an LVM volume group",
2167 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169 This also forcibly removes all logical volumes in the volume
2172 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2173 [InitEmpty, Always, TestOutputListOfDevices (
2174 [["part_disk"; "/dev/sda"; "mbr"];
2175 ["pvcreate"; "/dev/sda1"];
2176 ["vgcreate"; "VG"; "/dev/sda1"];
2177 ["lvcreate"; "LV1"; "VG"; "50"];
2178 ["lvcreate"; "LV2"; "VG"; "50"];
2180 ["pvremove"; "/dev/sda1"];
2182 InitEmpty, Always, TestOutputListOfDevices (
2183 [["part_disk"; "/dev/sda"; "mbr"];
2184 ["pvcreate"; "/dev/sda1"];
2185 ["vgcreate"; "VG"; "/dev/sda1"];
2186 ["lvcreate"; "LV1"; "VG"; "50"];
2187 ["lvcreate"; "LV2"; "VG"; "50"];
2189 ["pvremove"; "/dev/sda1"];
2191 InitEmpty, Always, TestOutputListOfDevices (
2192 [["part_disk"; "/dev/sda"; "mbr"];
2193 ["pvcreate"; "/dev/sda1"];
2194 ["vgcreate"; "VG"; "/dev/sda1"];
2195 ["lvcreate"; "LV1"; "VG"; "50"];
2196 ["lvcreate"; "LV2"; "VG"; "50"];
2198 ["pvremove"; "/dev/sda1"];
2200 "remove an LVM physical volume",
2202 This wipes a physical volume C<device> so that LVM will no longer
2205 The implementation uses the C<pvremove> command which refuses to
2206 wipe physical volumes that contain any volume groups, so you have
2207 to remove those first.");
2209 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2210 [InitBasicFS, Always, TestOutput (
2211 [["set_e2label"; "/dev/sda1"; "testlabel"];
2212 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2213 "set the ext2/3/4 filesystem label",
2215 This sets the ext2/3/4 filesystem label of the filesystem on
2216 C<device> to C<label>. Filesystem labels are limited to
2219 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2220 to return the existing label on a filesystem.");
2222 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224 "get the ext2/3/4 filesystem label",
2226 This returns the ext2/3/4 filesystem label of the filesystem on
2229 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2230 (let uuid = uuidgen () in
2231 [InitBasicFS, Always, TestOutput (
2232 [["set_e2uuid"; "/dev/sda1"; uuid];
2233 ["get_e2uuid"; "/dev/sda1"]], uuid);
2234 InitBasicFS, Always, TestOutput (
2235 [["set_e2uuid"; "/dev/sda1"; "clear"];
2236 ["get_e2uuid"; "/dev/sda1"]], "");
2237 (* We can't predict what UUIDs will be, so just check the commands run. *)
2238 InitBasicFS, Always, TestRun (
2239 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2240 InitBasicFS, Always, TestRun (
2241 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2242 "set the ext2/3/4 filesystem UUID",
2244 This sets the ext2/3/4 filesystem UUID of the filesystem on
2245 C<device> to C<uuid>. The format of the UUID and alternatives
2246 such as C<clear>, C<random> and C<time> are described in the
2247 L<tune2fs(8)> manpage.
2249 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2250 to return the existing UUID of a filesystem.");
2252 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254 "get the ext2/3/4 filesystem UUID",
2256 This returns the ext2/3/4 filesystem UUID of the filesystem on
2259 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2260 [InitBasicFS, Always, TestOutputInt (
2261 [["umount"; "/dev/sda1"];
2262 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2263 InitBasicFS, Always, TestOutputInt (
2264 [["umount"; "/dev/sda1"];
2265 ["zero"; "/dev/sda1"];
2266 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2267 "run the filesystem checker",
2269 This runs the filesystem checker (fsck) on C<device> which
2270 should have filesystem type C<fstype>.
2272 The returned integer is the status. See L<fsck(8)> for the
2273 list of status codes from C<fsck>.
2281 Multiple status codes can be summed together.
2285 A non-zero return code can mean \"success\", for example if
2286 errors have been corrected on the filesystem.
2290 Checking or repairing NTFS volumes is not supported
2295 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297 ("zero", (RErr, [Device "device"]), 85, [],
2298 [InitBasicFS, Always, TestOutput (
2299 [["umount"; "/dev/sda1"];
2300 ["zero"; "/dev/sda1"];
2301 ["file"; "/dev/sda1"]], "data")],
2302 "write zeroes to the device",
2304 This command writes zeroes over the first few blocks of C<device>.
2306 How many blocks are zeroed isn't specified (but it's I<not> enough
2307 to securely wipe the device). It should be sufficient to remove
2308 any partition tables, filesystem superblocks and so on.
2310 See also: C<guestfs_scrub_device>.");
2312 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2313 (* Test disabled because grub-install incompatible with virtio-blk driver.
2314 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316 [InitBasicFS, Disabled, TestOutputTrue (
2317 [["grub_install"; "/"; "/dev/sda1"];
2318 ["is_dir"; "/boot"]])],
2321 This command installs GRUB (the Grand Unified Bootloader) on
2322 C<device>, with the root directory being C<root>.");
2324 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2325 [InitBasicFS, Always, TestOutput (
2326 [["write_file"; "/old"; "file content"; "0"];
2327 ["cp"; "/old"; "/new"];
2328 ["cat"; "/new"]], "file content");
2329 InitBasicFS, Always, TestOutputTrue (
2330 [["write_file"; "/old"; "file content"; "0"];
2331 ["cp"; "/old"; "/new"];
2332 ["is_file"; "/old"]]);
2333 InitBasicFS, Always, TestOutput (
2334 [["write_file"; "/old"; "file content"; "0"];
2336 ["cp"; "/old"; "/dir/new"];
2337 ["cat"; "/dir/new"]], "file content")],
2340 This copies a file from C<src> to C<dest> where C<dest> is
2341 either a destination filename or destination directory.");
2343 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2344 [InitBasicFS, Always, TestOutput (
2345 [["mkdir"; "/olddir"];
2346 ["mkdir"; "/newdir"];
2347 ["write_file"; "/olddir/file"; "file content"; "0"];
2348 ["cp_a"; "/olddir"; "/newdir"];
2349 ["cat"; "/newdir/olddir/file"]], "file content")],
2350 "copy a file or directory recursively",
2352 This copies a file or directory from C<src> to C<dest>
2353 recursively using the C<cp -a> command.");
2355 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2356 [InitBasicFS, Always, TestOutput (
2357 [["write_file"; "/old"; "file content"; "0"];
2358 ["mv"; "/old"; "/new"];
2359 ["cat"; "/new"]], "file content");
2360 InitBasicFS, Always, TestOutputFalse (
2361 [["write_file"; "/old"; "file content"; "0"];
2362 ["mv"; "/old"; "/new"];
2363 ["is_file"; "/old"]])],
2366 This moves a file from C<src> to C<dest> where C<dest> is
2367 either a destination filename or destination directory.");
2369 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2370 [InitEmpty, Always, TestRun (
2371 [["drop_caches"; "3"]])],
2372 "drop kernel page cache, dentries and inodes",
2374 This instructs the guest kernel to drop its page cache,
2375 and/or dentries and inode caches. The parameter C<whattodrop>
2376 tells the kernel what precisely to drop, see
2377 L<http://linux-mm.org/Drop_Caches>
2379 Setting C<whattodrop> to 3 should drop everything.
2381 This automatically calls L<sync(2)> before the operation,
2382 so that the maximum guest memory is freed.");
2384 ("dmesg", (RString "kmsgs", []), 91, [],
2385 [InitEmpty, Always, TestRun (
2387 "return kernel messages",
2389 This returns the kernel messages (C<dmesg> output) from
2390 the guest kernel. This is sometimes useful for extended
2391 debugging of problems.
2393 Another way to get the same information is to enable
2394 verbose messages with C<guestfs_set_verbose> or by setting
2395 the environment variable C<LIBGUESTFS_DEBUG=1> before
2396 running the program.");
2398 ("ping_daemon", (RErr, []), 92, [],
2399 [InitEmpty, Always, TestRun (
2400 [["ping_daemon"]])],
2401 "ping the guest daemon",
2403 This is a test probe into the guestfs daemon running inside
2404 the qemu subprocess. Calling this function checks that the
2405 daemon responds to the ping message, without affecting the daemon
2406 or attached block device(s) in any other way.");
2408 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2409 [InitBasicFS, Always, TestOutputTrue (
2410 [["write_file"; "/file1"; "contents of a file"; "0"];
2411 ["cp"; "/file1"; "/file2"];
2412 ["equal"; "/file1"; "/file2"]]);
2413 InitBasicFS, Always, TestOutputFalse (
2414 [["write_file"; "/file1"; "contents of a file"; "0"];
2415 ["write_file"; "/file2"; "contents of another file"; "0"];
2416 ["equal"; "/file1"; "/file2"]]);
2417 InitBasicFS, Always, TestLastFail (
2418 [["equal"; "/file1"; "/file2"]])],
2419 "test if two files have equal contents",
2421 This compares the two files C<file1> and C<file2> and returns
2422 true if their content is exactly equal, or false otherwise.
2424 The external L<cmp(1)> program is used for the comparison.");
2426 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2427 [InitISOFS, Always, TestOutputList (
2428 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2429 InitISOFS, Always, TestOutputList (
2430 [["strings"; "/empty"]], [])],
2431 "print the printable strings in a file",
2433 This runs the L<strings(1)> command on a file and returns
2434 the list of printable strings found.");
2436 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2437 [InitISOFS, Always, TestOutputList (
2438 [["strings_e"; "b"; "/known-5"]], []);
2439 InitBasicFS, Disabled, TestOutputList (
2440 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2441 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2442 "print the printable strings in a file",
2444 This is like the C<guestfs_strings> command, but allows you to
2445 specify the encoding.
2447 See the L<strings(1)> manpage for the full list of encodings.
2449 Commonly useful encodings are C<l> (lower case L) which will
2450 show strings inside Windows/x86 files.
2452 The returned strings are transcoded to UTF-8.");
2454 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2455 [InitISOFS, Always, TestOutput (
2456 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2457 (* Test for RHBZ#501888c2 regression which caused large hexdump
2458 * commands to segfault.
2460 InitISOFS, Always, TestRun (
2461 [["hexdump"; "/100krandom"]])],
2462 "dump a file in hexadecimal",
2464 This runs C<hexdump -C> on the given C<path>. The result is
2465 the human-readable, canonical hex dump of the file.");
2467 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2468 [InitNone, Always, TestOutput (
2469 [["part_disk"; "/dev/sda"; "mbr"];
2470 ["mkfs"; "ext3"; "/dev/sda1"];
2471 ["mount_options"; ""; "/dev/sda1"; "/"];
2472 ["write_file"; "/new"; "test file"; "0"];
2473 ["umount"; "/dev/sda1"];
2474 ["zerofree"; "/dev/sda1"];
2475 ["mount_options"; ""; "/dev/sda1"; "/"];
2476 ["cat"; "/new"]], "test file")],
2477 "zero unused inodes and disk blocks on ext2/3 filesystem",
2479 This runs the I<zerofree> program on C<device>. This program
2480 claims to zero unused inodes and disk blocks on an ext2/3
2481 filesystem, thus making it possible to compress the filesystem
2484 You should B<not> run this program if the filesystem is
2487 It is possible that using this program can damage the filesystem
2488 or data on the filesystem.");
2490 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2492 "resize an LVM physical volume",
2494 This resizes (expands or shrinks) an existing LVM physical
2495 volume to match the new size of the underlying device.");
2497 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2498 Int "cyls"; Int "heads"; Int "sectors";
2499 String "line"]), 99, [DangerWillRobinson],
2501 "modify a single partition on a block device",
2503 This runs L<sfdisk(8)> option to modify just the single
2504 partition C<n> (note: C<n> counts from 1).
2506 For other parameters, see C<guestfs_sfdisk>. You should usually
2507 pass C<0> for the cyls/heads/sectors parameters.
2509 See also: C<guestfs_part_add>");
2511 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2513 "display the partition table",
2515 This displays the partition table on C<device>, in the
2516 human-readable output of the L<sfdisk(8)> command. It is
2517 not intended to be parsed.
2519 See also: C<guestfs_part_list>");
2521 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2523 "display the kernel geometry",
2525 This displays the kernel's idea of the geometry of C<device>.
2527 The result is in human-readable format, and not designed to
2530 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2532 "display the disk geometry from the partition table",
2534 This displays the disk geometry of C<device> read from the
2535 partition table. Especially in the case where the underlying
2536 block device has been resized, this can be different from the
2537 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2539 The result is in human-readable format, and not designed to
2542 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2544 "activate or deactivate all volume groups",
2546 This command activates or (if C<activate> is false) deactivates
2547 all logical volumes in all volume groups.
2548 If activated, then they are made known to the
2549 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2550 then those devices disappear.
2552 This command is the same as running C<vgchange -a y|n>");
2554 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2556 "activate or deactivate some volume groups",
2558 This command activates or (if C<activate> is false) deactivates
2559 all logical volumes in the listed volume groups C<volgroups>.
2560 If activated, then they are made known to the
2561 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2562 then those devices disappear.
2564 This command is the same as running C<vgchange -a y|n volgroups...>
2566 Note that if C<volgroups> is an empty list then B<all> volume groups
2567 are activated or deactivated.");
2569 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2570 [InitNone, Always, TestOutput (
2571 [["part_disk"; "/dev/sda"; "mbr"];
2572 ["pvcreate"; "/dev/sda1"];
2573 ["vgcreate"; "VG"; "/dev/sda1"];
2574 ["lvcreate"; "LV"; "VG"; "10"];
2575 ["mkfs"; "ext2"; "/dev/VG/LV"];
2576 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2577 ["write_file"; "/new"; "test content"; "0"];
2579 ["lvresize"; "/dev/VG/LV"; "20"];
2580 ["e2fsck_f"; "/dev/VG/LV"];
2581 ["resize2fs"; "/dev/VG/LV"];
2582 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2583 ["cat"; "/new"]], "test content");
2584 InitNone, Always, TestRun (
2585 (* Make an LV smaller to test RHBZ#587484. *)
2586 [["part_disk"; "/dev/sda"; "mbr"];
2587 ["pvcreate"; "/dev/sda1"];
2588 ["vgcreate"; "VG"; "/dev/sda1"];
2589 ["lvcreate"; "LV"; "VG"; "20"];
2590 ["lvresize"; "/dev/VG/LV"; "10"]])],
2591 "resize an LVM logical volume",
2593 This resizes (expands or shrinks) an existing LVM logical
2594 volume to C<mbytes>. When reducing, data in the reduced part
2597 ("resize2fs", (RErr, [Device "device"]), 106, [],
2598 [], (* lvresize tests this *)
2599 "resize an ext2/ext3 filesystem",
2601 This resizes an ext2 or ext3 filesystem to match the size of
2602 the underlying device.
2604 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2605 on the C<device> before calling this command. For unknown reasons
2606 C<resize2fs> sometimes gives an error about this and sometimes not.
2607 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2608 calling this function.");
2610 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2611 [InitBasicFS, Always, TestOutputList (
2612 [["find"; "/"]], ["lost+found"]);
2613 InitBasicFS, Always, TestOutputList (
2617 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2618 InitBasicFS, Always, TestOutputList (
2619 [["mkdir_p"; "/a/b/c"];
2620 ["touch"; "/a/b/c/d"];
2621 ["find"; "/a/b/"]], ["c"; "c/d"])],
2622 "find all files and directories",
2624 This command lists out all files and directories, recursively,
2625 starting at C<directory>. It is essentially equivalent to
2626 running the shell command C<find directory -print> but some
2627 post-processing happens on the output, described below.
2629 This returns a list of strings I<without any prefix>. Thus
2630 if the directory structure was:
2636 then the returned list from C<guestfs_find> C</tmp> would be
2644 If C<directory> is not a directory, then this command returns
2647 The returned list is sorted.
2649 See also C<guestfs_find0>.");
2651 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2652 [], (* lvresize tests this *)
2653 "check an ext2/ext3 filesystem",
2655 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2656 filesystem checker on C<device>, noninteractively (C<-p>),
2657 even if the filesystem appears to be clean (C<-f>).
2659 This command is only needed because of C<guestfs_resize2fs>
2660 (q.v.). Normally you should use C<guestfs_fsck>.");
2662 ("sleep", (RErr, [Int "secs"]), 109, [],
2663 [InitNone, Always, TestRun (
2665 "sleep for some seconds",
2667 Sleep for C<secs> seconds.");
2669 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2670 [InitNone, Always, TestOutputInt (
2671 [["part_disk"; "/dev/sda"; "mbr"];
2672 ["mkfs"; "ntfs"; "/dev/sda1"];
2673 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2674 InitNone, Always, TestOutputInt (
2675 [["part_disk"; "/dev/sda"; "mbr"];
2676 ["mkfs"; "ext2"; "/dev/sda1"];
2677 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2678 "probe NTFS volume",
2680 This command runs the L<ntfs-3g.probe(8)> command which probes
2681 an NTFS C<device> for mountability. (Not all NTFS volumes can
2682 be mounted read-write, and some cannot be mounted at all).
2684 C<rw> is a boolean flag. Set it to true if you want to test
2685 if the volume can be mounted read-write. Set it to false if
2686 you want to test if the volume can be mounted read-only.
2688 The return value is an integer which C<0> if the operation
2689 would succeed, or some non-zero value documented in the
2690 L<ntfs-3g.probe(8)> manual page.");
2692 ("sh", (RString "output", [String "command"]), 111, [],
2693 [], (* XXX needs tests *)
2694 "run a command via the shell",
2696 This call runs a command from the guest filesystem via the
2699 This is like C<guestfs_command>, but passes the command to:
2701 /bin/sh -c \"command\"
2703 Depending on the guest's shell, this usually results in
2704 wildcards being expanded, shell expressions being interpolated
2707 All the provisos about C<guestfs_command> apply to this call.");
2709 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2710 [], (* XXX needs tests *)
2711 "run a command via the shell returning lines",
2713 This is the same as C<guestfs_sh>, but splits the result
2714 into a list of lines.
2716 See also: C<guestfs_command_lines>");
2718 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2719 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2720 * code in stubs.c, since all valid glob patterns must start with "/".
2721 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2723 [InitBasicFS, Always, TestOutputList (
2724 [["mkdir_p"; "/a/b/c"];
2725 ["touch"; "/a/b/c/d"];
2726 ["touch"; "/a/b/c/e"];
2727 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2728 InitBasicFS, Always, TestOutputList (
2729 [["mkdir_p"; "/a/b/c"];
2730 ["touch"; "/a/b/c/d"];
2731 ["touch"; "/a/b/c/e"];
2732 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2733 InitBasicFS, Always, TestOutputList (
2734 [["mkdir_p"; "/a/b/c"];
2735 ["touch"; "/a/b/c/d"];
2736 ["touch"; "/a/b/c/e"];
2737 ["glob_expand"; "/a/*/x/*"]], [])],
2738 "expand a wildcard path",
2740 This command searches for all the pathnames matching
2741 C<pattern> according to the wildcard expansion rules
2744 If no paths match, then this returns an empty list
2745 (note: not an error).
2747 It is just a wrapper around the C L<glob(3)> function
2748 with flags C<GLOB_MARK|GLOB_BRACE>.
2749 See that manual page for more details.");
2751 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2752 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2753 [["scrub_device"; "/dev/sdc"]])],
2754 "scrub (securely wipe) a device",
2756 This command writes patterns over C<device> to make data retrieval
2759 It is an interface to the L<scrub(1)> program. See that
2760 manual page for more details.");
2762 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2763 [InitBasicFS, Always, TestRun (
2764 [["write_file"; "/file"; "content"; "0"];
2765 ["scrub_file"; "/file"]])],
2766 "scrub (securely wipe) a file",
2768 This command writes patterns over a file to make data retrieval
2771 The file is I<removed> after scrubbing.
2773 It is an interface to the L<scrub(1)> program. See that
2774 manual page for more details.");
2776 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2777 [], (* XXX needs testing *)
2778 "scrub (securely wipe) free space",
2780 This command creates the directory C<dir> and then fills it
2781 with files until the filesystem is full, and scrubs the files
2782 as for C<guestfs_scrub_file>, and deletes them.
2783 The intention is to scrub any free space on the partition
2786 It is an interface to the L<scrub(1)> program. See that
2787 manual page for more details.");
2789 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2790 [InitBasicFS, Always, TestRun (
2792 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2793 "create a temporary directory",
2795 This command creates a temporary directory. The
2796 C<template> parameter should be a full pathname for the
2797 temporary directory name with the final six characters being
2800 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2801 the second one being suitable for Windows filesystems.
2803 The name of the temporary directory that was created
2806 The temporary directory is created with mode 0700
2807 and is owned by root.
2809 The caller is responsible for deleting the temporary
2810 directory and its contents after use.
2812 See also: L<mkdtemp(3)>");
2814 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2815 [InitISOFS, Always, TestOutputInt (
2816 [["wc_l"; "/10klines"]], 10000)],
2817 "count lines in a file",
2819 This command counts the lines in a file, using the
2820 C<wc -l> external command.");
2822 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2823 [InitISOFS, Always, TestOutputInt (
2824 [["wc_w"; "/10klines"]], 10000)],
2825 "count words in a file",
2827 This command counts the words in a file, using the
2828 C<wc -w> external command.");
2830 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2831 [InitISOFS, Always, TestOutputInt (
2832 [["wc_c"; "/100kallspaces"]], 102400)],
2833 "count characters in a file",
2835 This command counts the characters in a file, using the
2836 C<wc -c> external command.");
2838 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2839 [InitISOFS, Always, TestOutputList (
2840 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2841 "return first 10 lines of a file",
2843 This command returns up to the first 10 lines of a file as
2844 a list of strings.");
2846 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2847 [InitISOFS, Always, TestOutputList (
2848 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2849 InitISOFS, Always, TestOutputList (
2850 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2851 InitISOFS, Always, TestOutputList (
2852 [["head_n"; "0"; "/10klines"]], [])],
2853 "return first N lines of a file",
2855 If the parameter C<nrlines> is a positive number, this returns the first
2856 C<nrlines> lines of the file C<path>.
2858 If the parameter C<nrlines> is a negative number, this returns lines
2859 from the file C<path>, excluding the last C<nrlines> lines.
2861 If the parameter C<nrlines> is zero, this returns an empty list.");
2863 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2864 [InitISOFS, Always, TestOutputList (
2865 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2866 "return last 10 lines of a file",
2868 This command returns up to the last 10 lines of a file as
2869 a list of strings.");
2871 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2872 [InitISOFS, Always, TestOutputList (
2873 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2874 InitISOFS, Always, TestOutputList (
2875 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2876 InitISOFS, Always, TestOutputList (
2877 [["tail_n"; "0"; "/10klines"]], [])],
2878 "return last N lines of a file",
2880 If the parameter C<nrlines> is a positive number, this returns the last
2881 C<nrlines> lines of the file C<path>.
2883 If the parameter C<nrlines> is a negative number, this returns lines
2884 from the file C<path>, starting with the C<-nrlines>th line.
2886 If the parameter C<nrlines> is zero, this returns an empty list.");
2888 ("df", (RString "output", []), 125, [],
2889 [], (* XXX Tricky to test because it depends on the exact format
2890 * of the 'df' command and other imponderables.
2892 "report file system disk space usage",
2894 This command runs the C<df> command to report disk space used.
2896 This command is mostly useful for interactive sessions. It
2897 is I<not> intended that you try to parse the output string.
2898 Use C<statvfs> from programs.");
2900 ("df_h", (RString "output", []), 126, [],
2901 [], (* XXX Tricky to test because it depends on the exact format
2902 * of the 'df' command and other imponderables.
2904 "report file system disk space usage (human readable)",
2906 This command runs the C<df -h> command to report disk space used
2907 in human-readable format.
2909 This command is mostly useful for interactive sessions. It
2910 is I<not> intended that you try to parse the output string.
2911 Use C<statvfs> from programs.");
2913 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2914 [InitISOFS, Always, TestOutputInt (
2915 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2916 "estimate file space usage",
2918 This command runs the C<du -s> command to estimate file space
2921 C<path> can be a file or a directory. If C<path> is a directory
2922 then the estimate includes the contents of the directory and all
2923 subdirectories (recursively).
2925 The result is the estimated size in I<kilobytes>
2926 (ie. units of 1024 bytes).");
2928 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2929 [InitISOFS, Always, TestOutputList (
2930 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2931 "list files in an initrd",
2933 This command lists out files contained in an initrd.
2935 The files are listed without any initial C</> character. The
2936 files are listed in the order they appear (not necessarily
2937 alphabetical). Directory names are listed as separate items.
2939 Old Linux kernels (2.4 and earlier) used a compressed ext2
2940 filesystem as initrd. We I<only> support the newer initramfs
2941 format (compressed cpio files).");
2943 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2945 "mount a file using the loop device",
2947 This command lets you mount C<file> (a filesystem image
2948 in a file) on a mount point. It is entirely equivalent to
2949 the command C<mount -o loop file mountpoint>.");
2951 ("mkswap", (RErr, [Device "device"]), 130, [],
2952 [InitEmpty, Always, TestRun (
2953 [["part_disk"; "/dev/sda"; "mbr"];
2954 ["mkswap"; "/dev/sda1"]])],
2955 "create a swap partition",
2957 Create a swap partition on C<device>.");
2959 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2960 [InitEmpty, Always, TestRun (
2961 [["part_disk"; "/dev/sda"; "mbr"];
2962 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2963 "create a swap partition with a label",
2965 Create a swap partition on C<device> with label C<label>.
2967 Note that you cannot attach a swap label to a block device
2968 (eg. C</dev/sda>), just to a partition. This appears to be
2969 a limitation of the kernel or swap tools.");
2971 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2972 (let uuid = uuidgen () in
2973 [InitEmpty, Always, TestRun (
2974 [["part_disk"; "/dev/sda"; "mbr"];
2975 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2976 "create a swap partition with an explicit UUID",
2978 Create a swap partition on C<device> with UUID C<uuid>.");
2980 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2981 [InitBasicFS, Always, TestOutputStruct (
2982 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2983 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2984 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2985 InitBasicFS, Always, TestOutputStruct (
2986 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2987 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2988 "make block, character or FIFO devices",
2990 This call creates block or character special devices, or
2991 named pipes (FIFOs).
2993 The C<mode> parameter should be the mode, using the standard
2994 constants. C<devmajor> and C<devminor> are the
2995 device major and minor numbers, only used when creating block
2996 and character special devices.
2998 Note that, just like L<mknod(2)>, the mode must be bitwise
2999 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3000 just creates a regular file). These constants are
3001 available in the standard Linux header files, or you can use
3002 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3003 which are wrappers around this command which bitwise OR
3004 in the appropriate constant for you.
3006 The mode actually set is affected by the umask.");
3008 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3009 [InitBasicFS, Always, TestOutputStruct (
3010 [["mkfifo"; "0o777"; "/node"];
3011 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3012 "make FIFO (named pipe)",
3014 This call creates a FIFO (named pipe) called C<path> with
3015 mode C<mode>. It is just a convenient wrapper around
3018 The mode actually set is affected by the umask.");
3020 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3021 [InitBasicFS, Always, TestOutputStruct (
3022 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3023 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3024 "make block device node",
3026 This call creates a block device node called C<path> with
3027 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3028 It is just a convenient wrapper around C<guestfs_mknod>.
3030 The mode actually set is affected by the umask.");
3032 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3033 [InitBasicFS, Always, TestOutputStruct (
3034 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3035 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3036 "make char device node",
3038 This call creates a char device node called C<path> with
3039 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3040 It is just a convenient wrapper around C<guestfs_mknod>.
3042 The mode actually set is affected by the umask.");
3044 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3045 [InitEmpty, Always, TestOutputInt (
3046 [["umask"; "0o22"]], 0o22)],
3047 "set file mode creation mask (umask)",
3049 This function sets the mask used for creating new files and
3050 device nodes to C<mask & 0777>.
3052 Typical umask values would be C<022> which creates new files
3053 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3054 C<002> which creates new files with permissions like
3055 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3057 The default umask is C<022>. This is important because it
3058 means that directories and device nodes will be created with
3059 C<0644> or C<0755> mode even if you specify C<0777>.
3061 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3063 This call returns the previous umask.");
3065 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3067 "read directories entries",
3069 This returns the list of directory entries in directory C<dir>.
3071 All entries in the directory are returned, including C<.> and
3072 C<..>. The entries are I<not> sorted, but returned in the same
3073 order as the underlying filesystem.
3075 Also this call returns basic file type information about each
3076 file. The C<ftyp> field will contain one of the following characters:
3114 The L<readdir(3)> returned a C<d_type> field with an
3119 This function is primarily intended for use by programs. To
3120 get a simple list of names, use C<guestfs_ls>. To get a printable
3121 directory for human consumption, use C<guestfs_ll>.");
3123 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3125 "create partitions on a block device",
3127 This is a simplified interface to the C<guestfs_sfdisk>
3128 command, where partition sizes are specified in megabytes
3129 only (rounded to the nearest cylinder) and you don't need
3130 to specify the cyls, heads and sectors parameters which
3131 were rarely if ever used anyway.
3133 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3134 and C<guestfs_part_disk>");
3136 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3138 "determine file type inside a compressed file",
3140 This command runs C<file> after first decompressing C<path>
3143 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3145 Since 1.0.63, use C<guestfs_file> instead which can now
3146 process compressed files.");
3148 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3150 "list extended attributes of a file or directory",
3152 This call lists the extended attributes of the file or directory
3155 At the system call level, this is a combination of the
3156 L<listxattr(2)> and L<getxattr(2)> calls.
3158 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3160 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3162 "list extended attributes of a file or directory",
3164 This is the same as C<guestfs_getxattrs>, but if C<path>
3165 is a symbolic link, then it returns the extended attributes
3166 of the link itself.");
3168 ("setxattr", (RErr, [String "xattr";
3169 String "val"; Int "vallen"; (* will be BufferIn *)
3170 Pathname "path"]), 143, [Optional "linuxxattrs"],
3172 "set extended attribute of a file or directory",
3174 This call sets the extended attribute named C<xattr>
3175 of the file C<path> to the value C<val> (of length C<vallen>).
3176 The value is arbitrary 8 bit data.
3178 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3180 ("lsetxattr", (RErr, [String "xattr";
3181 String "val"; Int "vallen"; (* will be BufferIn *)
3182 Pathname "path"]), 144, [Optional "linuxxattrs"],
3184 "set extended attribute of a file or directory",
3186 This is the same as C<guestfs_setxattr>, but if C<path>
3187 is a symbolic link, then it sets an extended attribute
3188 of the link itself.");
3190 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3192 "remove extended attribute of a file or directory",
3194 This call removes the extended attribute named C<xattr>
3195 of the file C<path>.
3197 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3199 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3201 "remove extended attribute of a file or directory",
3203 This is the same as C<guestfs_removexattr>, but if C<path>
3204 is a symbolic link, then it removes an extended attribute
3205 of the link itself.");
3207 ("mountpoints", (RHashtable "mps", []), 147, [],
3211 This call is similar to C<guestfs_mounts>. That call returns
3212 a list of devices. This one returns a hash table (map) of
3213 device name to directory where the device is mounted.");
3215 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3216 (* This is a special case: while you would expect a parameter
3217 * of type "Pathname", that doesn't work, because it implies
3218 * NEED_ROOT in the generated calling code in stubs.c, and
3219 * this function cannot use NEED_ROOT.
3222 "create a mountpoint",
3224 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3225 specialized calls that can be used to create extra mountpoints
3226 before mounting the first filesystem.
3228 These calls are I<only> necessary in some very limited circumstances,
3229 mainly the case where you want to mount a mix of unrelated and/or
3230 read-only filesystems together.
3232 For example, live CDs often contain a \"Russian doll\" nest of
3233 filesystems, an ISO outer layer, with a squashfs image inside, with
3234 an ext2/3 image inside that. You can unpack this as follows
3237 add-ro Fedora-11-i686-Live.iso
3240 mkmountpoint /squash
3243 mount-loop /cd/LiveOS/squashfs.img /squash
3244 mount-loop /squash/LiveOS/ext3fs.img /ext3
3246 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3248 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3250 "remove a mountpoint",
3252 This calls removes a mountpoint that was previously created
3253 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3254 for full details.");
3256 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3257 [InitISOFS, Always, TestOutputBuffer (
3258 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3259 (* Test various near large, large and too large files (RHBZ#589039). *)
3260 InitBasicFS, Always, TestLastFail (
3262 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3263 ["read_file"; "/a"]]);
3264 InitBasicFS, Always, TestLastFail (
3266 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3267 ["read_file"; "/a"]]);
3268 InitBasicFS, Always, TestLastFail (
3270 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3271 ["read_file"; "/a"]])],
3274 This calls returns the contents of the file C<path> as a
3277 Unlike C<guestfs_cat>, this function can correctly
3278 handle files that contain embedded ASCII NUL characters.
3279 However unlike C<guestfs_download>, this function is limited
3280 in the total size of file that can be handled.");
3282 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3283 [InitISOFS, Always, TestOutputList (
3284 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3285 InitISOFS, Always, TestOutputList (
3286 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3287 "return lines matching a pattern",
3289 This calls the external C<grep> program and returns the
3292 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3293 [InitISOFS, Always, TestOutputList (
3294 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3295 "return lines matching a pattern",
3297 This calls the external C<egrep> program and returns the
3300 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3301 [InitISOFS, Always, TestOutputList (
3302 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3303 "return lines matching a pattern",
3305 This calls the external C<fgrep> program and returns the
3308 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3309 [InitISOFS, Always, TestOutputList (
3310 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3311 "return lines matching a pattern",
3313 This calls the external C<grep -i> program and returns the
3316 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3317 [InitISOFS, Always, TestOutputList (
3318 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3319 "return lines matching a pattern",
3321 This calls the external C<egrep -i> program and returns the
3324 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3325 [InitISOFS, Always, TestOutputList (
3326 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3327 "return lines matching a pattern",
3329 This calls the external C<fgrep -i> program and returns the
3332 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3333 [InitISOFS, Always, TestOutputList (
3334 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3335 "return lines matching a pattern",
3337 This calls the external C<zgrep> program and returns the
3340 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3341 [InitISOFS, Always, TestOutputList (
3342 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3343 "return lines matching a pattern",
3345 This calls the external C<zegrep> program and returns the
3348 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3349 [InitISOFS, Always, TestOutputList (
3350 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3351 "return lines matching a pattern",
3353 This calls the external C<zfgrep> program and returns the
3356 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3357 [InitISOFS, Always, TestOutputList (
3358 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3359 "return lines matching a pattern",
3361 This calls the external C<zgrep -i> program and returns the
3364 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3365 [InitISOFS, Always, TestOutputList (
3366 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3367 "return lines matching a pattern",
3369 This calls the external C<zegrep -i> program and returns the
3372 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3373 [InitISOFS, Always, TestOutputList (
3374 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3375 "return lines matching a pattern",
3377 This calls the external C<zfgrep -i> program and returns the
3380 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3381 [InitISOFS, Always, TestOutput (
3382 [["realpath"; "/../directory"]], "/directory")],
3383 "canonicalized absolute pathname",
3385 Return the canonicalized absolute pathname of C<path>. The
3386 returned path has no C<.>, C<..> or symbolic link path elements.");
3388 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3389 [InitBasicFS, Always, TestOutputStruct (
3392 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3393 "create a hard link",
3395 This command creates a hard link using the C<ln> command.");
3397 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3398 [InitBasicFS, Always, TestOutputStruct (
3401 ["ln_f"; "/a"; "/b"];
3402 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3403 "create a hard link",
3405 This command creates a hard link using the C<ln -f> command.
3406 The C<-f> option removes the link (C<linkname>) if it exists already.");
3408 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3409 [InitBasicFS, Always, TestOutputStruct (
3411 ["ln_s"; "a"; "/b"];
3412 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3413 "create a symbolic link",
3415 This command creates a symbolic link using the C<ln -s> command.");
3417 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3418 [InitBasicFS, Always, TestOutput (
3419 [["mkdir_p"; "/a/b"];
3420 ["touch"; "/a/b/c"];
3421 ["ln_sf"; "../d"; "/a/b/c"];
3422 ["readlink"; "/a/b/c"]], "../d")],
3423 "create a symbolic link",
3425 This command creates a symbolic link using the C<ln -sf> command,
3426 The C<-f> option removes the link (C<linkname>) if it exists already.");
3428 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3429 [] (* XXX tested above *),
3430 "read the target of a symbolic link",
3432 This command reads the target of a symbolic link.");
3434 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3435 [InitBasicFS, Always, TestOutputStruct (
3436 [["fallocate"; "/a"; "1000000"];
3437 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3438 "preallocate a file in the guest filesystem",
3440 This command preallocates a file (containing zero bytes) named
3441 C<path> of size C<len> bytes. If the file exists already, it
3444 Do not confuse this with the guestfish-specific
3445 C<alloc> command which allocates a file in the host and
3446 attaches it as a device.");
3448 ("swapon_device", (RErr, [Device "device"]), 170, [],
3449 [InitPartition, Always, TestRun (
3450 [["mkswap"; "/dev/sda1"];
3451 ["swapon_device"; "/dev/sda1"];
3452 ["swapoff_device"; "/dev/sda1"]])],
3453 "enable swap on device",
3455 This command enables the libguestfs appliance to use the
3456 swap device or partition named C<device>. The increased
3457 memory is made available for all commands, for example
3458 those run using C<guestfs_command> or C<guestfs_sh>.
3460 Note that you should not swap to existing guest swap
3461 partitions unless you know what you are doing. They may
3462 contain hibernation information, or other information that
3463 the guest doesn't want you to trash. You also risk leaking
3464 information about the host to the guest this way. Instead,
3465 attach a new host device to the guest and swap on that.");
3467 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3468 [], (* XXX tested by swapon_device *)
3469 "disable swap on device",
3471 This command disables the libguestfs appliance swap
3472 device or partition named C<device>.
3473 See C<guestfs_swapon_device>.");
3475 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3476 [InitBasicFS, Always, TestRun (
3477 [["fallocate"; "/swap"; "8388608"];
3478 ["mkswap_file"; "/swap"];
3479 ["swapon_file"; "/swap"];
3480 ["swapoff_file"; "/swap"]])],
3481 "enable swap on file",
3483 This command enables swap to a file.
3484 See C<guestfs_swapon_device> for other notes.");
3486 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3487 [], (* XXX tested by swapon_file *)
3488 "disable swap on file",
3490 This command disables the libguestfs appliance swap on file.");
3492 ("swapon_label", (RErr, [String "label"]), 174, [],
3493 [InitEmpty, Always, TestRun (
3494 [["part_disk"; "/dev/sdb"; "mbr"];
3495 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3496 ["swapon_label"; "swapit"];
3497 ["swapoff_label"; "swapit"];
3498 ["zero"; "/dev/sdb"];
3499 ["blockdev_rereadpt"; "/dev/sdb"]])],
3500 "enable swap on labeled swap partition",
3502 This command enables swap to a labeled swap partition.
3503 See C<guestfs_swapon_device> for other notes.");
3505 ("swapoff_label", (RErr, [String "label"]), 175, [],
3506 [], (* XXX tested by swapon_label *)
3507 "disable swap on labeled swap partition",
3509 This command disables the libguestfs appliance swap on
3510 labeled swap partition.");
3512 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3513 (let uuid = uuidgen () in
3514 [InitEmpty, Always, TestRun (
3515 [["mkswap_U"; uuid; "/dev/sdb"];
3516 ["swapon_uuid"; uuid];
3517 ["swapoff_uuid"; uuid]])]),
3518 "enable swap on swap partition by UUID",
3520 This command enables swap to a swap partition with the given UUID.
3521 See C<guestfs_swapon_device> for other notes.");
3523 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3524 [], (* XXX tested by swapon_uuid *)
3525 "disable swap on swap partition by UUID",
3527 This command disables the libguestfs appliance swap partition
3528 with the given UUID.");
3530 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3531 [InitBasicFS, Always, TestRun (
3532 [["fallocate"; "/swap"; "8388608"];
3533 ["mkswap_file"; "/swap"]])],
3534 "create a swap file",
3538 This command just writes a swap file signature to an existing
3539 file. To create the file itself, use something like C<guestfs_fallocate>.");
3541 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3542 [InitISOFS, Always, TestRun (
3543 [["inotify_init"; "0"]])],
3544 "create an inotify handle",
3546 This command creates a new inotify handle.
3547 The inotify subsystem can be used to notify events which happen to
3548 objects in the guest filesystem.
3550 C<maxevents> is the maximum number of events which will be
3551 queued up between calls to C<guestfs_inotify_read> or
3552 C<guestfs_inotify_files>.
3553 If this is passed as C<0>, then the kernel (or previously set)
3554 default is used. For Linux 2.6.29 the default was 16384 events.
3555 Beyond this limit, the kernel throws away events, but records
3556 the fact that it threw them away by setting a flag
3557 C<IN_Q_OVERFLOW> in the returned structure list (see
3558 C<guestfs_inotify_read>).
3560 Before any events are generated, you have to add some
3561 watches to the internal watch list. See:
3562 C<guestfs_inotify_add_watch>,
3563 C<guestfs_inotify_rm_watch> and
3564 C<guestfs_inotify_watch_all>.
3566 Queued up events should be read periodically by calling
3567 C<guestfs_inotify_read>
3568 (or C<guestfs_inotify_files> which is just a helpful
3569 wrapper around C<guestfs_inotify_read>). If you don't
3570 read the events out often enough then you risk the internal
3573 The handle should be closed after use by calling
3574 C<guestfs_inotify_close>. This also removes any
3575 watches automatically.
3577 See also L<inotify(7)> for an overview of the inotify interface
3578 as exposed by the Linux kernel, which is roughly what we expose
3579 via libguestfs. Note that there is one global inotify handle
3580 per libguestfs instance.");
3582 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3583 [InitBasicFS, Always, TestOutputList (
3584 [["inotify_init"; "0"];
3585 ["inotify_add_watch"; "/"; "1073741823"];
3588 ["inotify_files"]], ["a"; "b"])],
3589 "add an inotify watch",
3591 Watch C<path> for the events listed in C<mask>.
3593 Note that if C<path> is a directory then events within that
3594 directory are watched, but this does I<not> happen recursively
3595 (in subdirectories).
3597 Note for non-C or non-Linux callers: the inotify events are
3598 defined by the Linux kernel ABI and are listed in
3599 C</usr/include/sys/inotify.h>.");
3601 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3603 "remove an inotify watch",
3605 Remove a previously defined inotify watch.
3606 See C<guestfs_inotify_add_watch>.");
3608 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3610 "return list of inotify events",
3612 Return the complete queue of events that have happened
3613 since the previous read call.
3615 If no events have happened, this returns an empty list.
3617 I<Note>: In order to make sure that all events have been
3618 read, you must call this function repeatedly until it
3619 returns an empty list. The reason is that the call will
3620 read events up to the maximum appliance-to-host message
3621 size and leave remaining events in the queue.");
3623 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3625 "return list of watched files that had events",
3627 This function is a helpful wrapper around C<guestfs_inotify_read>
3628 which just returns a list of pathnames of objects that were
3629 touched. The returned pathnames are sorted and deduplicated.");
3631 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3633 "close the inotify handle",
3635 This closes the inotify handle which was previously
3636 opened by inotify_init. It removes all watches, throws
3637 away any pending events, and deallocates all resources.");
3639 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3641 "set SELinux security context",
3643 This sets the SELinux security context of the daemon
3644 to the string C<context>.
3646 See the documentation about SELINUX in L<guestfs(3)>.");
3648 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3650 "get SELinux security context",
3652 This gets the SELinux security context of the daemon.
3654 See the documentation about SELINUX in L<guestfs(3)>,
3655 and C<guestfs_setcon>");
3657 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3658 [InitEmpty, Always, TestOutput (
3659 [["part_disk"; "/dev/sda"; "mbr"];
3660 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3661 ["mount_options"; ""; "/dev/sda1"; "/"];
3662 ["write_file"; "/new"; "new file contents"; "0"];
3663 ["cat"; "/new"]], "new file contents")],
3664 "make a filesystem with block size",
3666 This call is similar to C<guestfs_mkfs>, but it allows you to
3667 control the block size of the resulting filesystem. Supported
3668 block sizes depend on the filesystem type, but typically they
3669 are C<1024>, C<2048> or C<4096> only.");
3671 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3672 [InitEmpty, Always, TestOutput (
3673 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3674 ["mke2journal"; "4096"; "/dev/sda1"];
3675 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3676 ["mount_options"; ""; "/dev/sda2"; "/"];
3677 ["write_file"; "/new"; "new file contents"; "0"];
3678 ["cat"; "/new"]], "new file contents")],
3679 "make ext2/3/4 external journal",
3681 This creates an ext2 external journal on C<device>. It is equivalent
3684 mke2fs -O journal_dev -b blocksize device");
3686 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3687 [InitEmpty, Always, TestOutput (
3688 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3689 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3690 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3691 ["mount_options"; ""; "/dev/sda2"; "/"];
3692 ["write_file"; "/new"; "new file contents"; "0"];
3693 ["cat"; "/new"]], "new file contents")],
3694 "make ext2/3/4 external journal with label",
3696 This creates an ext2 external journal on C<device> with label C<label>.");
3698 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3699 (let uuid = uuidgen () in
3700 [InitEmpty, Always, TestOutput (
3701 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3702 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3703 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3704 ["mount_options"; ""; "/dev/sda2"; "/"];
3705 ["write_file"; "/new"; "new file contents"; "0"];
3706 ["cat"; "/new"]], "new file contents")]),
3707 "make ext2/3/4 external journal with UUID",
3709 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3711 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3713 "make ext2/3/4 filesystem with external journal",
3715 This creates an ext2/3/4 filesystem on C<device> with
3716 an external journal on C<journal>. It is equivalent
3719 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3721 See also C<guestfs_mke2journal>.");
3723 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3725 "make ext2/3/4 filesystem with external journal",
3727 This creates an ext2/3/4 filesystem on C<device> with
3728 an external journal on the journal labeled C<label>.
3730 See also C<guestfs_mke2journal_L>.");
3732 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3734 "make ext2/3/4 filesystem with external journal",
3736 This creates an ext2/3/4 filesystem on C<device> with
3737 an external journal on the journal with UUID C<uuid>.
3739 See also C<guestfs_mke2journal_U>.");
3741 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3742 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3743 "load a kernel module",
3745 This loads a kernel module in the appliance.
3747 The kernel module must have been whitelisted when libguestfs
3748 was built (see C<appliance/kmod.whitelist.in> in the source).");
3750 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3751 [InitNone, Always, TestOutput (
3752 [["echo_daemon"; "This is a test"]], "This is a test"
3754 "echo arguments back to the client",
3756 This command concatenate the list of C<words> passed with single spaces between
3757 them and returns the resulting string.
3759 You can use this command to test the connection through to the daemon.
3761 See also C<guestfs_ping_daemon>.");
3763 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3764 [], (* There is a regression test for this. *)
3765 "find all files and directories, returning NUL-separated list",
3767 This command lists out all files and directories, recursively,
3768 starting at C<directory>, placing the resulting list in the
3769 external file called C<files>.
3771 This command works the same way as C<guestfs_find> with the
3772 following exceptions:
3778 The resulting list is written to an external file.
3782 Items (filenames) in the result are separated
3783 by C<\\0> characters. See L<find(1)> option I<-print0>.
3787 This command is not limited in the number of names that it
3792 The result list is not sorted.
3796 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3797 [InitISOFS, Always, TestOutput (
3798 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3799 InitISOFS, Always, TestOutput (
3800 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3801 InitISOFS, Always, TestOutput (
3802 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3803 InitISOFS, Always, TestLastFail (
3804 [["case_sensitive_path"; "/Known-1/"]]);
3805 InitBasicFS, Always, TestOutput (
3807 ["mkdir"; "/a/bbb"];
3808 ["touch"; "/a/bbb/c"];
3809 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3810 InitBasicFS, Always, TestOutput (
3812 ["mkdir"; "/a/bbb"];
3813 ["touch"; "/a/bbb/c"];
3814 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3815 InitBasicFS, Always, TestLastFail (
3817 ["mkdir"; "/a/bbb"];
3818 ["touch"; "/a/bbb/c"];
3819 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3820 "return true path on case-insensitive filesystem",
3822 This can be used to resolve case insensitive paths on
3823 a filesystem which is case sensitive. The use case is
3824 to resolve paths which you have read from Windows configuration
3825 files or the Windows Registry, to the true path.
3827 The command handles a peculiarity of the Linux ntfs-3g
3828 filesystem driver (and probably others), which is that although
3829 the underlying filesystem is case-insensitive, the driver
3830 exports the filesystem to Linux as case-sensitive.
3832 One consequence of this is that special directories such
3833 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3834 (or other things) depending on the precise details of how
3835 they were created. In Windows itself this would not be
3838 Bug or feature? You decide:
3839 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3841 This function resolves the true case of each element in the
3842 path and returns the case-sensitive path.
3844 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3845 might return C<\"/WINDOWS/system32\"> (the exact return value
3846 would depend on details of how the directories were originally
3847 created under Windows).
3850 This function does not handle drive names, backslashes etc.
3852 See also C<guestfs_realpath>.");
3854 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3855 [InitBasicFS, Always, TestOutput (
3856 [["vfs_type"; "/dev/sda1"]], "ext2")],
3857 "get the Linux VFS type corresponding to a mounted device",
3859 This command gets the block device type corresponding to
3860 a mounted device called C<device>.
3862 Usually the result is the name of the Linux VFS module that
3863 is used to mount this device (probably determined automatically
3864 if you used the C<guestfs_mount> call).");
3866 ("truncate", (RErr, [Pathname "path"]), 199, [],
3867 [InitBasicFS, Always, TestOutputStruct (
3868 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3869 ["truncate"; "/test"];
3870 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3871 "truncate a file to zero size",
3873 This command truncates C<path> to a zero-length file. The
3874 file must exist already.");
3876 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3877 [InitBasicFS, Always, TestOutputStruct (
3878 [["touch"; "/test"];
3879 ["truncate_size"; "/test"; "1000"];
3880 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3881 "truncate a file to a particular size",
3883 This command truncates C<path> to size C<size> bytes. The file
3884 must exist already. If the file is smaller than C<size> then
3885 the file is extended to the required size with null bytes.");
3887 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3888 [InitBasicFS, Always, TestOutputStruct (
3889 [["touch"; "/test"];
3890 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3891 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3892 "set timestamp of a file with nanosecond precision",
3894 This command sets the timestamps of a file with nanosecond
3897 C<atsecs, atnsecs> are the last access time (atime) in secs and
3898 nanoseconds from the epoch.
3900 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3901 secs and nanoseconds from the epoch.
3903 If the C<*nsecs> field contains the special value C<-1> then
3904 the corresponding timestamp is set to the current time. (The
3905 C<*secs> field is ignored in this case).
3907 If the C<*nsecs> field contains the special value C<-2> then
3908 the corresponding timestamp is left unchanged. (The
3909 C<*secs> field is ignored in this case).");
3911 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3912 [InitBasicFS, Always, TestOutputStruct (
3913 [["mkdir_mode"; "/test"; "0o111"];
3914 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3915 "create a directory with a particular mode",
3917 This command creates a directory, setting the initial permissions
3918 of the directory to C<mode>.
3920 For common Linux filesystems, the actual mode which is set will
3921 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3922 interpret the mode in other ways.
3924 See also C<guestfs_mkdir>, C<guestfs_umask>");
3926 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3928 "change file owner and group",
3930 Change the file owner to C<owner> and group to C<group>.
3931 This is like C<guestfs_chown> but if C<path> is a symlink then
3932 the link itself is changed, not the target.
3934 Only numeric uid and gid are supported. If you want to use
3935 names, you will need to locate and parse the password file
3936 yourself (Augeas support makes this relatively easy).");
3938 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3940 "lstat on multiple files",
3942 This call allows you to perform the C<guestfs_lstat> operation
3943 on multiple files, where all files are in the directory C<path>.
3944 C<names> is the list of files from this directory.
3946 On return you get a list of stat structs, with a one-to-one
3947 correspondence to the C<names> list. If any name did not exist
3948 or could not be lstat'd, then the C<ino> field of that structure
3951 This call is intended for programs that want to efficiently
3952 list a directory contents without making many round-trips.
3953 See also C<guestfs_lxattrlist> for a similarly efficient call
3954 for getting extended attributes. Very long directory listings
3955 might cause the protocol message size to be exceeded, causing
3956 this call to fail. The caller must split up such requests
3957 into smaller groups of names.");
3959 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3961 "lgetxattr on multiple files",
3963 This call allows you to get the extended attributes
3964 of multiple files, where all files are in the directory C<path>.
3965 C<names> is the list of files from this directory.
3967 On return you get a flat list of xattr structs which must be
3968 interpreted sequentially. The first xattr struct always has a zero-length
3969 C<attrname>. C<attrval> in this struct is zero-length
3970 to indicate there was an error doing C<lgetxattr> for this
3971 file, I<or> is a C string which is a decimal number
3972 (the number of following attributes for this file, which could
3973 be C<\"0\">). Then after the first xattr struct are the
3974 zero or more attributes for the first named file.
3975 This repeats for the second and subsequent files.
3977 This call is intended for programs that want to efficiently
3978 list a directory contents without making many round-trips.
3979 See also C<guestfs_lstatlist> for a similarly efficient call
3980 for getting standard stats. Very long directory listings
3981 might cause the protocol message size to be exceeded, causing
3982 this call to fail. The caller must split up such requests
3983 into smaller groups of names.");
3985 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3987 "readlink on multiple files",
3989 This call allows you to do a C<readlink> operation
3990 on multiple files, where all files are in the directory C<path>.
3991 C<names> is the list of files from this directory.
3993 On return you get a list of strings, with a one-to-one
3994 correspondence to the C<names> list. Each string is the
3995 value of the symbol link.
3997 If the C<readlink(2)> operation fails on any name, then
3998 the corresponding result string is the empty string C<\"\">.
3999 However the whole operation is completed even if there
4000 were C<readlink(2)> errors, and so you can call this
4001 function with names where you don't know if they are
4002 symbolic links already (albeit slightly less efficient).
4004 This call is intended for programs that want to efficiently
4005 list a directory contents without making many round-trips.
4006 Very long directory listings might cause the protocol
4007 message size to be exceeded, causing
4008 this call to fail. The caller must split up such requests
4009 into smaller groups of names.");
4011 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4012 [InitISOFS, Always, TestOutputBuffer (
4013 [["pread"; "/known-4"; "1"; "3"]], "\n");
4014 InitISOFS, Always, TestOutputBuffer (
4015 [["pread"; "/empty"; "0"; "100"]], "")],
4016 "read part of a file",
4018 This command lets you read part of a file. It reads C<count>
4019 bytes of the file, starting at C<offset>, from file C<path>.
4021 This may read fewer bytes than requested. For further details
4022 see the L<pread(2)> system call.");
4024 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4025 [InitEmpty, Always, TestRun (
4026 [["part_init"; "/dev/sda"; "gpt"]])],
4027 "create an empty partition table",
4029 This creates an empty partition table on C<device> of one of the
4030 partition types listed below. Usually C<parttype> should be
4031 either C<msdos> or C<gpt> (for large disks).
4033 Initially there are no partitions. Following this, you should
4034 call C<guestfs_part_add> for each partition required.
4036 Possible values for C<parttype> are:
4040 =item B<efi> | B<gpt>
4042 Intel EFI / GPT partition table.
4044 This is recommended for >= 2 TB partitions that will be accessed
4045 from Linux and Intel-based Mac OS X. It also has limited backwards
4046 compatibility with the C<mbr> format.
4048 =item B<mbr> | B<msdos>
4050 The standard PC \"Master Boot Record\" (MBR) format used
4051 by MS-DOS and Windows. This partition type will B<only> work
4052 for device sizes up to 2 TB. For large disks we recommend
4057 Other partition table types that may work but are not
4066 =item B<amiga> | B<rdb>
4068 Amiga \"Rigid Disk Block\" format.
4076 DASD, used on IBM mainframes.
4084 Old Mac partition format. Modern Macs use C<gpt>.
4088 NEC PC-98 format, common in Japan apparently.
4096 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4097 [InitEmpty, Always, TestRun (
4098 [["part_init"; "/dev/sda"; "mbr"];
4099 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4100 InitEmpty, Always, TestRun (
4101 [["part_init"; "/dev/sda"; "gpt"];
4102 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4103 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4104 InitEmpty, Always, TestRun (
4105 [["part_init"; "/dev/sda"; "mbr"];
4106 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4107 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4108 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4109 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4110 "add a partition to the device",
4112 This command adds a partition to C<device>. If there is no partition
4113 table on the device, call C<guestfs_part_init> first.
4115 The C<prlogex> parameter is the type of partition. Normally you
4116 should pass C<p> or C<primary> here, but MBR partition tables also
4117 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4120 C<startsect> and C<endsect> are the start and end of the partition
4121 in I<sectors>. C<endsect> may be negative, which means it counts
4122 backwards from the end of the disk (C<-1> is the last sector).
4124 Creating a partition which covers the whole disk is not so easy.
4125 Use C<guestfs_part_disk> to do that.");
4127 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4128 [InitEmpty, Always, TestRun (
4129 [["part_disk"; "/dev/sda"; "mbr"]]);
4130 InitEmpty, Always, TestRun (
4131 [["part_disk"; "/dev/sda"; "gpt"]])],
4132 "partition whole disk with a single primary partition",
4134 This command is simply a combination of C<guestfs_part_init>
4135 followed by C<guestfs_part_add> to create a single primary partition
4136 covering the whole disk.
4138 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4139 but other possible values are described in C<guestfs_part_init>.");
4141 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4142 [InitEmpty, Always, TestRun (
4143 [["part_disk"; "/dev/sda"; "mbr"];
4144 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4145 "make a partition bootable",
4147 This sets the bootable flag on partition numbered C<partnum> on
4148 device C<device>. Note that partitions are numbered from 1.
4150 The bootable flag is used by some operating systems (notably
4151 Windows) to determine which partition to boot from. It is by
4152 no means universally recognized.");
4154 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4155 [InitEmpty, Always, TestRun (
4156 [["part_disk"; "/dev/sda"; "gpt"];
4157 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4158 "set partition name",
4160 This sets the partition name on partition numbered C<partnum> on
4161 device C<device>. Note that partitions are numbered from 1.
4163 The partition name can only be set on certain types of partition
4164 table. This works on C<gpt> but not on C<mbr> partitions.");
4166 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4167 [], (* XXX Add a regression test for this. *)
4168 "list partitions on a device",
4170 This command parses the partition table on C<device> and
4171 returns the list of partitions found.
4173 The fields in the returned structure are:
4179 Partition number, counting from 1.
4183 Start of the partition I<in bytes>. To get sectors you have to
4184 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4188 End of the partition in bytes.
4192 Size of the partition in bytes.
4196 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4197 [InitEmpty, Always, TestOutput (
4198 [["part_disk"; "/dev/sda"; "gpt"];
4199 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4200 "get the partition table type",
4202 This command examines the partition table on C<device> and
4203 returns the partition table type (format) being used.
4205 Common return values include: C<msdos> (a DOS/Windows style MBR
4206 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4207 values are possible, although unusual. See C<guestfs_part_init>
4210 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4211 [InitBasicFS, Always, TestOutputBuffer (
4212 [["fill"; "0x63"; "10"; "/test"];
4213 ["read_file"; "/test"]], "cccccccccc")],
4214 "fill a file with octets",
4216 This command creates a new file called C<path>. The initial
4217 content of the file is C<len> octets of C<c>, where C<c>
4218 must be a number in the range C<[0..255]>.
4220 To fill a file with zero bytes (sparsely), it is
4221 much more efficient to use C<guestfs_truncate_size>.");
4223 ("available", (RErr, [StringList "groups"]), 216, [],
4224 [InitNone, Always, TestRun [["available"; ""]]],
4225 "test availability of some parts of the API",
4227 This command is used to check the availability of some
4228 groups of functionality in the appliance, which not all builds of
4229 the libguestfs appliance will be able to provide.
4231 The libguestfs groups, and the functions that those
4232 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4234 The argument C<groups> is a list of group names, eg:
4235 C<[\"inotify\", \"augeas\"]> would check for the availability of
4236 the Linux inotify functions and Augeas (configuration file
4239 The command returns no error if I<all> requested groups are available.
4241 It fails with an error if one or more of the requested
4242 groups is unavailable in the appliance.
4244 If an unknown group name is included in the
4245 list of groups then an error is always returned.
4253 You must call C<guestfs_launch> before calling this function.
4255 The reason is because we don't know what groups are
4256 supported by the appliance/daemon until it is running and can
4261 If a group of functions is available, this does not necessarily
4262 mean that they will work. You still have to check for errors
4263 when calling individual API functions even if they are
4268 It is usually the job of distro packagers to build
4269 complete functionality into the libguestfs appliance.
4270 Upstream libguestfs, if built from source with all
4271 requirements satisfied, will support everything.
4275 This call was added in version C<1.0.80>. In previous
4276 versions of libguestfs all you could do would be to speculatively
4277 execute a command to find out if the daemon implemented it.
4278 See also C<guestfs_version>.
4282 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4283 [InitBasicFS, Always, TestOutputBuffer (
4284 [["write_file"; "/src"; "hello, world"; "0"];
4285 ["dd"; "/src"; "/dest"];
4286 ["read_file"; "/dest"]], "hello, world")],
4287 "copy from source to destination using dd",
4289 This command copies from one source device or file C<src>
4290 to another destination device or file C<dest>. Normally you
4291 would use this to copy to or from a device or partition, for
4292 example to duplicate a filesystem.
4294 If the destination is a device, it must be as large or larger
4295 than the source file or device, otherwise the copy will fail.
4296 This command cannot do partial copies (see C<guestfs_copy_size>).");
4298 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4299 [InitBasicFS, Always, TestOutputInt (
4300 [["write_file"; "/file"; "hello, world"; "0"];
4301 ["filesize"; "/file"]], 12)],
4302 "return the size of the file in bytes",
4304 This command returns the size of C<file> in bytes.
4306 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4307 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4308 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4310 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4311 [InitBasicFSonLVM, Always, TestOutputList (
4312 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4313 ["lvs"]], ["/dev/VG/LV2"])],
4314 "rename an LVM logical volume",
4316 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4318 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4319 [InitBasicFSonLVM, Always, TestOutputList (
4321 ["vg_activate"; "false"; "VG"];
4322 ["vgrename"; "VG"; "VG2"];
4323 ["vg_activate"; "true"; "VG2"];
4324 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4325 ["vgs"]], ["VG2"])],
4326 "rename an LVM volume group",
4328 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4330 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4331 [InitISOFS, Always, TestOutputBuffer (
4332 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4333 "list the contents of a single file in an initrd",
4335 This command unpacks the file C<filename> from the initrd file
4336 called C<initrdpath>. The filename must be given I<without> the
4337 initial C</> character.
4339 For example, in guestfish you could use the following command
4340 to examine the boot script (usually called C</init>)
4341 contained in a Linux initrd or initramfs image:
4343 initrd-cat /boot/initrd-<version>.img init
4345 See also C<guestfs_initrd_list>.");
4347 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4349 "get the UUID of a physical volume",
4351 This command returns the UUID of the LVM PV C<device>.");
4353 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4355 "get the UUID of a volume group",
4357 This command returns the UUID of the LVM VG named C<vgname>.");
4359 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4361 "get the UUID of a logical volume",
4363 This command returns the UUID of the LVM LV C<device>.");
4365 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4367 "get the PV UUIDs containing the volume group",
4369 Given a VG called C<vgname>, this returns the UUIDs of all
4370 the physical volumes that this volume group resides on.
4372 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4373 calls to associate physical volumes and volume groups.
4375 See also C<guestfs_vglvuuids>.");
4377 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4379 "get the LV UUIDs of all LVs in the volume group",
4381 Given a VG called C<vgname>, this returns the UUIDs of all
4382 the logical volumes created in this volume group.
4384 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4385 calls to associate logical volumes and volume groups.
4387 See also C<guestfs_vgpvuuids>.");
4389 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4390 [InitBasicFS, Always, TestOutputBuffer (
4391 [["write_file"; "/src"; "hello, world"; "0"];
4392 ["copy_size"; "/src"; "/dest"; "5"];
4393 ["read_file"; "/dest"]], "hello")],
4394 "copy size bytes from source to destination using dd",
4396 This command copies exactly C<size> bytes from one source device
4397 or file C<src> to another destination device or file C<dest>.
4399 Note this will fail if the source is too short or if the destination
4400 is not large enough.");
4402 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4403 [InitEmpty, Always, TestRun (
4404 [["part_init"; "/dev/sda"; "mbr"];
4405 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4406 ["part_del"; "/dev/sda"; "1"]])],
4407 "delete a partition",
4409 This command deletes the partition numbered C<partnum> on C<device>.
4411 Note that in the case of MBR partitioning, deleting an
4412 extended partition also deletes any logical partitions
4415 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4416 [InitEmpty, Always, TestOutputTrue (
4417 [["part_init"; "/dev/sda"; "mbr"];
4418 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4419 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4420 ["part_get_bootable"; "/dev/sda"; "1"]])],
4421 "return true if a partition is bootable",
4423 This command returns true if the partition C<partnum> on
4424 C<device> has the bootable flag set.
4426 See also C<guestfs_part_set_bootable>.");
4428 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4429 [InitEmpty, Always, TestOutputInt (
4430 [["part_init"; "/dev/sda"; "mbr"];
4431 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4432 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4433 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4434 "get the MBR type byte (ID byte) from a partition",
4436 Returns the MBR type byte (also known as the ID byte) from
4437 the numbered partition C<partnum>.
4439 Note that only MBR (old DOS-style) partitions have type bytes.
4440 You will get undefined results for other partition table
4441 types (see C<guestfs_part_get_parttype>).");
4443 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4444 [], (* tested by part_get_mbr_id *)
4445 "set the MBR type byte (ID byte) of a partition",
4447 Sets the MBR type byte (also known as the ID byte) of
4448 the numbered partition C<partnum> to C<idbyte>. Note
4449 that the type bytes quoted in most documentation are
4450 in fact hexadecimal numbers, but usually documented
4451 without any leading \"0x\" which might be confusing.
4453 Note that only MBR (old DOS-style) partitions have type bytes.
4454 You will get undefined results for other partition table
4455 types (see C<guestfs_part_get_parttype>).");
4459 let all_functions = non_daemon_functions @ daemon_functions
4461 (* In some places we want the functions to be displayed sorted
4462 * alphabetically, so this is useful:
4464 let all_functions_sorted =
4465 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4466 compare n1 n2) all_functions
4468 (* Field types for structures. *)
4470 | FChar (* C 'char' (really, a 7 bit byte). *)
4471 | FString (* nul-terminated ASCII string, NOT NULL. *)
4472 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4477 | FBytes (* Any int measure that counts bytes. *)
4478 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4479 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4481 (* Because we generate extra parsing code for LVM command line tools,
4482 * we have to pull out the LVM columns separately here.
4492 "pv_attr", FString (* XXX *);
4493 "pv_pe_count", FInt64;
4494 "pv_pe_alloc_count", FInt64;
4497 "pv_mda_count", FInt64;
4498 "pv_mda_free", FBytes;
4499 (* Not in Fedora 10:
4500 "pv_mda_size", FBytes;
4507 "vg_attr", FString (* XXX *);
4510 "vg_sysid", FString;
4511 "vg_extent_size", FBytes;
4512 "vg_extent_count", FInt64;
4513 "vg_free_count", FInt64;
4518 "snap_count", FInt64;
4521 "vg_mda_count", FInt64;
4522 "vg_mda_free", FBytes;
4523 (* Not in Fedora 10:
4524 "vg_mda_size", FBytes;
4530 "lv_attr", FString (* XXX *);
4533 "lv_kernel_major", FInt64;
4534 "lv_kernel_minor", FInt64;
4536 "seg_count", FInt64;
4538 "snap_percent", FOptPercent;
4539 "copy_percent", FOptPercent;
4542 "mirror_log", FString;
4546 (* Names and fields in all structures (in RStruct and RStructList)
4550 (* The old RIntBool return type, only ever used for aug_defnode. Do
4551 * not use this struct in any new code.
4554 "i", FInt32; (* for historical compatibility *)
4555 "b", FInt32; (* for historical compatibility *)
4558 (* LVM PVs, VGs, LVs. *)
4559 "lvm_pv", lvm_pv_cols;
4560 "lvm_vg", lvm_vg_cols;
4561 "lvm_lv", lvm_lv_cols;
4563 (* Column names and types from stat structures.
4564 * NB. Can't use things like 'st_atime' because glibc header files
4565 * define some of these as macros. Ugh.
4596 (* Column names in dirent structure. *)
4599 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4604 (* Version numbers. *)
4612 (* Extended attribute. *)
4614 "attrname", FString;
4618 (* Inotify events. *)
4622 "in_cookie", FUInt32;
4626 (* Partition table entry. *)
4629 "part_start", FBytes;
4631 "part_size", FBytes;
4633 ] (* end of structs *)
4635 (* Ugh, Java has to be different ..
4636 * These names are also used by the Haskell bindings.
4638 let java_structs = [
4639 "int_bool", "IntBool";
4644 "statvfs", "StatVFS";
4646 "version", "Version";
4648 "inotify_event", "INotifyEvent";
4649 "partition", "Partition";
4652 (* What structs are actually returned. *)
4653 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4655 (* Returns a list of RStruct/RStructList structs that are returned
4656 * by any function. Each element of returned list is a pair:
4658 * (structname, RStructOnly)
4659 * == there exists function which returns RStruct (_, structname)
4660 * (structname, RStructListOnly)
4661 * == there exists function which returns RStructList (_, structname)
4662 * (structname, RStructAndList)
4663 * == there are functions returning both RStruct (_, structname)
4664 * and RStructList (_, structname)
4666 let rstructs_used_by functions =
4667 (* ||| is a "logical OR" for rstructs_used_t *)
4671 | _, RStructAndList -> RStructAndList
4672 | RStructOnly, RStructListOnly
4673 | RStructListOnly, RStructOnly -> RStructAndList
4674 | RStructOnly, RStructOnly -> RStructOnly
4675 | RStructListOnly, RStructListOnly -> RStructListOnly
4678 let h = Hashtbl.create 13 in
4680 (* if elem->oldv exists, update entry using ||| operator,
4681 * else just add elem->newv to the hash
4683 let update elem newv =
4684 try let oldv = Hashtbl.find h elem in
4685 Hashtbl.replace h elem (newv ||| oldv)
4686 with Not_found -> Hashtbl.add h elem newv
4690 fun (_, style, _, _, _, _, _) ->
4691 match fst style with
4692 | RStruct (_, structname) -> update structname RStructOnly
4693 | RStructList (_, structname) -> update structname RStructListOnly
4697 (* return key->values as a list of (key,value) *)
4698 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4700 (* Used for testing language bindings. *)
4702 | CallString of string
4703 | CallOptString of string option
4704 | CallStringList of string list
4706 | CallInt64 of int64
4709 (* Used to memoize the result of pod2text. *)
4710 let pod2text_memo_filename = "src/.pod2text.data"
4711 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4713 let chan = open_in pod2text_memo_filename in
4714 let v = input_value chan in
4718 _ -> Hashtbl.create 13
4719 let pod2text_memo_updated () =
4720 let chan = open_out pod2text_memo_filename in
4721 output_value chan pod2text_memo;
4724 (* Useful functions.
4725 * Note we don't want to use any external OCaml libraries which
4726 * makes this a bit harder than it should be.
4728 module StringMap = Map.Make (String)
4730 let failwithf fs = ksprintf failwith fs
4732 let unique = let i = ref 0 in fun () -> incr i; !i
4734 let replace_char s c1 c2 =
4735 let s2 = String.copy s in
4736 let r = ref false in
4737 for i = 0 to String.length s2 - 1 do
4738 if String.unsafe_get s2 i = c1 then (
4739 String.unsafe_set s2 i c2;
4743 if not !r then s else s2
4747 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4749 let triml ?(test = isspace) str =
4751 let n = ref (String.length str) in
4752 while !n > 0 && test str.[!i]; do
4757 else String.sub str !i !n
4759 let trimr ?(test = isspace) str =
4760 let n = ref (String.length str) in
4761 while !n > 0 && test str.[!n-1]; do
4764 if !n = String.length str then str
4765 else String.sub str 0 !n
4767 let trim ?(test = isspace) str =
4768 trimr ~test (triml ~test str)
4770 let rec find s sub =
4771 let len = String.length s in
4772 let sublen = String.length sub in
4774 if i <= len-sublen then (
4776 if j < sublen then (
4777 if s.[i+j] = sub.[j] then loop2 (j+1)
4783 if r = -1 then loop (i+1) else r
4789 let rec replace_str s s1 s2 =
4790 let len = String.length s in
4791 let sublen = String.length s1 in
4792 let i = find s s1 in
4795 let s' = String.sub s 0 i in
4796 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4797 s' ^ s2 ^ replace_str s'' s1 s2
4800 let rec string_split sep str =
4801 let len = String.length str in
4802 let seplen = String.length sep in
4803 let i = find str sep in
4804 if i = -1 then [str]
4806 let s' = String.sub str 0 i in
4807 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4808 s' :: string_split sep s''
4811 let files_equal n1 n2 =
4812 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4813 match Sys.command cmd with
4816 | i -> failwithf "%s: failed with error code %d" cmd i
4818 let rec filter_map f = function
4822 | Some y -> y :: filter_map f xs
4823 | None -> filter_map f xs
4825 let rec find_map f = function
4826 | [] -> raise Not_found
4830 | None -> find_map f xs
4833 let rec loop i = function
4835 | x :: xs -> f i x; loop (i+1) xs
4840 let rec loop i = function
4842 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4846 let count_chars c str =
4847 let count = ref 0 in
4848 for i = 0 to String.length str - 1 do
4849 if c = String.unsafe_get str i then incr count
4853 let name_of_argt = function
4854 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4855 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4856 | FileIn n | FileOut n -> n
4858 let java_name_of_struct typ =
4859 try List.assoc typ java_structs
4862 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4864 let cols_of_struct typ =
4865 try List.assoc typ structs
4867 failwithf "cols_of_struct: unknown struct %s" typ
4869 let seq_of_test = function
4870 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4871 | TestOutputListOfDevices (s, _)
4872 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4873 | TestOutputTrue s | TestOutputFalse s
4874 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4875 | TestOutputStruct (s, _)
4876 | TestLastFail s -> s
4878 (* Handling for function flags. *)
4879 let protocol_limit_warning =
4880 "Because of the message protocol, there is a transfer limit
4881 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4883 let danger_will_robinson =
4884 "B<This command is dangerous. Without careful use you
4885 can easily destroy all your data>."
4887 let deprecation_notice flags =
4890 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4892 sprintf "This function is deprecated.
4893 In new code, use the C<%s> call instead.
4895 Deprecated functions will not be removed from the API, but the
4896 fact that they are deprecated indicates that there are problems
4897 with correct use of these functions." alt in
4902 (* Create list of optional groups. *)
4904 let h = Hashtbl.create 13 in
4906 fun (name, _, _, flags, _, _, _) ->
4910 let names = try Hashtbl.find h group with Not_found -> [] in
4911 Hashtbl.replace h group (name :: names)
4915 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4918 fun group -> group, List.sort compare (Hashtbl.find h group)
4920 List.sort (fun x y -> compare (fst x) (fst y)) groups
4922 (* Check function names etc. for consistency. *)
4923 let check_functions () =
4924 let contains_uppercase str =
4925 let len = String.length str in
4927 if i >= len then false
4930 if c >= 'A' && c <= 'Z' then true
4937 (* Check function names. *)
4939 fun (name, _, _, _, _, _, _) ->
4940 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4941 failwithf "function name %s does not need 'guestfs' prefix" name;
4943 failwithf "function name is empty";
4944 if name.[0] < 'a' || name.[0] > 'z' then
4945 failwithf "function name %s must start with lowercase a-z" name;
4946 if String.contains name '-' then
4947 failwithf "function name %s should not contain '-', use '_' instead."
4951 (* Check function parameter/return names. *)
4953 fun (name, style, _, _, _, _, _) ->
4954 let check_arg_ret_name n =
4955 if contains_uppercase n then
4956 failwithf "%s param/ret %s should not contain uppercase chars"
4958 if String.contains n '-' || String.contains n '_' then
4959 failwithf "%s param/ret %s should not contain '-' or '_'"
4962 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;
4963 if n = "int" || n = "char" || n = "short" || n = "long" then
4964 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4965 if n = "i" || n = "n" then
4966 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4967 if n = "argv" || n = "args" then
4968 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4970 (* List Haskell, OCaml and C keywords here.
4971 * http://www.haskell.org/haskellwiki/Keywords
4972 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4973 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4974 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4975 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4976 * Omitting _-containing words, since they're handled above.
4977 * Omitting the OCaml reserved word, "val", is ok,
4978 * and saves us from renaming several parameters.
4981 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4982 "char"; "class"; "const"; "constraint"; "continue"; "data";
4983 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4984 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4985 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4986 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4987 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4989 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4990 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4991 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4992 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4993 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4994 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4995 "volatile"; "when"; "where"; "while";
4997 if List.mem n reserved then
4998 failwithf "%s has param/ret using reserved word %s" name n;
5001 (match fst style with
5003 | RInt n | RInt64 n | RBool n
5004 | RConstString n | RConstOptString n | RString n
5005 | RStringList n | RStruct (n, _) | RStructList (n, _)
5006 | RHashtable n | RBufferOut n ->
5007 check_arg_ret_name n
5009 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5012 (* Check short descriptions. *)
5014 fun (name, _, _, _, _, shortdesc, _) ->
5015 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5016 failwithf "short description of %s should begin with lowercase." name;
5017 let c = shortdesc.[String.length shortdesc-1] in
5018 if c = '\n' || c = '.' then
5019 failwithf "short description of %s should not end with . or \\n." name
5022 (* Check long descriptions. *)
5024 fun (name, _, _, _, _, _, longdesc) ->
5025 if longdesc.[String.length longdesc-1] = '\n' then
5026 failwithf "long description of %s should not end with \\n." name
5029 (* Check proc_nrs. *)
5031 fun (name, _, proc_nr, _, _, _, _) ->
5032 if proc_nr <= 0 then
5033 failwithf "daemon function %s should have proc_nr > 0" name
5037 fun (name, _, proc_nr, _, _, _, _) ->
5038 if proc_nr <> -1 then
5039 failwithf "non-daemon function %s should have proc_nr -1" name
5040 ) non_daemon_functions;
5043 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5046 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5047 let rec loop = function
5050 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5052 | (name1,nr1) :: (name2,nr2) :: _ ->
5053 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5061 (* Ignore functions that have no tests. We generate a
5062 * warning when the user does 'make check' instead.
5064 | name, _, _, _, [], _, _ -> ()
5065 | name, _, _, _, tests, _, _ ->
5069 match seq_of_test test with
5071 failwithf "%s has a test containing an empty sequence" name
5072 | cmds -> List.map List.hd cmds
5074 let funcs = List.flatten funcs in
5076 let tested = List.mem name funcs in
5079 failwithf "function %s has tests but does not test itself" name
5082 (* 'pr' prints to the current output file. *)
5083 let chan = ref Pervasives.stdout
5088 let i = count_chars '\n' str in
5089 lines := !lines + i;
5090 output_string !chan str
5093 let copyright_years =
5094 let this_year = 1900 + (localtime (time ())).tm_year in
5095 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5097 (* Generate a header block in a number of standard styles. *)
5098 type comment_style =
5099 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5100 type license = GPLv2plus | LGPLv2plus
5102 let generate_header ?(extra_inputs = []) comment license =
5103 let inputs = "src/generator.ml" :: extra_inputs in
5104 let c = match comment with
5105 | CStyle -> pr "/* "; " *"
5106 | CPlusPlusStyle -> pr "// "; "//"
5107 | HashStyle -> pr "# "; "#"
5108 | OCamlStyle -> pr "(* "; " *"
5109 | HaskellStyle -> pr "{- "; " " in
5110 pr "libguestfs generated file\n";
5111 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5112 List.iter (pr "%s %s\n" c) inputs;
5113 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5115 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5119 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5120 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5121 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5122 pr "%s (at your option) any later version.\n" c;
5124 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5125 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5126 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5127 pr "%s GNU General Public License for more details.\n" c;
5129 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5130 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5131 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5134 pr "%s This library is free software; you can redistribute it and/or\n" c;
5135 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5136 pr "%s License as published by the Free Software Foundation; either\n" c;
5137 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5139 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5140 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5141 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5142 pr "%s Lesser General Public License for more details.\n" c;
5144 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5145 pr "%s License along with this library; if not, write to the Free Software\n" c;
5146 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5149 | CStyle -> pr " */\n"
5152 | OCamlStyle -> pr " *)\n"
5153 | HaskellStyle -> pr "-}\n"
5157 (* Start of main code generation functions below this line. *)
5159 (* Generate the pod documentation for the C API. *)
5160 let rec generate_actions_pod () =
5162 fun (shortname, style, _, flags, _, _, longdesc) ->
5163 if not (List.mem NotInDocs flags) then (
5164 let name = "guestfs_" ^ shortname in
5165 pr "=head2 %s\n\n" name;
5167 generate_prototype ~extern:false ~handle:"g" name style;
5169 pr "%s\n\n" longdesc;
5170 (match fst style with
5172 pr "This function returns 0 on success or -1 on error.\n\n"
5174 pr "On error this function returns -1.\n\n"
5176 pr "On error this function returns -1.\n\n"
5178 pr "This function returns a C truth value on success or -1 on error.\n\n"
5180 pr "This function returns a string, or NULL on error.
5181 The string is owned by the guest handle and must I<not> be freed.\n\n"
5182 | RConstOptString _ ->
5183 pr "This function returns a string which may be NULL.
5184 There is way to return an error from this function.
5185 The string is owned by the guest handle and must I<not> be freed.\n\n"
5187 pr "This function returns a string, or NULL on error.
5188 I<The caller must free the returned string after use>.\n\n"
5190 pr "This function returns a NULL-terminated array of strings
5191 (like L<environ(3)>), or NULL if there was an error.
5192 I<The caller must free the strings and the array after use>.\n\n"
5193 | RStruct (_, typ) ->
5194 pr "This function returns a C<struct guestfs_%s *>,
5195 or NULL if there was an error.
5196 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5197 | RStructList (_, typ) ->
5198 pr "This function returns a C<struct guestfs_%s_list *>
5199 (see E<lt>guestfs-structs.hE<gt>),
5200 or NULL if there was an error.
5201 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5203 pr "This function returns a NULL-terminated array of
5204 strings, or NULL if there was an error.
5205 The array of strings will always have length C<2n+1>, where
5206 C<n> keys and values alternate, followed by the trailing NULL entry.
5207 I<The caller must free the strings and the array after use>.\n\n"
5209 pr "This function returns a buffer, or NULL on error.
5210 The size of the returned buffer is written to C<*size_r>.
5211 I<The caller must free the returned buffer after use>.\n\n"
5213 if List.mem ProtocolLimitWarning flags then
5214 pr "%s\n\n" protocol_limit_warning;
5215 if List.mem DangerWillRobinson flags then
5216 pr "%s\n\n" danger_will_robinson;
5217 match deprecation_notice flags with
5219 | Some txt -> pr "%s\n\n" txt
5221 ) all_functions_sorted
5223 and generate_structs_pod () =
5224 (* Structs documentation. *)
5227 pr "=head2 guestfs_%s\n" typ;
5229 pr " struct guestfs_%s {\n" typ;
5232 | name, FChar -> pr " char %s;\n" name
5233 | name, FUInt32 -> pr " uint32_t %s;\n" name
5234 | name, FInt32 -> pr " int32_t %s;\n" name
5235 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5236 | name, FInt64 -> pr " int64_t %s;\n" name
5237 | name, FString -> pr " char *%s;\n" name
5239 pr " /* The next two fields describe a byte array. */\n";
5240 pr " uint32_t %s_len;\n" name;
5241 pr " char *%s;\n" name
5243 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5244 pr " char %s[32];\n" name
5245 | name, FOptPercent ->
5246 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5247 pr " float %s;\n" name
5251 pr " struct guestfs_%s_list {\n" typ;
5252 pr " uint32_t len; /* Number of elements in list. */\n";
5253 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5256 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5257 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5262 and generate_availability_pod () =
5263 (* Availability documentation. *)
5267 fun (group, functions) ->
5268 pr "=item B<%s>\n" group;
5270 pr "The following functions:\n";
5271 List.iter (pr "L</guestfs_%s>\n") functions;
5277 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5278 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5280 * We have to use an underscore instead of a dash because otherwise
5281 * rpcgen generates incorrect code.
5283 * This header is NOT exported to clients, but see also generate_structs_h.
5285 and generate_xdr () =
5286 generate_header CStyle LGPLv2plus;
5288 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5289 pr "typedef string str<>;\n";
5292 (* Internal structures. *)
5296 pr "struct guestfs_int_%s {\n" typ;
5298 | name, FChar -> pr " char %s;\n" name
5299 | name, FString -> pr " string %s<>;\n" name
5300 | name, FBuffer -> pr " opaque %s<>;\n" name
5301 | name, FUUID -> pr " opaque %s[32];\n" name
5302 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5303 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5304 | name, FOptPercent -> pr " float %s;\n" name
5308 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5313 fun (shortname, style, _, _, _, _, _) ->
5314 let name = "guestfs_" ^ shortname in
5316 (match snd style with
5319 pr "struct %s_args {\n" name;
5322 | Pathname n | Device n | Dev_or_Path n | String n ->
5323 pr " string %s<>;\n" n
5324 | OptString n -> pr " str *%s;\n" n
5325 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5326 | Bool n -> pr " bool %s;\n" n
5327 | Int n -> pr " int %s;\n" n
5328 | Int64 n -> pr " hyper %s;\n" n
5329 | FileIn _ | FileOut _ -> ()
5333 (match fst style with
5336 pr "struct %s_ret {\n" name;
5340 pr "struct %s_ret {\n" name;
5341 pr " hyper %s;\n" n;
5344 pr "struct %s_ret {\n" name;
5347 | RConstString _ | RConstOptString _ ->
5348 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5350 pr "struct %s_ret {\n" name;
5351 pr " string %s<>;\n" n;
5354 pr "struct %s_ret {\n" name;
5355 pr " str %s<>;\n" n;
5357 | RStruct (n, typ) ->
5358 pr "struct %s_ret {\n" name;
5359 pr " guestfs_int_%s %s;\n" typ n;
5361 | RStructList (n, typ) ->
5362 pr "struct %s_ret {\n" name;
5363 pr " guestfs_int_%s_list %s;\n" typ n;
5366 pr "struct %s_ret {\n" name;
5367 pr " str %s<>;\n" n;
5370 pr "struct %s_ret {\n" name;
5371 pr " opaque %s<>;\n" n;
5376 (* Table of procedure numbers. *)
5377 pr "enum guestfs_procedure {\n";
5379 fun (shortname, _, proc_nr, _, _, _, _) ->
5380 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5382 pr " GUESTFS_PROC_NR_PROCS\n";
5386 (* Having to choose a maximum message size is annoying for several
5387 * reasons (it limits what we can do in the API), but it (a) makes
5388 * the protocol a lot simpler, and (b) provides a bound on the size
5389 * of the daemon which operates in limited memory space.
5391 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5394 (* Message header, etc. *)
5396 /* The communication protocol is now documented in the guestfs(3)
5400 const GUESTFS_PROGRAM = 0x2000F5F5;
5401 const GUESTFS_PROTOCOL_VERSION = 1;
5403 /* These constants must be larger than any possible message length. */
5404 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5405 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5407 enum guestfs_message_direction {
5408 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5409 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5412 enum guestfs_message_status {
5413 GUESTFS_STATUS_OK = 0,
5414 GUESTFS_STATUS_ERROR = 1
5417 const GUESTFS_ERROR_LEN = 256;
5419 struct guestfs_message_error {
5420 string error_message<GUESTFS_ERROR_LEN>;
5423 struct guestfs_message_header {
5424 unsigned prog; /* GUESTFS_PROGRAM */
5425 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5426 guestfs_procedure proc; /* GUESTFS_PROC_x */
5427 guestfs_message_direction direction;
5428 unsigned serial; /* message serial number */
5429 guestfs_message_status status;
5432 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5434 struct guestfs_chunk {
5435 int cancel; /* if non-zero, transfer is cancelled */
5436 /* data size is 0 bytes if the transfer has finished successfully */
5437 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5441 (* Generate the guestfs-structs.h file. *)
5442 and generate_structs_h () =
5443 generate_header CStyle LGPLv2plus;
5445 (* This is a public exported header file containing various
5446 * structures. The structures are carefully written to have
5447 * exactly the same in-memory format as the XDR structures that
5448 * we use on the wire to the daemon. The reason for creating
5449 * copies of these structures here is just so we don't have to
5450 * export the whole of guestfs_protocol.h (which includes much
5451 * unrelated and XDR-dependent stuff that we don't want to be
5452 * public, or required by clients).
5454 * To reiterate, we will pass these structures to and from the
5455 * client with a simple assignment or memcpy, so the format
5456 * must be identical to what rpcgen / the RFC defines.
5459 (* Public structures. *)
5462 pr "struct guestfs_%s {\n" typ;
5465 | name, FChar -> pr " char %s;\n" name
5466 | name, FString -> pr " char *%s;\n" name
5468 pr " uint32_t %s_len;\n" name;
5469 pr " char *%s;\n" name
5470 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5471 | name, FUInt32 -> pr " uint32_t %s;\n" name
5472 | name, FInt32 -> pr " int32_t %s;\n" name
5473 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5474 | name, FInt64 -> pr " int64_t %s;\n" name
5475 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5479 pr "struct guestfs_%s_list {\n" typ;
5480 pr " uint32_t len;\n";
5481 pr " struct guestfs_%s *val;\n" typ;
5484 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5485 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5489 (* Generate the guestfs-actions.h file. *)
5490 and generate_actions_h () =
5491 generate_header CStyle LGPLv2plus;
5493 fun (shortname, style, _, _, _, _, _) ->
5494 let name = "guestfs_" ^ shortname in
5495 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5499 (* Generate the guestfs-internal-actions.h file. *)
5500 and generate_internal_actions_h () =
5501 generate_header CStyle LGPLv2plus;
5503 fun (shortname, style, _, _, _, _, _) ->
5504 let name = "guestfs__" ^ shortname in
5505 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5507 ) non_daemon_functions
5509 (* Generate the client-side dispatch stubs. *)
5510 and generate_client_actions () =
5511 generate_header CStyle LGPLv2plus;
5518 #include <inttypes.h>
5520 #include \"guestfs.h\"
5521 #include \"guestfs-internal.h\"
5522 #include \"guestfs-internal-actions.h\"
5523 #include \"guestfs_protocol.h\"
5525 #define error guestfs_error
5526 //#define perrorf guestfs_perrorf
5527 #define safe_malloc guestfs_safe_malloc
5528 #define safe_realloc guestfs_safe_realloc
5529 //#define safe_strdup guestfs_safe_strdup
5530 #define safe_memdup guestfs_safe_memdup
5532 /* Check the return message from a call for validity. */
5534 check_reply_header (guestfs_h *g,
5535 const struct guestfs_message_header *hdr,
5536 unsigned int proc_nr, unsigned int serial)
5538 if (hdr->prog != GUESTFS_PROGRAM) {
5539 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5542 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5543 error (g, \"wrong protocol version (%%d/%%d)\",
5544 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5547 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5548 error (g, \"unexpected message direction (%%d/%%d)\",
5549 hdr->direction, GUESTFS_DIRECTION_REPLY);
5552 if (hdr->proc != proc_nr) {
5553 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5556 if (hdr->serial != serial) {
5557 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5564 /* Check we are in the right state to run a high-level action. */
5566 check_state (guestfs_h *g, const char *caller)
5568 if (!guestfs__is_ready (g)) {
5569 if (guestfs__is_config (g) || guestfs__is_launching (g))
5570 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5573 error (g, \"%%s called from the wrong state, %%d != READY\",
5574 caller, guestfs__get_state (g));
5582 (* Generate code to generate guestfish call traces. *)
5583 let trace_call shortname style =
5584 pr " if (guestfs__get_trace (g)) {\n";
5587 List.exists (function
5588 | StringList _ | DeviceList _ -> true
5589 | _ -> false) (snd style) in
5595 pr " printf (\"%s\");\n" shortname;
5598 | String n (* strings *)
5604 (* guestfish doesn't support string escaping, so neither do we *)
5605 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5606 | OptString n -> (* string option *)
5607 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5608 pr " else printf (\" null\");\n"
5610 | DeviceList n -> (* string list *)
5611 pr " putchar (' ');\n";
5612 pr " putchar ('\"');\n";
5613 pr " for (i = 0; %s[i]; ++i) {\n" n;
5614 pr " if (i > 0) putchar (' ');\n";
5615 pr " fputs (%s[i], stdout);\n" n;
5617 pr " putchar ('\"');\n";
5618 | Bool n -> (* boolean *)
5619 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5620 | Int n -> (* int *)
5621 pr " printf (\" %%d\", %s);\n" n
5623 pr " printf (\" %%\" PRIi64, %s);\n" n
5625 pr " putchar ('\\n');\n";
5630 (* For non-daemon functions, generate a wrapper around each function. *)
5632 fun (shortname, style, _, _, _, _, _) ->
5633 let name = "guestfs_" ^ shortname in
5635 generate_prototype ~extern:false ~semicolon:false ~newline:true
5636 ~handle:"g" name style;
5638 trace_call shortname style;
5639 pr " return guestfs__%s " shortname;
5640 generate_c_call_args ~handle:"g" style;
5644 ) non_daemon_functions;
5646 (* Client-side stubs for each function. *)
5648 fun (shortname, style, _, _, _, _, _) ->
5649 let name = "guestfs_" ^ shortname in
5651 (* Generate the action stub. *)
5652 generate_prototype ~extern:false ~semicolon:false ~newline:true
5653 ~handle:"g" name style;
5656 match fst style with
5657 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5658 | RConstString _ | RConstOptString _ ->
5659 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5660 | RString _ | RStringList _
5661 | RStruct _ | RStructList _
5662 | RHashtable _ | RBufferOut _ ->
5667 (match snd style with
5669 | _ -> pr " struct %s_args args;\n" name
5672 pr " guestfs_message_header hdr;\n";
5673 pr " guestfs_message_error err;\n";
5675 match fst style with
5677 | RConstString _ | RConstOptString _ ->
5678 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5680 | RBool _ | RString _ | RStringList _
5681 | RStruct _ | RStructList _
5682 | RHashtable _ | RBufferOut _ ->
5683 pr " struct %s_ret ret;\n" name;
5686 pr " int serial;\n";
5689 trace_call shortname style;
5690 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5691 pr " guestfs___set_busy (g);\n";
5694 (* Send the main header and arguments. *)
5695 (match snd style with
5697 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5698 (String.uppercase shortname)
5702 | Pathname n | Device n | Dev_or_Path n | String n ->
5703 pr " args.%s = (char *) %s;\n" n n
5705 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5706 | StringList n | DeviceList n ->
5707 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5708 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5710 pr " args.%s = %s;\n" n n
5712 pr " args.%s = %s;\n" n n
5714 pr " args.%s = %s;\n" n n
5715 | FileIn _ | FileOut _ -> ()
5717 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5718 (String.uppercase shortname);
5719 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5722 pr " if (serial == -1) {\n";
5723 pr " guestfs___end_busy (g);\n";
5724 pr " return %s;\n" error_code;
5728 (* Send any additional files (FileIn) requested. *)
5729 let need_read_reply_label = ref false in
5733 pr " r = guestfs___send_file (g, %s);\n" n;
5734 pr " if (r == -1) {\n";
5735 pr " guestfs___end_busy (g);\n";
5736 pr " return %s;\n" error_code;
5738 pr " if (r == -2) /* daemon cancelled */\n";
5739 pr " goto read_reply;\n";
5740 need_read_reply_label := true;
5745 (* Wait for the reply from the remote end. *)
5746 if !need_read_reply_label then pr " read_reply:\n";
5747 pr " memset (&hdr, 0, sizeof hdr);\n";
5748 pr " memset (&err, 0, sizeof err);\n";
5749 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5751 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5755 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5758 pr " if (r == -1) {\n";
5759 pr " guestfs___end_busy (g);\n";
5760 pr " return %s;\n" error_code;
5764 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5765 (String.uppercase shortname);
5766 pr " guestfs___end_busy (g);\n";
5767 pr " return %s;\n" error_code;
5771 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5772 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5773 pr " free (err.error_message);\n";
5774 pr " guestfs___end_busy (g);\n";
5775 pr " return %s;\n" error_code;
5779 (* Expecting to receive further files (FileOut)? *)
5783 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5784 pr " guestfs___end_busy (g);\n";
5785 pr " return %s;\n" error_code;
5791 pr " guestfs___end_busy (g);\n";
5793 (match fst style with
5794 | RErr -> pr " return 0;\n"
5795 | RInt n | RInt64 n | RBool n ->
5796 pr " return ret.%s;\n" n
5797 | RConstString _ | RConstOptString _ ->
5798 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5800 pr " return ret.%s; /* caller will free */\n" n
5801 | RStringList n | RHashtable n ->
5802 pr " /* caller will free this, but we need to add a NULL entry */\n";
5803 pr " ret.%s.%s_val =\n" n n;
5804 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5805 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5807 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5808 pr " return ret.%s.%s_val;\n" n n
5810 pr " /* caller will free this */\n";
5811 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5812 | RStructList (n, _) ->
5813 pr " /* caller will free this */\n";
5814 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5816 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5817 pr " * _val might be NULL here. To make the API saner for\n";
5818 pr " * callers, we turn this case into a unique pointer (using\n";
5819 pr " * malloc(1)).\n";
5821 pr " if (ret.%s.%s_len > 0) {\n" n n;
5822 pr " *size_r = ret.%s.%s_len;\n" n n;
5823 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5825 pr " free (ret.%s.%s_val);\n" n n;
5826 pr " char *p = safe_malloc (g, 1);\n";
5827 pr " *size_r = ret.%s.%s_len;\n" n n;
5835 (* Functions to free structures. *)
5836 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5837 pr " * structure format is identical to the XDR format. See note in\n";
5838 pr " * generator.ml.\n";
5845 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5847 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5853 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5855 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5862 (* Generate daemon/actions.h. *)
5863 and generate_daemon_actions_h () =
5864 generate_header CStyle GPLv2plus;
5866 pr "#include \"../src/guestfs_protocol.h\"\n";
5870 fun (name, style, _, _, _, _, _) ->
5872 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5876 (* Generate the linker script which controls the visibility of
5877 * symbols in the public ABI and ensures no other symbols get
5878 * exported accidentally.
5880 and generate_linker_script () =
5881 generate_header HashStyle GPLv2plus;
5886 "guestfs_get_error_handler";
5887 "guestfs_get_out_of_memory_handler";
5888 "guestfs_last_error";
5889 "guestfs_set_error_handler";
5890 "guestfs_set_launch_done_callback";
5891 "guestfs_set_log_message_callback";
5892 "guestfs_set_out_of_memory_handler";
5893 "guestfs_set_subprocess_quit_callback";
5895 (* Unofficial parts of the API: the bindings code use these
5896 * functions, so it is useful to export them.
5898 "guestfs_safe_calloc";
5899 "guestfs_safe_malloc";
5902 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5906 List.map (fun (typ, _) ->
5907 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5910 let globals = List.sort compare (globals @ functions @ structs) in
5914 List.iter (pr " %s;\n") globals;
5921 (* Generate the server-side stubs. *)
5922 and generate_daemon_actions () =
5923 generate_header CStyle GPLv2plus;
5925 pr "#include <config.h>\n";
5927 pr "#include <stdio.h>\n";
5928 pr "#include <stdlib.h>\n";
5929 pr "#include <string.h>\n";
5930 pr "#include <inttypes.h>\n";
5931 pr "#include <rpc/types.h>\n";
5932 pr "#include <rpc/xdr.h>\n";
5934 pr "#include \"daemon.h\"\n";
5935 pr "#include \"c-ctype.h\"\n";
5936 pr "#include \"../src/guestfs_protocol.h\"\n";
5937 pr "#include \"actions.h\"\n";
5941 fun (name, style, _, _, _, _, _) ->
5942 (* Generate server-side stubs. *)
5943 pr "static void %s_stub (XDR *xdr_in)\n" name;
5946 match fst style with
5947 | RErr | RInt _ -> pr " int r;\n"; "-1"
5948 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5949 | RBool _ -> pr " int r;\n"; "-1"
5950 | RConstString _ | RConstOptString _ ->
5951 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5952 | RString _ -> pr " char *r;\n"; "NULL"
5953 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5954 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5955 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5957 pr " size_t size = 1;\n";
5961 (match snd style with
5964 pr " struct guestfs_%s_args args;\n" name;
5967 | Device n | Dev_or_Path n
5970 | OptString n -> pr " char *%s;\n" n
5971 | StringList n | DeviceList n -> pr " char **%s;\n" n
5972 | Bool n -> pr " int %s;\n" n
5973 | Int n -> pr " int %s;\n" n
5974 | Int64 n -> pr " int64_t %s;\n" n
5975 | FileIn _ | FileOut _ -> ()
5980 (match snd style with
5983 pr " memset (&args, 0, sizeof args);\n";
5985 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5986 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5990 pr " char *%s = args.%s;\n" n n
5992 let pr_list_handling_code n =
5993 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5994 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5995 pr " if (%s == NULL) {\n" n;
5996 pr " reply_with_perror (\"realloc\");\n";
5999 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6000 pr " args.%s.%s_val = %s;\n" n n n;
6006 pr " ABS_PATH (%s, goto done);\n" n;
6009 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6012 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6013 | String n -> pr_args n
6014 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6016 pr_list_handling_code n;
6018 pr_list_handling_code n;
6019 pr " /* Ensure that each is a device,\n";
6020 pr " * and perform device name translation. */\n";
6021 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6022 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6024 | Bool n -> pr " %s = args.%s;\n" n n
6025 | Int n -> pr " %s = args.%s;\n" n n
6026 | Int64 n -> pr " %s = args.%s;\n" n n
6027 | FileIn _ | FileOut _ -> ()
6033 (* this is used at least for do_equal *)
6034 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6035 (* Emit NEED_ROOT just once, even when there are two or
6036 more Pathname args *)
6037 pr " NEED_ROOT (goto done);\n";
6040 (* Don't want to call the impl with any FileIn or FileOut
6041 * parameters, since these go "outside" the RPC protocol.
6044 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6046 pr " r = do_%s " name;
6047 generate_c_call_args (fst style, args');
6050 (match fst style with
6051 | RErr | RInt _ | RInt64 _ | RBool _
6052 | RConstString _ | RConstOptString _
6053 | RString _ | RStringList _ | RHashtable _
6054 | RStruct (_, _) | RStructList (_, _) ->
6055 pr " if (r == %s)\n" error_code;
6056 pr " /* do_%s has already called reply_with_error */\n" name;
6060 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6061 pr " * an ordinary zero-length buffer), so be careful ...\n";
6063 pr " if (size == 1 && r == %s)\n" error_code;
6064 pr " /* do_%s has already called reply_with_error */\n" name;
6069 (* If there are any FileOut parameters, then the impl must
6070 * send its own reply.
6073 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6075 pr " /* do_%s has already sent a reply */\n" name
6077 match fst style with
6078 | RErr -> pr " reply (NULL, NULL);\n"
6079 | RInt n | RInt64 n | RBool n ->
6080 pr " struct guestfs_%s_ret ret;\n" name;
6081 pr " ret.%s = r;\n" n;
6082 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6084 | RConstString _ | RConstOptString _ ->
6085 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6087 pr " struct guestfs_%s_ret ret;\n" name;
6088 pr " ret.%s = r;\n" n;
6089 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6092 | RStringList n | RHashtable n ->
6093 pr " struct guestfs_%s_ret ret;\n" name;
6094 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6095 pr " ret.%s.%s_val = r;\n" n n;
6096 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6098 pr " free_strings (r);\n"
6100 pr " struct guestfs_%s_ret ret;\n" name;
6101 pr " ret.%s = *r;\n" n;
6102 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6104 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6106 | RStructList (n, _) ->
6107 pr " struct guestfs_%s_ret ret;\n" name;
6108 pr " ret.%s = *r;\n" n;
6109 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6111 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6114 pr " struct guestfs_%s_ret ret;\n" name;
6115 pr " ret.%s.%s_val = r;\n" n n;
6116 pr " ret.%s.%s_len = size;\n" n n;
6117 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6122 (* Free the args. *)
6123 (match snd style with
6128 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6135 (* Dispatch function. *)
6136 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6138 pr " switch (proc_nr) {\n";
6141 fun (name, style, _, _, _, _, _) ->
6142 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6143 pr " %s_stub (xdr_in);\n" name;
6148 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";
6153 (* LVM columns and tokenization functions. *)
6154 (* XXX This generates crap code. We should rethink how we
6160 pr "static const char *lvm_%s_cols = \"%s\";\n"
6161 typ (String.concat "," (List.map fst cols));
6164 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6166 pr " char *tok, *p, *next;\n";
6170 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6173 pr " if (!str) {\n";
6174 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6177 pr " if (!*str || c_isspace (*str)) {\n";
6178 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6183 fun (name, coltype) ->
6184 pr " if (!tok) {\n";
6185 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6188 pr " p = strchrnul (tok, ',');\n";
6189 pr " if (*p) next = p+1; else next = NULL;\n";
6190 pr " *p = '\\0';\n";
6193 pr " r->%s = strdup (tok);\n" name;
6194 pr " if (r->%s == NULL) {\n" name;
6195 pr " perror (\"strdup\");\n";
6199 pr " for (i = j = 0; i < 32; ++j) {\n";
6200 pr " if (tok[j] == '\\0') {\n";
6201 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6203 pr " } else if (tok[j] != '-')\n";
6204 pr " r->%s[i++] = tok[j];\n" name;
6207 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6208 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6212 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6213 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6217 pr " if (tok[0] == '\\0')\n";
6218 pr " r->%s = -1;\n" name;
6219 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6220 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6223 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6224 assert false (* can never be an LVM column *)
6226 pr " tok = next;\n";
6229 pr " if (tok != NULL) {\n";
6230 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6237 pr "guestfs_int_lvm_%s_list *\n" typ;
6238 pr "parse_command_line_%ss (void)\n" typ;
6240 pr " char *out, *err;\n";
6241 pr " char *p, *pend;\n";
6243 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6244 pr " void *newp;\n";
6246 pr " ret = malloc (sizeof *ret);\n";
6247 pr " if (!ret) {\n";
6248 pr " reply_with_perror (\"malloc\");\n";
6249 pr " return NULL;\n";
6252 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6253 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6255 pr " r = command (&out, &err,\n";
6256 pr " \"lvm\", \"%ss\",\n" typ;
6257 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6258 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6259 pr " if (r == -1) {\n";
6260 pr " reply_with_error (\"%%s\", err);\n";
6261 pr " free (out);\n";
6262 pr " free (err);\n";
6263 pr " free (ret);\n";
6264 pr " return NULL;\n";
6267 pr " free (err);\n";
6269 pr " /* Tokenize each line of the output. */\n";
6272 pr " while (p) {\n";
6273 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6274 pr " if (pend) {\n";
6275 pr " *pend = '\\0';\n";
6279 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6282 pr " if (!*p) { /* Empty line? Skip it. */\n";
6287 pr " /* Allocate some space to store this next entry. */\n";
6288 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6289 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6290 pr " if (newp == NULL) {\n";
6291 pr " reply_with_perror (\"realloc\");\n";
6292 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6293 pr " free (ret);\n";
6294 pr " free (out);\n";
6295 pr " return NULL;\n";
6297 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6299 pr " /* Tokenize the next entry. */\n";
6300 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6301 pr " if (r == -1) {\n";
6302 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6303 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6304 pr " free (ret);\n";
6305 pr " free (out);\n";
6306 pr " return NULL;\n";
6313 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6315 pr " free (out);\n";
6316 pr " return ret;\n";
6319 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6321 (* Generate a list of function names, for debugging in the daemon.. *)
6322 and generate_daemon_names () =
6323 generate_header CStyle GPLv2plus;
6325 pr "#include <config.h>\n";
6327 pr "#include \"daemon.h\"\n";
6330 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6331 pr "const char *function_names[] = {\n";
6333 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6337 (* Generate the optional groups for the daemon to implement
6338 * guestfs_available.
6340 and generate_daemon_optgroups_c () =
6341 generate_header CStyle GPLv2plus;
6343 pr "#include <config.h>\n";
6345 pr "#include \"daemon.h\"\n";
6346 pr "#include \"optgroups.h\"\n";
6349 pr "struct optgroup optgroups[] = {\n";
6352 pr " { \"%s\", optgroup_%s_available },\n" group group
6354 pr " { NULL, NULL }\n";
6357 and generate_daemon_optgroups_h () =
6358 generate_header CStyle GPLv2plus;
6362 pr "extern int optgroup_%s_available (void);\n" group
6365 (* Generate the tests. *)
6366 and generate_tests () =
6367 generate_header CStyle GPLv2plus;
6374 #include <sys/types.h>
6377 #include \"guestfs.h\"
6378 #include \"guestfs-internal.h\"
6380 static guestfs_h *g;
6381 static int suppress_error = 0;
6383 static void print_error (guestfs_h *g, void *data, const char *msg)
6385 if (!suppress_error)
6386 fprintf (stderr, \"%%s\\n\", msg);
6389 /* FIXME: nearly identical code appears in fish.c */
6390 static void print_strings (char *const *argv)
6394 for (argc = 0; argv[argc] != NULL; ++argc)
6395 printf (\"\\t%%s\\n\", argv[argc]);
6399 static void print_table (char const *const *argv)
6403 for (i = 0; argv[i] != NULL; i += 2)
6404 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6410 (* Generate a list of commands which are not tested anywhere. *)
6411 pr "static void no_test_warnings (void)\n";
6414 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6416 fun (_, _, _, _, tests, _, _) ->
6417 let tests = filter_map (
6419 | (_, (Always|If _|Unless _), test) -> Some test
6420 | (_, Disabled, _) -> None
6422 let seq = List.concat (List.map seq_of_test tests) in
6423 let cmds_tested = List.map List.hd seq in
6424 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6428 fun (name, _, _, _, _, _, _) ->
6429 if not (Hashtbl.mem hash name) then
6430 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6436 (* Generate the actual tests. Note that we generate the tests
6437 * in reverse order, deliberately, so that (in general) the
6438 * newest tests run first. This makes it quicker and easier to
6443 fun (name, _, _, flags, tests, _, _) ->
6444 mapi (generate_one_test name flags) tests
6445 ) (List.rev all_functions) in
6446 let test_names = List.concat test_names in
6447 let nr_tests = List.length test_names in
6450 int main (int argc, char *argv[])
6453 unsigned long int n_failed = 0;
6454 const char *filename;
6456 int nr_tests, test_num = 0;
6458 setbuf (stdout, NULL);
6460 no_test_warnings ();
6462 g = guestfs_create ();
6464 printf (\"guestfs_create FAILED\\n\");
6465 exit (EXIT_FAILURE);
6468 guestfs_set_error_handler (g, print_error, NULL);
6470 guestfs_set_path (g, \"../appliance\");
6472 filename = \"test1.img\";
6473 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6476 exit (EXIT_FAILURE);
6478 if (lseek (fd, %d, SEEK_SET) == -1) {
6482 exit (EXIT_FAILURE);
6484 if (write (fd, &c, 1) == -1) {
6488 exit (EXIT_FAILURE);
6490 if (close (fd) == -1) {
6493 exit (EXIT_FAILURE);
6495 if (guestfs_add_drive (g, filename) == -1) {
6496 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6497 exit (EXIT_FAILURE);
6500 filename = \"test2.img\";
6501 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6504 exit (EXIT_FAILURE);
6506 if (lseek (fd, %d, SEEK_SET) == -1) {
6510 exit (EXIT_FAILURE);
6512 if (write (fd, &c, 1) == -1) {
6516 exit (EXIT_FAILURE);
6518 if (close (fd) == -1) {
6521 exit (EXIT_FAILURE);
6523 if (guestfs_add_drive (g, filename) == -1) {
6524 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6525 exit (EXIT_FAILURE);
6528 filename = \"test3.img\";
6529 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6532 exit (EXIT_FAILURE);
6534 if (lseek (fd, %d, SEEK_SET) == -1) {
6538 exit (EXIT_FAILURE);
6540 if (write (fd, &c, 1) == -1) {
6544 exit (EXIT_FAILURE);
6546 if (close (fd) == -1) {
6549 exit (EXIT_FAILURE);
6551 if (guestfs_add_drive (g, filename) == -1) {
6552 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6553 exit (EXIT_FAILURE);
6556 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6557 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6558 exit (EXIT_FAILURE);
6561 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6564 if (guestfs_launch (g) == -1) {
6565 printf (\"guestfs_launch FAILED\\n\");
6566 exit (EXIT_FAILURE);
6569 /* Cancel previous alarm. */
6574 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6578 pr " test_num++;\n";
6579 pr " if (guestfs_get_verbose (g))\n";
6580 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6581 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6582 pr " if (%s () == -1) {\n" test_name;
6583 pr " printf (\"%s FAILED\\n\");\n" test_name;
6584 pr " n_failed++;\n";
6589 pr " guestfs_close (g);\n";
6590 pr " unlink (\"test1.img\");\n";
6591 pr " unlink (\"test2.img\");\n";
6592 pr " unlink (\"test3.img\");\n";
6595 pr " if (n_failed > 0) {\n";
6596 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6597 pr " exit (EXIT_FAILURE);\n";
6601 pr " exit (EXIT_SUCCESS);\n";
6604 and generate_one_test name flags i (init, prereq, test) =
6605 let test_name = sprintf "test_%s_%d" name i in
6608 static int %s_skip (void)
6612 str = getenv (\"TEST_ONLY\");
6614 return strstr (str, \"%s\") == NULL;
6615 str = getenv (\"SKIP_%s\");
6616 if (str && STREQ (str, \"1\")) return 1;
6617 str = getenv (\"SKIP_TEST_%s\");
6618 if (str && STREQ (str, \"1\")) return 1;
6622 " test_name name (String.uppercase test_name) (String.uppercase name);
6625 | Disabled | Always -> ()
6626 | If code | Unless code ->
6627 pr "static int %s_prereq (void)\n" test_name;
6635 static int %s (void)
6638 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6642 " test_name test_name test_name;
6644 (* Optional functions should only be tested if the relevant
6645 * support is available in the daemon.
6651 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6653 pr " suppress_error = 1;\n";
6654 pr " r = guestfs_available (g, (char **) groups);\n";
6655 pr " suppress_error = 0;\n";
6656 pr " if (r == -1) {\n";
6657 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6666 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6668 pr " if (! %s_prereq ()) {\n" test_name;
6669 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6673 generate_one_test_body name i test_name init test;
6675 pr " if (%s_prereq ()) {\n" test_name;
6676 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6680 generate_one_test_body name i test_name init test;
6682 generate_one_test_body name i test_name init test
6690 and generate_one_test_body name i test_name init test =
6692 | InitNone (* XXX at some point, InitNone and InitEmpty became
6693 * folded together as the same thing. Really we should
6694 * make InitNone do nothing at all, but the tests may
6695 * need to be checked to make sure this is OK.
6698 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6699 List.iter (generate_test_command_call test_name)
6700 [["blockdev_setrw"; "/dev/sda"];
6704 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6705 List.iter (generate_test_command_call test_name)
6706 [["blockdev_setrw"; "/dev/sda"];
6709 ["part_disk"; "/dev/sda"; "mbr"]]
6711 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6712 List.iter (generate_test_command_call test_name)
6713 [["blockdev_setrw"; "/dev/sda"];
6716 ["part_disk"; "/dev/sda"; "mbr"];
6717 ["mkfs"; "ext2"; "/dev/sda1"];
6718 ["mount_options"; ""; "/dev/sda1"; "/"]]
6719 | InitBasicFSonLVM ->
6720 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6722 List.iter (generate_test_command_call test_name)
6723 [["blockdev_setrw"; "/dev/sda"];
6726 ["part_disk"; "/dev/sda"; "mbr"];
6727 ["pvcreate"; "/dev/sda1"];
6728 ["vgcreate"; "VG"; "/dev/sda1"];
6729 ["lvcreate"; "LV"; "VG"; "8"];
6730 ["mkfs"; "ext2"; "/dev/VG/LV"];
6731 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6733 pr " /* InitISOFS for %s */\n" test_name;
6734 List.iter (generate_test_command_call test_name)
6735 [["blockdev_setrw"; "/dev/sda"];
6738 ["mount_ro"; "/dev/sdd"; "/"]]
6741 let get_seq_last = function
6743 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6746 let seq = List.rev seq in
6747 List.rev (List.tl seq), List.hd seq
6752 pr " /* TestRun for %s (%d) */\n" name i;
6753 List.iter (generate_test_command_call test_name) seq
6754 | TestOutput (seq, expected) ->
6755 pr " /* TestOutput for %s (%d) */\n" name i;
6756 pr " const char *expected = \"%s\";\n" (c_quote expected);
6757 let seq, last = get_seq_last seq in
6759 pr " if (STRNEQ (r, expected)) {\n";
6760 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6764 List.iter (generate_test_command_call test_name) seq;
6765 generate_test_command_call ~test test_name last
6766 | TestOutputList (seq, expected) ->
6767 pr " /* TestOutputList for %s (%d) */\n" name i;
6768 let seq, last = get_seq_last seq in
6772 pr " if (!r[%d]) {\n" i;
6773 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6774 pr " print_strings (r);\n";
6778 pr " const char *expected = \"%s\";\n" (c_quote str);
6779 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6780 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6785 pr " if (r[%d] != NULL) {\n" (List.length expected);
6786 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6788 pr " print_strings (r);\n";
6792 List.iter (generate_test_command_call test_name) seq;
6793 generate_test_command_call ~test test_name last
6794 | TestOutputListOfDevices (seq, expected) ->
6795 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6796 let seq, last = get_seq_last seq in
6800 pr " if (!r[%d]) {\n" i;
6801 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6802 pr " print_strings (r);\n";
6806 pr " const char *expected = \"%s\";\n" (c_quote str);
6807 pr " r[%d][5] = 's';\n" i;
6808 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6809 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6814 pr " if (r[%d] != NULL) {\n" (List.length expected);
6815 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6817 pr " print_strings (r);\n";
6821 List.iter (generate_test_command_call test_name) seq;
6822 generate_test_command_call ~test test_name last
6823 | TestOutputInt (seq, expected) ->
6824 pr " /* TestOutputInt for %s (%d) */\n" name i;
6825 let seq, last = get_seq_last seq in
6827 pr " if (r != %d) {\n" expected;
6828 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6834 List.iter (generate_test_command_call test_name) seq;
6835 generate_test_command_call ~test test_name last
6836 | TestOutputIntOp (seq, op, expected) ->
6837 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6838 let seq, last = get_seq_last seq in
6840 pr " if (! (r %s %d)) {\n" op expected;
6841 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6842 test_name op expected;
6847 List.iter (generate_test_command_call test_name) seq;
6848 generate_test_command_call ~test test_name last
6849 | TestOutputTrue seq ->
6850 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6851 let seq, last = get_seq_last seq in
6854 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6859 List.iter (generate_test_command_call test_name) seq;
6860 generate_test_command_call ~test test_name last
6861 | TestOutputFalse seq ->
6862 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6863 let seq, last = get_seq_last seq in
6866 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6871 List.iter (generate_test_command_call test_name) seq;
6872 generate_test_command_call ~test test_name last
6873 | TestOutputLength (seq, expected) ->
6874 pr " /* TestOutputLength for %s (%d) */\n" name i;
6875 let seq, last = get_seq_last seq in
6878 pr " for (j = 0; j < %d; ++j)\n" expected;
6879 pr " if (r[j] == NULL) {\n";
6880 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6882 pr " print_strings (r);\n";
6885 pr " if (r[j] != NULL) {\n";
6886 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6888 pr " print_strings (r);\n";
6892 List.iter (generate_test_command_call test_name) seq;
6893 generate_test_command_call ~test test_name last
6894 | TestOutputBuffer (seq, expected) ->
6895 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6896 pr " const char *expected = \"%s\";\n" (c_quote expected);
6897 let seq, last = get_seq_last seq in
6898 let len = String.length expected in
6900 pr " if (size != %d) {\n" len;
6901 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6904 pr " if (STRNEQLEN (r, expected, size)) {\n";
6905 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6909 List.iter (generate_test_command_call test_name) seq;
6910 generate_test_command_call ~test test_name last
6911 | TestOutputStruct (seq, checks) ->
6912 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6913 let seq, last = get_seq_last seq in
6917 | CompareWithInt (field, expected) ->
6918 pr " if (r->%s != %d) {\n" field expected;
6919 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6920 test_name field expected;
6921 pr " (int) r->%s);\n" field;
6924 | CompareWithIntOp (field, op, expected) ->
6925 pr " if (!(r->%s %s %d)) {\n" field op expected;
6926 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6927 test_name field op expected;
6928 pr " (int) r->%s);\n" field;
6931 | CompareWithString (field, expected) ->
6932 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6933 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6934 test_name field expected;
6935 pr " r->%s);\n" field;
6938 | CompareFieldsIntEq (field1, field2) ->
6939 pr " if (r->%s != r->%s) {\n" field1 field2;
6940 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6941 test_name field1 field2;
6942 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6945 | CompareFieldsStrEq (field1, field2) ->
6946 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6947 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6948 test_name field1 field2;
6949 pr " r->%s, r->%s);\n" field1 field2;
6954 List.iter (generate_test_command_call test_name) seq;
6955 generate_test_command_call ~test test_name last
6956 | TestLastFail seq ->
6957 pr " /* TestLastFail for %s (%d) */\n" name i;
6958 let seq, last = get_seq_last seq in
6959 List.iter (generate_test_command_call test_name) seq;
6960 generate_test_command_call test_name ~expect_error:true last
6962 (* Generate the code to run a command, leaving the result in 'r'.
6963 * If you expect to get an error then you should set expect_error:true.
6965 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6967 | [] -> assert false
6969 (* Look up the command to find out what args/ret it has. *)
6972 let _, style, _, _, _, _, _ =
6973 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6976 failwithf "%s: in test, command %s was not found" test_name name in
6978 if List.length (snd style) <> List.length args then
6979 failwithf "%s: in test, wrong number of args given to %s"
6986 | OptString n, "NULL" -> ()
6989 | Dev_or_Path n, arg
6991 | OptString n, arg ->
6992 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6996 | FileIn _, _ | FileOut _, _ -> ()
6997 | StringList n, "" | DeviceList n, "" ->
6998 pr " const char *const %s[1] = { NULL };\n" n
6999 | StringList n, arg | DeviceList n, arg ->
7000 let strs = string_split " " arg in
7003 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7005 pr " const char *const %s[] = {\n" n;
7007 fun i _ -> pr " %s_%d,\n" n i
7011 ) (List.combine (snd style) args);
7014 match fst style with
7015 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7016 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7017 | RConstString _ | RConstOptString _ ->
7018 pr " const char *r;\n"; "NULL"
7019 | RString _ -> pr " char *r;\n"; "NULL"
7020 | RStringList _ | RHashtable _ ->
7024 | RStruct (_, typ) ->
7025 pr " struct guestfs_%s *r;\n" typ; "NULL"
7026 | RStructList (_, typ) ->
7027 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7030 pr " size_t size;\n";
7033 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7034 pr " r = guestfs_%s (g" name;
7036 (* Generate the parameters. *)
7039 | OptString _, "NULL" -> pr ", NULL"
7041 | Device n, _ | Dev_or_Path n, _
7045 | FileIn _, arg | FileOut _, arg ->
7046 pr ", \"%s\"" (c_quote arg)
7047 | StringList n, _ | DeviceList n, _ ->
7048 pr ", (char **) %s" n
7051 try int_of_string arg
7052 with Failure "int_of_string" ->
7053 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7057 try Int64.of_string arg
7058 with Failure "int_of_string" ->
7059 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7062 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7063 ) (List.combine (snd style) args);
7065 (match fst style with
7066 | RBufferOut _ -> pr ", &size"
7072 if not expect_error then
7073 pr " if (r == %s)\n" error_code
7075 pr " if (r != %s)\n" error_code;
7078 (* Insert the test code. *)
7084 (match fst style with
7085 | RErr | RInt _ | RInt64 _ | RBool _
7086 | RConstString _ | RConstOptString _ -> ()
7087 | RString _ | RBufferOut _ -> pr " free (r);\n"
7088 | RStringList _ | RHashtable _ ->
7089 pr " for (i = 0; r[i] != NULL; ++i)\n";
7090 pr " free (r[i]);\n";
7092 | RStruct (_, typ) ->
7093 pr " guestfs_free_%s (r);\n" typ
7094 | RStructList (_, typ) ->
7095 pr " guestfs_free_%s_list (r);\n" typ
7101 let str = replace_str str "\r" "\\r" in
7102 let str = replace_str str "\n" "\\n" in
7103 let str = replace_str str "\t" "\\t" in
7104 let str = replace_str str "\000" "\\0" in
7107 (* Generate a lot of different functions for guestfish. *)
7108 and generate_fish_cmds () =
7109 generate_header CStyle GPLv2plus;
7113 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7115 let all_functions_sorted =
7117 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7118 ) all_functions_sorted in
7120 pr "#include <config.h>\n";
7122 pr "#include <stdio.h>\n";
7123 pr "#include <stdlib.h>\n";
7124 pr "#include <string.h>\n";
7125 pr "#include <inttypes.h>\n";
7127 pr "#include <guestfs.h>\n";
7128 pr "#include \"c-ctype.h\"\n";
7129 pr "#include \"full-write.h\"\n";
7130 pr "#include \"xstrtol.h\"\n";
7131 pr "#include \"fish.h\"\n";
7134 (* list_commands function, which implements guestfish -h *)
7135 pr "void list_commands (void)\n";
7137 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7138 pr " list_builtin_commands ();\n";
7140 fun (name, _, _, flags, _, shortdesc, _) ->
7141 let name = replace_char name '_' '-' in
7142 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7144 ) all_functions_sorted;
7145 pr " printf (\" %%s\\n\",";
7146 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7150 (* display_command function, which implements guestfish -h cmd *)
7151 pr "void display_command (const char *cmd)\n";
7154 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7155 let name2 = replace_char name '_' '-' in
7157 try find_map (function FishAlias n -> Some n | _ -> None) flags
7158 with Not_found -> name in
7159 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7161 match snd style with
7165 name2 (String.concat " " (List.map name_of_argt args)) in
7168 if List.mem ProtocolLimitWarning flags then
7169 ("\n\n" ^ protocol_limit_warning)
7172 (* For DangerWillRobinson commands, we should probably have
7173 * guestfish prompt before allowing you to use them (especially
7174 * in interactive mode). XXX
7178 if List.mem DangerWillRobinson flags then
7179 ("\n\n" ^ danger_will_robinson)
7184 match deprecation_notice flags with
7186 | Some txt -> "\n\n" ^ txt in
7188 let describe_alias =
7189 if name <> alias then
7190 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7194 pr "STRCASEEQ (cmd, \"%s\")" name;
7195 if name <> name2 then
7196 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7197 if name <> alias then
7198 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7200 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7202 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7203 "=head1 DESCRIPTION\n\n" ^
7204 longdesc ^ warnings ^ describe_alias);
7207 pr " display_builtin_command (cmd);\n";
7211 let emit_print_list_function typ =
7212 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7215 pr " unsigned int i;\n";
7217 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7218 pr " printf (\"[%%d] = {\\n\", i);\n";
7219 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7220 pr " printf (\"}\\n\");\n";
7226 (* print_* functions *)
7230 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7232 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7235 pr " unsigned int i;\n";
7241 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7243 pr " printf (\"%%s%s: \", indent);\n" name;
7244 pr " for (i = 0; i < 32; ++i)\n";
7245 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7246 pr " printf (\"\\n\");\n"
7248 pr " printf (\"%%s%s: \", indent);\n" name;
7249 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7250 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7251 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7253 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7254 pr " printf (\"\\n\");\n"
7255 | name, (FUInt64|FBytes) ->
7256 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7259 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7262 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7265 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7268 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7270 | name, FOptPercent ->
7271 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7272 typ name name typ name;
7273 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7279 (* Emit a print_TYPE_list function definition only if that function is used. *)
7282 | typ, (RStructListOnly | RStructAndList) ->
7283 (* generate the function for typ *)
7284 emit_print_list_function typ
7285 | typ, _ -> () (* empty *)
7286 ) (rstructs_used_by all_functions);
7288 (* Emit a print_TYPE function definition only if that function is used. *)
7291 | typ, (RStructOnly | RStructAndList) ->
7292 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7294 pr " print_%s_indent (%s, \"\");\n" typ typ;
7297 | typ, _ -> () (* empty *)
7298 ) (rstructs_used_by all_functions);
7300 (* run_<action> actions *)
7302 fun (name, style, _, flags, _, _, _) ->
7303 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7305 (match fst style with
7308 | RBool _ -> pr " int r;\n"
7309 | RInt64 _ -> pr " int64_t r;\n"
7310 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7311 | RString _ -> pr " char *r;\n"
7312 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7313 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7314 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7317 pr " size_t size;\n";
7325 | FileOut n -> pr " const char *%s;\n" n
7327 | Dev_or_Path n -> pr " char *%s;\n" n
7328 | StringList n | DeviceList n -> pr " char **%s;\n" n
7329 | Bool n -> pr " int %s;\n" n
7330 | Int n -> pr " int %s;\n" n
7331 | Int64 n -> pr " int64_t %s;\n" n
7334 (* Check and convert parameters. *)
7335 let argc_expected = List.length (snd style) in
7336 pr " if (argc != %d) {\n" argc_expected;
7337 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7339 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7343 let parse_integer fn fntyp rtyp range name i =
7345 pr " strtol_error xerr;\n";
7346 pr " %s r;\n" fntyp;
7348 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7349 pr " if (xerr != LONGINT_OK) {\n";
7350 pr " fprintf (stderr,\n";
7351 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7352 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7357 | Some (min, max, comment) ->
7358 pr " /* %s */\n" comment;
7359 pr " if (r < %s || r > %s) {\n" min max;
7360 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7364 pr " /* The check above should ensure this assignment does not overflow. */\n";
7366 pr " %s = r;\n" name;
7375 pr " %s = argv[%d];\n" name i
7377 | Dev_or_Path name ->
7378 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7379 pr " if (%s == NULL) return -1;\n" name
7381 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7384 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7387 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7389 | StringList name | DeviceList name ->
7390 pr " %s = parse_string_list (argv[%d]);\n" name i;
7391 pr " if (%s == NULL) return -1;\n" name;
7393 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7396 let min = "(-(2LL<<30))"
7397 and max = "((2LL<<30)-1)"
7399 "The Int type in the generator is a signed 31 bit int." in
7400 Some (min, max, comment) in
7401 parse_integer "xstrtoll" "long long" "int" range name i
7403 parse_integer "xstrtoll" "long long" "int64_t" None name i
7406 (* Call C API function. *)
7408 try find_map (function FishAction n -> Some n | _ -> None) flags
7409 with Not_found -> sprintf "guestfs_%s" name in
7411 generate_c_call_args ~handle:"g" style;
7416 | Device name | String name
7417 | OptString name | FileIn name | FileOut name | Bool name
7418 | Int name | Int64 name -> ()
7419 | Pathname name | Dev_or_Path name ->
7420 pr " free (%s);\n" name
7421 | StringList name | DeviceList name ->
7422 pr " free_strings (%s);\n" name
7425 (* Check return value for errors and display command results. *)
7426 (match fst style with
7427 | RErr -> pr " return r;\n"
7429 pr " if (r == -1) return -1;\n";
7430 pr " printf (\"%%d\\n\", r);\n";
7433 pr " if (r == -1) return -1;\n";
7434 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7437 pr " if (r == -1) return -1;\n";
7438 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7441 pr " if (r == NULL) return -1;\n";
7442 pr " printf (\"%%s\\n\", r);\n";
7444 | RConstOptString _ ->
7445 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7448 pr " if (r == NULL) return -1;\n";
7449 pr " printf (\"%%s\\n\", r);\n";
7453 pr " if (r == NULL) return -1;\n";
7454 pr " print_strings (r);\n";
7455 pr " free_strings (r);\n";
7457 | RStruct (_, typ) ->
7458 pr " if (r == NULL) return -1;\n";
7459 pr " print_%s (r);\n" typ;
7460 pr " guestfs_free_%s (r);\n" typ;
7462 | RStructList (_, typ) ->
7463 pr " if (r == NULL) return -1;\n";
7464 pr " print_%s_list (r);\n" typ;
7465 pr " guestfs_free_%s_list (r);\n" typ;
7468 pr " if (r == NULL) return -1;\n";
7469 pr " print_table (r);\n";
7470 pr " free_strings (r);\n";
7473 pr " if (r == NULL) return -1;\n";
7474 pr " if (full_write (1, r, size) != size) {\n";
7475 pr " perror (\"write\");\n";
7486 (* run_action function *)
7487 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7490 fun (name, _, _, flags, _, _, _) ->
7491 let name2 = replace_char name '_' '-' in
7493 try find_map (function FishAlias n -> Some n | _ -> None) flags
7494 with Not_found -> name in
7496 pr "STRCASEEQ (cmd, \"%s\")" name;
7497 if name <> name2 then
7498 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7499 if name <> alias then
7500 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7502 pr " return run_%s (cmd, argc, argv);\n" name;
7506 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7507 pr " if (command_num == 1)\n";
7508 pr " extended_help_message ();\n";
7515 (* Readline completion for guestfish. *)
7516 and generate_fish_completion () =
7517 generate_header CStyle GPLv2plus;
7521 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7531 #ifdef HAVE_LIBREADLINE
7532 #include <readline/readline.h>
7537 #ifdef HAVE_LIBREADLINE
7539 static const char *const commands[] = {
7540 BUILTIN_COMMANDS_FOR_COMPLETION,
7543 (* Get the commands, including the aliases. They don't need to be
7544 * sorted - the generator() function just does a dumb linear search.
7548 fun (name, _, _, flags, _, _, _) ->
7549 let name2 = replace_char name '_' '-' in
7551 try find_map (function FishAlias n -> Some n | _ -> None) flags
7552 with Not_found -> name in
7554 if name <> alias then [name2; alias] else [name2]
7556 let commands = List.flatten commands in
7558 List.iter (pr " \"%s\",\n") commands;
7564 generator (const char *text, int state)
7566 static int index, len;
7571 len = strlen (text);
7574 rl_attempted_completion_over = 1;
7576 while ((name = commands[index]) != NULL) {
7578 if (STRCASEEQLEN (name, text, len))
7579 return strdup (name);
7585 #endif /* HAVE_LIBREADLINE */
7587 #ifdef HAVE_RL_COMPLETION_MATCHES
7588 #define RL_COMPLETION_MATCHES rl_completion_matches
7590 #ifdef HAVE_COMPLETION_MATCHES
7591 #define RL_COMPLETION_MATCHES completion_matches
7593 #endif /* else just fail if we don't have either symbol */
7596 do_completion (const char *text, int start, int end)
7598 char **matches = NULL;
7600 #ifdef HAVE_LIBREADLINE
7601 rl_completion_append_character = ' ';
7604 matches = RL_COMPLETION_MATCHES (text, generator);
7605 else if (complete_dest_paths)
7606 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7613 (* Generate the POD documentation for guestfish. *)
7614 and generate_fish_actions_pod () =
7615 let all_functions_sorted =
7617 fun (_, _, _, flags, _, _, _) ->
7618 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7619 ) all_functions_sorted in
7621 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7624 fun (name, style, _, flags, _, _, longdesc) ->
7626 Str.global_substitute rex (
7629 try Str.matched_group 1 s
7631 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7632 "C<" ^ replace_char sub '_' '-' ^ ">"
7634 let name = replace_char name '_' '-' in
7636 try find_map (function FishAlias n -> Some n | _ -> None) flags
7637 with Not_found -> name in
7639 pr "=head2 %s" name;
7640 if name <> alias then
7647 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7648 | OptString n -> pr " %s" n
7649 | StringList n | DeviceList n -> pr " '%s ...'" n
7650 | Bool _ -> pr " true|false"
7651 | Int n -> pr " %s" n
7652 | Int64 n -> pr " %s" n
7653 | FileIn n | FileOut n -> pr " (%s|-)" n
7657 pr "%s\n\n" longdesc;
7659 if List.exists (function FileIn _ | FileOut _ -> true
7660 | _ -> false) (snd style) then
7661 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7663 if List.mem ProtocolLimitWarning flags then
7664 pr "%s\n\n" protocol_limit_warning;
7666 if List.mem DangerWillRobinson flags then
7667 pr "%s\n\n" danger_will_robinson;
7669 match deprecation_notice flags with
7671 | Some txt -> pr "%s\n\n" txt
7672 ) all_functions_sorted
7674 (* Generate a C function prototype. *)
7675 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7676 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7678 ?handle name style =
7679 if extern then pr "extern ";
7680 if static then pr "static ";
7681 (match fst style with
7683 | RInt _ -> pr "int "
7684 | RInt64 _ -> pr "int64_t "
7685 | RBool _ -> pr "int "
7686 | RConstString _ | RConstOptString _ -> pr "const char *"
7687 | RString _ | RBufferOut _ -> pr "char *"
7688 | RStringList _ | RHashtable _ -> pr "char **"
7689 | RStruct (_, typ) ->
7690 if not in_daemon then pr "struct guestfs_%s *" typ
7691 else pr "guestfs_int_%s *" typ
7692 | RStructList (_, typ) ->
7693 if not in_daemon then pr "struct guestfs_%s_list *" typ
7694 else pr "guestfs_int_%s_list *" typ
7696 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7697 pr "%s%s (" prefix name;
7698 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7701 let comma = ref false in
7704 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7708 if single_line then pr ", " else pr ",\n\t\t"
7715 | Device n | Dev_or_Path n
7719 pr "const char *%s" n
7720 | StringList n | DeviceList n ->
7722 pr "char *const *%s" n
7723 | Bool n -> next (); pr "int %s" n
7724 | Int n -> next (); pr "int %s" n
7725 | Int64 n -> next (); pr "int64_t %s" n
7728 if not in_daemon then (next (); pr "const char *%s" n)
7730 if is_RBufferOut then (next (); pr "size_t *size_r");
7733 if semicolon then pr ";";
7734 if newline then pr "\n"
7736 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7737 and generate_c_call_args ?handle ?(decl = false) style =
7739 let comma = ref false in
7741 if !comma then pr ", ";
7746 | Some handle -> pr "%s" handle; comma := true
7751 pr "%s" (name_of_argt arg)
7753 (* For RBufferOut calls, add implicit &size parameter. *)
7755 match fst style with
7763 (* Generate the OCaml bindings interface. *)
7764 and generate_ocaml_mli () =
7765 generate_header OCamlStyle LGPLv2plus;
7768 (** For API documentation you should refer to the C API
7769 in the guestfs(3) manual page. The OCaml API uses almost
7770 exactly the same calls. *)
7773 (** A [guestfs_h] handle. *)
7775 exception Error of string
7776 (** This exception is raised when there is an error. *)
7778 exception Handle_closed of string
7779 (** This exception is raised if you use a {!Guestfs.t} handle
7780 after calling {!close} on it. The string is the name of
7783 val create : unit -> t
7784 (** Create a {!Guestfs.t} handle. *)
7786 val close : t -> unit
7787 (** Close the {!Guestfs.t} handle and free up all resources used
7790 Handles are closed by the garbage collector when they become
7791 unreferenced, but callers can call this in order to provide
7792 predictable cleanup. *)
7795 generate_ocaml_structure_decls ();
7799 fun (name, style, _, _, _, shortdesc, _) ->
7800 generate_ocaml_prototype name style;
7801 pr "(** %s *)\n" shortdesc;
7803 ) all_functions_sorted
7805 (* Generate the OCaml bindings implementation. *)
7806 and generate_ocaml_ml () =
7807 generate_header OCamlStyle LGPLv2plus;
7812 exception Error of string
7813 exception Handle_closed of string
7815 external create : unit -> t = \"ocaml_guestfs_create\"
7816 external close : t -> unit = \"ocaml_guestfs_close\"
7818 (* Give the exceptions names, so they can be raised from the C code. *)
7820 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7821 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7825 generate_ocaml_structure_decls ();
7829 fun (name, style, _, _, _, shortdesc, _) ->
7830 generate_ocaml_prototype ~is_external:true name style;
7831 ) all_functions_sorted
7833 (* Generate the OCaml bindings C implementation. *)
7834 and generate_ocaml_c () =
7835 generate_header CStyle LGPLv2plus;
7842 #include <caml/config.h>
7843 #include <caml/alloc.h>
7844 #include <caml/callback.h>
7845 #include <caml/fail.h>
7846 #include <caml/memory.h>
7847 #include <caml/mlvalues.h>
7848 #include <caml/signals.h>
7850 #include <guestfs.h>
7852 #include \"guestfs_c.h\"
7854 /* Copy a hashtable of string pairs into an assoc-list. We return
7855 * the list in reverse order, but hashtables aren't supposed to be
7858 static CAMLprim value
7859 copy_table (char * const * argv)
7862 CAMLlocal5 (rv, pairv, kv, vv, cons);
7866 for (i = 0; argv[i] != NULL; i += 2) {
7867 kv = caml_copy_string (argv[i]);
7868 vv = caml_copy_string (argv[i+1]);
7869 pairv = caml_alloc (2, 0);
7870 Store_field (pairv, 0, kv);
7871 Store_field (pairv, 1, vv);
7872 cons = caml_alloc (2, 0);
7873 Store_field (cons, 1, rv);
7875 Store_field (cons, 0, pairv);
7883 (* Struct copy functions. *)
7885 let emit_ocaml_copy_list_function typ =
7886 pr "static CAMLprim value\n";
7887 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7889 pr " CAMLparam0 ();\n";
7890 pr " CAMLlocal2 (rv, v);\n";
7891 pr " unsigned int i;\n";
7893 pr " if (%ss->len == 0)\n" typ;
7894 pr " CAMLreturn (Atom (0));\n";
7896 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7897 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7898 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7899 pr " caml_modify (&Field (rv, i), v);\n";
7901 pr " CAMLreturn (rv);\n";
7909 let has_optpercent_col =
7910 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7912 pr "static CAMLprim value\n";
7913 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7915 pr " CAMLparam0 ();\n";
7916 if has_optpercent_col then
7917 pr " CAMLlocal3 (rv, v, v2);\n"
7919 pr " CAMLlocal2 (rv, v);\n";
7921 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7926 pr " v = caml_copy_string (%s->%s);\n" typ name
7928 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7929 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7932 pr " v = caml_alloc_string (32);\n";
7933 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7934 | name, (FBytes|FInt64|FUInt64) ->
7935 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7936 | name, (FInt32|FUInt32) ->
7937 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7938 | name, FOptPercent ->
7939 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7940 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7941 pr " v = caml_alloc (1, 0);\n";
7942 pr " Store_field (v, 0, v2);\n";
7943 pr " } else /* None */\n";
7944 pr " v = Val_int (0);\n";
7946 pr " v = Val_int (%s->%s);\n" typ name
7948 pr " Store_field (rv, %d, v);\n" i
7950 pr " CAMLreturn (rv);\n";
7955 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7958 | typ, (RStructListOnly | RStructAndList) ->
7959 (* generate the function for typ *)
7960 emit_ocaml_copy_list_function typ
7961 | typ, _ -> () (* empty *)
7962 ) (rstructs_used_by all_functions);
7966 fun (name, style, _, _, _, _, _) ->
7967 pr "/* Automatically generated wrapper for function\n";
7969 generate_ocaml_prototype name style;
7974 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7976 let needs_extra_vs =
7977 match fst style with RConstOptString _ -> true | _ -> false in
7979 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7980 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7981 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7984 pr "CAMLprim value\n";
7985 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7986 List.iter (pr ", value %s") (List.tl params);
7991 | [p1; p2; p3; p4; p5] ->
7992 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7993 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7994 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7995 pr " CAMLxparam%d (%s);\n"
7996 (List.length rest) (String.concat ", " rest)
7998 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8000 if not needs_extra_vs then
8001 pr " CAMLlocal1 (rv);\n"
8003 pr " CAMLlocal3 (rv, v, v2);\n";
8006 pr " guestfs_h *g = Guestfs_val (gv);\n";
8007 pr " if (g == NULL)\n";
8008 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8014 | Device n | Dev_or_Path n
8018 pr " const char *%s = String_val (%sv);\n" n n
8020 pr " const char *%s =\n" n;
8021 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8023 | StringList n | DeviceList n ->
8024 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8026 pr " int %s = Bool_val (%sv);\n" n n
8028 pr " int %s = Int_val (%sv);\n" n n
8030 pr " int64_t %s = Int64_val (%sv);\n" n n
8033 match fst style with
8034 | RErr -> pr " int r;\n"; "-1"
8035 | RInt _ -> pr " int r;\n"; "-1"
8036 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8037 | RBool _ -> pr " int r;\n"; "-1"
8038 | RConstString _ | RConstOptString _ ->
8039 pr " const char *r;\n"; "NULL"
8040 | RString _ -> pr " char *r;\n"; "NULL"
8045 | RStruct (_, typ) ->
8046 pr " struct guestfs_%s *r;\n" typ; "NULL"
8047 | RStructList (_, typ) ->
8048 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8055 pr " size_t size;\n";
8059 pr " caml_enter_blocking_section ();\n";
8060 pr " r = guestfs_%s " name;
8061 generate_c_call_args ~handle:"g" style;
8063 pr " caml_leave_blocking_section ();\n";
8067 | StringList n | DeviceList n ->
8068 pr " ocaml_guestfs_free_strings (%s);\n" n;
8069 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8070 | Bool _ | Int _ | Int64 _
8071 | FileIn _ | FileOut _ -> ()
8074 pr " if (r == %s)\n" error_code;
8075 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8078 (match fst style with
8079 | RErr -> pr " rv = Val_unit;\n"
8080 | RInt _ -> pr " rv = Val_int (r);\n"
8082 pr " rv = caml_copy_int64 (r);\n"
8083 | RBool _ -> pr " rv = Val_bool (r);\n"
8085 pr " rv = caml_copy_string (r);\n"
8086 | RConstOptString _ ->
8087 pr " if (r) { /* Some string */\n";
8088 pr " v = caml_alloc (1, 0);\n";
8089 pr " v2 = caml_copy_string (r);\n";
8090 pr " Store_field (v, 0, v2);\n";
8091 pr " } else /* None */\n";
8092 pr " v = Val_int (0);\n";
8094 pr " rv = caml_copy_string (r);\n";
8097 pr " rv = caml_copy_string_array ((const char **) r);\n";
8098 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8100 | RStruct (_, typ) ->
8101 pr " rv = copy_%s (r);\n" typ;
8102 pr " guestfs_free_%s (r);\n" typ;
8103 | RStructList (_, typ) ->
8104 pr " rv = copy_%s_list (r);\n" typ;
8105 pr " guestfs_free_%s_list (r);\n" typ;
8107 pr " rv = copy_table (r);\n";
8108 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8111 pr " rv = caml_alloc_string (size);\n";
8112 pr " memcpy (String_val (rv), r, size);\n";
8115 pr " CAMLreturn (rv);\n";
8119 if List.length params > 5 then (
8120 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8121 pr "CAMLprim value ";
8122 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8123 pr "CAMLprim value\n";
8124 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8126 pr " return ocaml_guestfs_%s (argv[0]" name;
8127 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8132 ) all_functions_sorted
8134 and generate_ocaml_structure_decls () =
8137 pr "type %s = {\n" typ;
8140 | name, FString -> pr " %s : string;\n" name
8141 | name, FBuffer -> pr " %s : string;\n" name
8142 | name, FUUID -> pr " %s : string;\n" name
8143 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8144 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8145 | name, FChar -> pr " %s : char;\n" name
8146 | name, FOptPercent -> pr " %s : float option;\n" name
8152 and generate_ocaml_prototype ?(is_external = false) name style =
8153 if is_external then pr "external " else pr "val ";
8154 pr "%s : t -> " name;
8157 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8158 | OptString _ -> pr "string option -> "
8159 | StringList _ | DeviceList _ -> pr "string array -> "
8160 | Bool _ -> pr "bool -> "
8161 | Int _ -> pr "int -> "
8162 | Int64 _ -> pr "int64 -> "
8164 (match fst style with
8165 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8166 | RInt _ -> pr "int"
8167 | RInt64 _ -> pr "int64"
8168 | RBool _ -> pr "bool"
8169 | RConstString _ -> pr "string"
8170 | RConstOptString _ -> pr "string option"
8171 | RString _ | RBufferOut _ -> pr "string"
8172 | RStringList _ -> pr "string array"
8173 | RStruct (_, typ) -> pr "%s" typ
8174 | RStructList (_, typ) -> pr "%s array" typ
8175 | RHashtable _ -> pr "(string * string) list"
8177 if is_external then (
8179 if List.length (snd style) + 1 > 5 then
8180 pr "\"ocaml_guestfs_%s_byte\" " name;
8181 pr "\"ocaml_guestfs_%s\"" name
8185 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8186 and generate_perl_xs () =
8187 generate_header CStyle LGPLv2plus;
8190 #include \"EXTERN.h\"
8194 #include <guestfs.h>
8197 #define PRId64 \"lld\"
8201 my_newSVll(long long val) {
8202 #ifdef USE_64_BIT_ALL
8203 return newSViv(val);
8207 len = snprintf(buf, 100, \"%%\" PRId64, val);
8208 return newSVpv(buf, len);
8213 #define PRIu64 \"llu\"
8217 my_newSVull(unsigned long long val) {
8218 #ifdef USE_64_BIT_ALL
8219 return newSVuv(val);
8223 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8224 return newSVpv(buf, len);
8228 /* http://www.perlmonks.org/?node_id=680842 */
8230 XS_unpack_charPtrPtr (SV *arg) {
8235 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8236 croak (\"array reference expected\");
8238 av = (AV *)SvRV (arg);
8239 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8241 croak (\"malloc failed\");
8243 for (i = 0; i <= av_len (av); i++) {
8244 SV **elem = av_fetch (av, i, 0);
8246 if (!elem || !*elem)
8247 croak (\"missing element in list\");
8249 ret[i] = SvPV_nolen (*elem);
8257 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8264 RETVAL = guestfs_create ();
8266 croak (\"could not create guestfs handle\");
8267 guestfs_set_error_handler (RETVAL, NULL, NULL);
8280 fun (name, style, _, _, _, _, _) ->
8281 (match fst style with
8282 | RErr -> pr "void\n"
8283 | RInt _ -> pr "SV *\n"
8284 | RInt64 _ -> pr "SV *\n"
8285 | RBool _ -> pr "SV *\n"
8286 | RConstString _ -> pr "SV *\n"
8287 | RConstOptString _ -> pr "SV *\n"
8288 | RString _ -> pr "SV *\n"
8289 | RBufferOut _ -> pr "SV *\n"
8291 | RStruct _ | RStructList _
8293 pr "void\n" (* all lists returned implictly on the stack *)
8295 (* Call and arguments. *)
8297 generate_c_call_args ~handle:"g" ~decl:true style;
8299 pr " guestfs_h *g;\n";
8303 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8306 (* http://www.perlmonks.org/?node_id=554277
8307 * Note that the implicit handle argument means we have
8308 * to add 1 to the ST(x) operator.
8310 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8311 | StringList n | DeviceList n -> pr " char **%s;\n" n
8312 | Bool n -> pr " int %s;\n" n
8313 | Int n -> pr " int %s;\n" n
8314 | Int64 n -> pr " int64_t %s;\n" n
8317 let do_cleanups () =
8320 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8321 | Bool _ | Int _ | Int64 _
8322 | FileIn _ | FileOut _ -> ()
8323 | StringList n | DeviceList n -> pr " free (%s);\n" n
8328 (match fst style with
8333 pr " r = guestfs_%s " name;
8334 generate_c_call_args ~handle:"g" style;
8337 pr " if (r == -1)\n";
8338 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8344 pr " %s = guestfs_%s " n name;
8345 generate_c_call_args ~handle:"g" style;
8348 pr " if (%s == -1)\n" n;
8349 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8350 pr " RETVAL = newSViv (%s);\n" n;
8355 pr " int64_t %s;\n" n;
8357 pr " %s = guestfs_%s " n name;
8358 generate_c_call_args ~handle:"g" style;
8361 pr " if (%s == -1)\n" n;
8362 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8363 pr " RETVAL = my_newSVll (%s);\n" n;
8368 pr " const char *%s;\n" n;
8370 pr " %s = guestfs_%s " n name;
8371 generate_c_call_args ~handle:"g" style;
8374 pr " if (%s == NULL)\n" n;
8375 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8376 pr " RETVAL = newSVpv (%s, 0);\n" n;
8379 | RConstOptString n ->
8381 pr " const char *%s;\n" n;
8383 pr " %s = guestfs_%s " n name;
8384 generate_c_call_args ~handle:"g" style;
8387 pr " if (%s == NULL)\n" n;
8388 pr " RETVAL = &PL_sv_undef;\n";
8390 pr " RETVAL = newSVpv (%s, 0);\n" n;
8395 pr " char *%s;\n" n;
8397 pr " %s = guestfs_%s " n name;
8398 generate_c_call_args ~handle:"g" style;
8401 pr " if (%s == NULL)\n" n;
8402 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8403 pr " RETVAL = newSVpv (%s, 0);\n" n;
8404 pr " free (%s);\n" n;
8407 | RStringList n | RHashtable n ->
8409 pr " char **%s;\n" n;
8412 pr " %s = guestfs_%s " n name;
8413 generate_c_call_args ~handle:"g" style;
8416 pr " if (%s == NULL)\n" n;
8417 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8418 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8419 pr " EXTEND (SP, n);\n";
8420 pr " for (i = 0; i < n; ++i) {\n";
8421 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8422 pr " free (%s[i]);\n" n;
8424 pr " free (%s);\n" n;
8425 | RStruct (n, typ) ->
8426 let cols = cols_of_struct typ in
8427 generate_perl_struct_code typ cols name style n do_cleanups
8428 | RStructList (n, typ) ->
8429 let cols = cols_of_struct typ in
8430 generate_perl_struct_list_code typ cols name style n do_cleanups
8433 pr " char *%s;\n" n;
8434 pr " size_t size;\n";
8436 pr " %s = guestfs_%s " n name;
8437 generate_c_call_args ~handle:"g" style;
8440 pr " if (%s == NULL)\n" n;
8441 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8442 pr " RETVAL = newSVpvn (%s, size);\n" n;
8443 pr " free (%s);\n" n;
8451 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8453 pr " struct guestfs_%s_list *%s;\n" typ n;
8457 pr " %s = guestfs_%s " n name;
8458 generate_c_call_args ~handle:"g" style;
8461 pr " if (%s == NULL)\n" n;
8462 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8463 pr " EXTEND (SP, %s->len);\n" n;
8464 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8465 pr " hv = newHV ();\n";
8469 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8470 name (String.length name) n name
8472 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8473 name (String.length name) n name
8475 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8476 name (String.length name) n name n name
8477 | name, (FBytes|FUInt64) ->
8478 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8479 name (String.length name) n name
8481 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8482 name (String.length name) n name
8483 | name, (FInt32|FUInt32) ->
8484 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8485 name (String.length name) n name
8487 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8488 name (String.length name) n name
8489 | name, FOptPercent ->
8490 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8491 name (String.length name) n name
8493 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8495 pr " guestfs_free_%s_list (%s);\n" typ n
8497 and generate_perl_struct_code typ cols name style n do_cleanups =
8499 pr " struct guestfs_%s *%s;\n" typ n;
8501 pr " %s = guestfs_%s " n name;
8502 generate_c_call_args ~handle:"g" style;
8505 pr " if (%s == NULL)\n" n;
8506 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8507 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8509 fun ((name, _) as col) ->
8510 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8514 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8517 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8520 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8522 | name, (FBytes|FUInt64) ->
8523 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8526 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8528 | name, (FInt32|FUInt32) ->
8529 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8532 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8534 | name, FOptPercent ->
8535 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8538 pr " free (%s);\n" n
8540 (* Generate Sys/Guestfs.pm. *)
8541 and generate_perl_pm () =
8542 generate_header HashStyle LGPLv2plus;
8549 Sys::Guestfs - Perl bindings for libguestfs
8555 my $h = Sys::Guestfs->new ();
8556 $h->add_drive ('guest.img');
8558 $h->mount ('/dev/sda1', '/');
8559 $h->touch ('/hello');
8564 The C<Sys::Guestfs> module provides a Perl XS binding to the
8565 libguestfs API for examining and modifying virtual machine
8568 Amongst the things this is good for: making batch configuration
8569 changes to guests, getting disk used/free statistics (see also:
8570 virt-df), migrating between virtualization systems (see also:
8571 virt-p2v), performing partial backups, performing partial guest
8572 clones, cloning guests and changing registry/UUID/hostname info, and
8575 Libguestfs uses Linux kernel and qemu code, and can access any type of
8576 guest filesystem that Linux and qemu can, including but not limited
8577 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8578 schemes, qcow, qcow2, vmdk.
8580 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8581 LVs, what filesystem is in each LV, etc.). It can also run commands
8582 in the context of the guest. Also you can access filesystems over
8585 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8586 functions for using libguestfs from Perl, including integration
8591 All errors turn into calls to C<croak> (see L<Carp(3)>).
8599 package Sys::Guestfs;
8605 XSLoader::load ('Sys::Guestfs');
8607 =item $h = Sys::Guestfs->new ();
8609 Create a new guestfs handle.
8615 my $class = ref ($proto) || $proto;
8617 my $self = Sys::Guestfs::_create ();
8618 bless $self, $class;
8624 (* Actions. We only need to print documentation for these as
8625 * they are pulled in from the XS code automatically.
8628 fun (name, style, _, flags, _, _, longdesc) ->
8629 if not (List.mem NotInDocs flags) then (
8630 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8632 generate_perl_prototype name style;
8634 pr "%s\n\n" longdesc;
8635 if List.mem ProtocolLimitWarning flags then
8636 pr "%s\n\n" protocol_limit_warning;
8637 if List.mem DangerWillRobinson flags then
8638 pr "%s\n\n" danger_will_robinson;
8639 match deprecation_notice flags with
8641 | Some txt -> pr "%s\n\n" txt
8643 ) all_functions_sorted;
8655 Copyright (C) %s Red Hat Inc.
8659 Please see the file COPYING.LIB for the full license.
8665 L<http://libguestfs.org>,
8666 L<Sys::Guestfs::Lib(3)>.
8671 and generate_perl_prototype name style =
8672 (match fst style with
8680 | RBufferOut n -> pr "$%s = " n
8682 | RHashtable n -> pr "%%%s = " n
8684 | RStructList (n,_) -> pr "@%s = " n
8687 let comma = ref false in
8690 if !comma then pr ", ";
8693 | Pathname n | Device n | Dev_or_Path n | String n
8694 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8696 | StringList n | DeviceList n ->
8701 (* Generate Python C module. *)
8702 and generate_python_c () =
8703 generate_header CStyle LGPLv2plus;
8712 #include \"guestfs.h\"
8720 get_handle (PyObject *obj)
8723 assert (obj != Py_None);
8724 return ((Pyguestfs_Object *) obj)->g;
8728 put_handle (guestfs_h *g)
8732 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8735 /* This list should be freed (but not the strings) after use. */
8737 get_string_list (PyObject *obj)
8744 if (!PyList_Check (obj)) {
8745 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8749 len = PyList_Size (obj);
8750 r = malloc (sizeof (char *) * (len+1));
8752 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8756 for (i = 0; i < len; ++i)
8757 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8764 put_string_list (char * const * const argv)
8769 for (argc = 0; argv[argc] != NULL; ++argc)
8772 list = PyList_New (argc);
8773 for (i = 0; i < argc; ++i)
8774 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8780 put_table (char * const * const argv)
8782 PyObject *list, *item;
8785 for (argc = 0; argv[argc] != NULL; ++argc)
8788 list = PyList_New (argc >> 1);
8789 for (i = 0; i < argc; i += 2) {
8790 item = PyTuple_New (2);
8791 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8792 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8793 PyList_SetItem (list, i >> 1, item);
8800 free_strings (char **argv)
8804 for (argc = 0; argv[argc] != NULL; ++argc)
8810 py_guestfs_create (PyObject *self, PyObject *args)
8814 g = guestfs_create ();
8816 PyErr_SetString (PyExc_RuntimeError,
8817 \"guestfs.create: failed to allocate handle\");
8820 guestfs_set_error_handler (g, NULL, NULL);
8821 return put_handle (g);
8825 py_guestfs_close (PyObject *self, PyObject *args)
8830 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8832 g = get_handle (py_g);
8836 Py_INCREF (Py_None);
8842 let emit_put_list_function typ =
8843 pr "static PyObject *\n";
8844 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8846 pr " PyObject *list;\n";
8849 pr " list = PyList_New (%ss->len);\n" typ;
8850 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8851 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8852 pr " return list;\n";
8857 (* Structures, turned into Python dictionaries. *)
8860 pr "static PyObject *\n";
8861 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8863 pr " PyObject *dict;\n";
8865 pr " dict = PyDict_New ();\n";
8869 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8870 pr " PyString_FromString (%s->%s));\n"
8873 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8874 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8877 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8878 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8880 | name, (FBytes|FUInt64) ->
8881 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8882 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8885 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8886 pr " PyLong_FromLongLong (%s->%s));\n"
8889 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8890 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8893 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8894 pr " PyLong_FromLong (%s->%s));\n"
8896 | name, FOptPercent ->
8897 pr " if (%s->%s >= 0)\n" typ name;
8898 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8899 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8902 pr " Py_INCREF (Py_None);\n";
8903 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8906 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8907 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8909 pr " return dict;\n";
8915 (* Emit a put_TYPE_list function definition only if that function is used. *)
8918 | typ, (RStructListOnly | RStructAndList) ->
8919 (* generate the function for typ *)
8920 emit_put_list_function typ
8921 | typ, _ -> () (* empty *)
8922 ) (rstructs_used_by all_functions);
8924 (* Python wrapper functions. *)
8926 fun (name, style, _, _, _, _, _) ->
8927 pr "static PyObject *\n";
8928 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8931 pr " PyObject *py_g;\n";
8932 pr " guestfs_h *g;\n";
8933 pr " PyObject *py_r;\n";
8936 match fst style with
8937 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8938 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8939 | RConstString _ | RConstOptString _ ->
8940 pr " const char *r;\n"; "NULL"
8941 | RString _ -> pr " char *r;\n"; "NULL"
8942 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8943 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8944 | RStructList (_, typ) ->
8945 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8948 pr " size_t size;\n";
8953 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8954 pr " const char *%s;\n" n
8955 | OptString n -> pr " const char *%s;\n" n
8956 | StringList n | DeviceList n ->
8957 pr " PyObject *py_%s;\n" n;
8958 pr " char **%s;\n" n
8959 | Bool n -> pr " int %s;\n" n
8960 | Int n -> pr " int %s;\n" n
8961 | Int64 n -> pr " long long %s;\n" n
8966 (* Convert the parameters. *)
8967 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8970 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8971 | OptString _ -> pr "z"
8972 | StringList _ | DeviceList _ -> pr "O"
8973 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8975 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8976 * emulate C's int/long/long long in Python?
8979 pr ":guestfs_%s\",\n" name;
8983 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8984 | OptString n -> pr ", &%s" n
8985 | StringList n | DeviceList n -> pr ", &py_%s" n
8986 | Bool n -> pr ", &%s" n
8987 | Int n -> pr ", &%s" n
8988 | Int64 n -> pr ", &%s" n
8992 pr " return NULL;\n";
8994 pr " g = get_handle (py_g);\n";
8997 | Pathname _ | Device _ | Dev_or_Path _ | String _
8998 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8999 | StringList n | DeviceList n ->
9000 pr " %s = get_string_list (py_%s);\n" n n;
9001 pr " if (!%s) return NULL;\n" n
9006 pr " r = guestfs_%s " name;
9007 generate_c_call_args ~handle:"g" style;
9012 | Pathname _ | Device _ | Dev_or_Path _ | String _
9013 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9014 | StringList n | DeviceList n ->
9015 pr " free (%s);\n" n
9018 pr " if (r == %s) {\n" error_code;
9019 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9020 pr " return NULL;\n";
9024 (match fst style with
9026 pr " Py_INCREF (Py_None);\n";
9027 pr " py_r = Py_None;\n"
9029 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9030 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9031 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9032 | RConstOptString _ ->
9034 pr " py_r = PyString_FromString (r);\n";
9036 pr " Py_INCREF (Py_None);\n";
9037 pr " py_r = Py_None;\n";
9040 pr " py_r = PyString_FromString (r);\n";
9043 pr " py_r = put_string_list (r);\n";
9044 pr " free_strings (r);\n"
9045 | RStruct (_, typ) ->
9046 pr " py_r = put_%s (r);\n" typ;
9047 pr " guestfs_free_%s (r);\n" typ
9048 | RStructList (_, typ) ->
9049 pr " py_r = put_%s_list (r);\n" typ;
9050 pr " guestfs_free_%s_list (r);\n" typ
9052 pr " py_r = put_table (r);\n";
9053 pr " free_strings (r);\n"
9055 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9059 pr " return py_r;\n";
9064 (* Table of functions. *)
9065 pr "static PyMethodDef methods[] = {\n";
9066 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9067 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9069 fun (name, _, _, _, _, _, _) ->
9070 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9073 pr " { NULL, NULL, 0, NULL }\n";
9077 (* Init function. *)
9080 initlibguestfsmod (void)
9082 static int initialized = 0;
9084 if (initialized) return;
9085 Py_InitModule ((char *) \"libguestfsmod\", methods);
9090 (* Generate Python module. *)
9091 and generate_python_py () =
9092 generate_header HashStyle LGPLv2plus;
9095 u\"\"\"Python bindings for libguestfs
9098 g = guestfs.GuestFS ()
9099 g.add_drive (\"guest.img\")
9101 parts = g.list_partitions ()
9103 The guestfs module provides a Python binding to the libguestfs API
9104 for examining and modifying virtual machine disk images.
9106 Amongst the things this is good for: making batch configuration
9107 changes to guests, getting disk used/free statistics (see also:
9108 virt-df), migrating between virtualization systems (see also:
9109 virt-p2v), performing partial backups, performing partial guest
9110 clones, cloning guests and changing registry/UUID/hostname info, and
9113 Libguestfs uses Linux kernel and qemu code, and can access any type of
9114 guest filesystem that Linux and qemu can, including but not limited
9115 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9116 schemes, qcow, qcow2, vmdk.
9118 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9119 LVs, what filesystem is in each LV, etc.). It can also run commands
9120 in the context of the guest. Also you can access filesystems over
9123 Errors which happen while using the API are turned into Python
9124 RuntimeError exceptions.
9126 To create a guestfs handle you usually have to perform the following
9129 # Create the handle, call add_drive at least once, and possibly
9130 # several times if the guest has multiple block devices:
9131 g = guestfs.GuestFS ()
9132 g.add_drive (\"guest.img\")
9134 # Launch the qemu subprocess and wait for it to become ready:
9137 # Now you can issue commands, for example:
9142 import libguestfsmod
9145 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9147 def __init__ (self):
9148 \"\"\"Create a new libguestfs handle.\"\"\"
9149 self._o = libguestfsmod.create ()
9152 libguestfsmod.close (self._o)
9157 fun (name, style, _, flags, _, _, longdesc) ->
9159 generate_py_call_args ~handle:"self" (snd style);
9162 if not (List.mem NotInDocs flags) then (
9163 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9165 match fst style with
9166 | RErr | RInt _ | RInt64 _ | RBool _
9167 | RConstOptString _ | RConstString _
9168 | RString _ | RBufferOut _ -> doc
9170 doc ^ "\n\nThis function returns a list of strings."
9171 | RStruct (_, typ) ->
9172 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9173 | RStructList (_, typ) ->
9174 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9176 doc ^ "\n\nThis function returns a dictionary." in
9178 if List.mem ProtocolLimitWarning flags then
9179 doc ^ "\n\n" ^ protocol_limit_warning
9182 if List.mem DangerWillRobinson flags then
9183 doc ^ "\n\n" ^ danger_will_robinson
9186 match deprecation_notice flags with
9188 | Some txt -> doc ^ "\n\n" ^ txt in
9189 let doc = pod2text ~width:60 name doc in
9190 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9191 let doc = String.concat "\n " doc in
9192 pr " u\"\"\"%s\"\"\"\n" doc;
9194 pr " return libguestfsmod.%s " name;
9195 generate_py_call_args ~handle:"self._o" (snd style);
9200 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9201 and generate_py_call_args ~handle args =
9203 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9206 (* Useful if you need the longdesc POD text as plain text. Returns a
9209 * Because this is very slow (the slowest part of autogeneration),
9210 * we memoize the results.
9212 and pod2text ~width name longdesc =
9213 let key = width, name, longdesc in
9214 try Hashtbl.find pod2text_memo key
9216 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9217 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9219 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9220 let chan = open_process_in cmd in
9221 let lines = ref [] in
9223 let line = input_line chan in
9224 if i = 1 then (* discard the first line of output *)
9227 let line = triml line in
9228 lines := line :: !lines;
9231 let lines = try loop 1 with End_of_file -> List.rev !lines in
9233 (match close_process_in chan with
9236 failwithf "pod2text: process exited with non-zero status (%d)" i
9237 | WSIGNALED i | WSTOPPED i ->
9238 failwithf "pod2text: process signalled or stopped by signal %d" i
9240 Hashtbl.add pod2text_memo key lines;
9241 pod2text_memo_updated ();
9244 (* Generate ruby bindings. *)
9245 and generate_ruby_c () =
9246 generate_header CStyle LGPLv2plus;
9254 #include \"guestfs.h\"
9256 #include \"extconf.h\"
9258 /* For Ruby < 1.9 */
9260 #define RARRAY_LEN(r) (RARRAY((r))->len)
9263 static VALUE m_guestfs; /* guestfs module */
9264 static VALUE c_guestfs; /* guestfs_h handle */
9265 static VALUE e_Error; /* used for all errors */
9267 static void ruby_guestfs_free (void *p)
9270 guestfs_close ((guestfs_h *) p);
9273 static VALUE ruby_guestfs_create (VALUE m)
9277 g = guestfs_create ();
9279 rb_raise (e_Error, \"failed to create guestfs handle\");
9281 /* Don't print error messages to stderr by default. */
9282 guestfs_set_error_handler (g, NULL, NULL);
9284 /* Wrap it, and make sure the close function is called when the
9287 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9290 static VALUE ruby_guestfs_close (VALUE gv)
9293 Data_Get_Struct (gv, guestfs_h, g);
9295 ruby_guestfs_free (g);
9296 DATA_PTR (gv) = NULL;
9304 fun (name, style, _, _, _, _, _) ->
9305 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9306 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9309 pr " guestfs_h *g;\n";
9310 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9312 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9318 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9319 pr " Check_Type (%sv, T_STRING);\n" n;
9320 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9322 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9323 pr " \"%s\", \"%s\");\n" n name
9325 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9326 | StringList n | DeviceList n ->
9327 pr " char **%s;\n" n;
9328 pr " Check_Type (%sv, T_ARRAY);\n" n;
9330 pr " int i, len;\n";
9331 pr " len = RARRAY_LEN (%sv);\n" n;
9332 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9334 pr " for (i = 0; i < len; ++i) {\n";
9335 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9336 pr " %s[i] = StringValueCStr (v);\n" n;
9338 pr " %s[len] = NULL;\n" n;
9341 pr " int %s = RTEST (%sv);\n" n n
9343 pr " int %s = NUM2INT (%sv);\n" n n
9345 pr " long long %s = NUM2LL (%sv);\n" n n
9350 match fst style with
9351 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9352 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9353 | RConstString _ | RConstOptString _ ->
9354 pr " const char *r;\n"; "NULL"
9355 | RString _ -> pr " char *r;\n"; "NULL"
9356 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9357 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9358 | RStructList (_, typ) ->
9359 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9362 pr " size_t size;\n";
9366 pr " r = guestfs_%s " name;
9367 generate_c_call_args ~handle:"g" style;
9372 | Pathname _ | Device _ | Dev_or_Path _ | String _
9373 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9374 | StringList n | DeviceList n ->
9375 pr " free (%s);\n" n
9378 pr " if (r == %s)\n" error_code;
9379 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9382 (match fst style with
9384 pr " return Qnil;\n"
9385 | RInt _ | RBool _ ->
9386 pr " return INT2NUM (r);\n"
9388 pr " return ULL2NUM (r);\n"
9390 pr " return rb_str_new2 (r);\n";
9391 | RConstOptString _ ->
9393 pr " return rb_str_new2 (r);\n";
9395 pr " return Qnil;\n";
9397 pr " VALUE rv = rb_str_new2 (r);\n";
9401 pr " int i, len = 0;\n";
9402 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9403 pr " VALUE rv = rb_ary_new2 (len);\n";
9404 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9405 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9406 pr " free (r[i]);\n";
9410 | RStruct (_, typ) ->
9411 let cols = cols_of_struct typ in
9412 generate_ruby_struct_code typ cols
9413 | RStructList (_, typ) ->
9414 let cols = cols_of_struct typ in
9415 generate_ruby_struct_list_code typ cols
9417 pr " VALUE rv = rb_hash_new ();\n";
9419 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9420 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9421 pr " free (r[i]);\n";
9422 pr " free (r[i+1]);\n";
9427 pr " VALUE rv = rb_str_new (r, size);\n";
9437 /* Initialize the module. */
9438 void Init__guestfs ()
9440 m_guestfs = rb_define_module (\"Guestfs\");
9441 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9442 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9444 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9445 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9448 (* Define the rest of the methods. *)
9450 fun (name, style, _, _, _, _, _) ->
9451 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9452 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9457 (* Ruby code to return a struct. *)
9458 and generate_ruby_struct_code typ cols =
9459 pr " VALUE rv = rb_hash_new ();\n";
9463 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9465 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9467 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9468 | name, (FBytes|FUInt64) ->
9469 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9471 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9473 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9475 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9476 | name, FOptPercent ->
9477 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9478 | name, FChar -> (* XXX wrong? *)
9479 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9481 pr " guestfs_free_%s (r);\n" typ;
9484 (* Ruby code to return a struct list. *)
9485 and generate_ruby_struct_list_code typ cols =
9486 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9488 pr " for (i = 0; i < r->len; ++i) {\n";
9489 pr " VALUE hv = rb_hash_new ();\n";
9493 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9495 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
9497 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9498 | name, (FBytes|FUInt64) ->
9499 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9501 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9503 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9505 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9506 | name, FOptPercent ->
9507 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9508 | name, FChar -> (* XXX wrong? *)
9509 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9511 pr " rb_ary_push (rv, hv);\n";
9513 pr " guestfs_free_%s_list (r);\n" typ;
9516 (* Generate Java bindings GuestFS.java file. *)
9517 and generate_java_java () =
9518 generate_header CStyle LGPLv2plus;
9521 package com.redhat.et.libguestfs;
9523 import java.util.HashMap;
9524 import com.redhat.et.libguestfs.LibGuestFSException;
9525 import com.redhat.et.libguestfs.PV;
9526 import com.redhat.et.libguestfs.VG;
9527 import com.redhat.et.libguestfs.LV;
9528 import com.redhat.et.libguestfs.Stat;
9529 import com.redhat.et.libguestfs.StatVFS;
9530 import com.redhat.et.libguestfs.IntBool;
9531 import com.redhat.et.libguestfs.Dirent;
9534 * The GuestFS object is a libguestfs handle.
9538 public class GuestFS {
9539 // Load the native code.
9541 System.loadLibrary (\"guestfs_jni\");
9545 * The native guestfs_h pointer.
9550 * Create a libguestfs handle.
9552 * @throws LibGuestFSException
9554 public GuestFS () throws LibGuestFSException
9558 private native long _create () throws LibGuestFSException;
9561 * Close a libguestfs handle.
9563 * You can also leave handles to be collected by the garbage
9564 * collector, but this method ensures that the resources used
9565 * by the handle are freed up immediately. If you call any
9566 * other methods after closing the handle, you will get an
9569 * @throws LibGuestFSException
9571 public void close () throws LibGuestFSException
9577 private native void _close (long g) throws LibGuestFSException;
9579 public void finalize () throws LibGuestFSException
9587 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9588 if not (List.mem NotInDocs flags); then (
9589 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9591 if List.mem ProtocolLimitWarning flags then
9592 doc ^ "\n\n" ^ protocol_limit_warning
9595 if List.mem DangerWillRobinson flags then
9596 doc ^ "\n\n" ^ danger_will_robinson
9599 match deprecation_notice flags with
9601 | Some txt -> doc ^ "\n\n" ^ txt in
9602 let doc = pod2text ~width:60 name doc in
9603 let doc = List.map ( (* RHBZ#501883 *)
9606 | nonempty -> nonempty
9608 let doc = String.concat "\n * " doc in
9611 pr " * %s\n" shortdesc;
9614 pr " * @throws LibGuestFSException\n";
9618 generate_java_prototype ~public:true ~semicolon:false name style;
9621 pr " if (g == 0)\n";
9622 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9625 if fst style <> RErr then pr "return ";
9627 generate_java_call_args ~handle:"g" (snd style);
9631 generate_java_prototype ~privat:true ~native:true name style;
9638 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9639 and generate_java_call_args ~handle args =
9641 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9644 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9645 ?(semicolon=true) name style =
9646 if privat then pr "private ";
9647 if public then pr "public ";
9648 if native then pr "native ";
9651 (match fst style with
9652 | RErr -> pr "void ";
9653 | RInt _ -> pr "int ";
9654 | RInt64 _ -> pr "long ";
9655 | RBool _ -> pr "boolean ";
9656 | RConstString _ | RConstOptString _ | RString _
9657 | RBufferOut _ -> pr "String ";
9658 | RStringList _ -> pr "String[] ";
9659 | RStruct (_, typ) ->
9660 let name = java_name_of_struct typ in
9662 | RStructList (_, typ) ->
9663 let name = java_name_of_struct typ in
9665 | RHashtable _ -> pr "HashMap<String,String> ";
9668 if native then pr "_%s " name else pr "%s " name;
9670 let needs_comma = ref false in
9679 if !needs_comma then pr ", ";
9680 needs_comma := true;
9684 | Device n | Dev_or_Path n
9690 | StringList n | DeviceList n ->
9701 pr " throws LibGuestFSException";
9702 if semicolon then pr ";"
9704 and generate_java_struct jtyp cols () =
9705 generate_header CStyle LGPLv2plus;
9708 package com.redhat.et.libguestfs;
9711 * Libguestfs %s structure.
9723 | name, FBuffer -> pr " public String %s;\n" name
9724 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9725 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9726 | name, FChar -> pr " public char %s;\n" name
9727 | name, FOptPercent ->
9728 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9729 pr " public float %s;\n" name
9734 and generate_java_c () =
9735 generate_header CStyle LGPLv2plus;
9742 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9743 #include \"guestfs.h\"
9745 /* Note that this function returns. The exception is not thrown
9746 * until after the wrapper function returns.
9749 throw_exception (JNIEnv *env, const char *msg)
9752 cl = (*env)->FindClass (env,
9753 \"com/redhat/et/libguestfs/LibGuestFSException\");
9754 (*env)->ThrowNew (env, cl, msg);
9757 JNIEXPORT jlong JNICALL
9758 Java_com_redhat_et_libguestfs_GuestFS__1create
9759 (JNIEnv *env, jobject obj)
9763 g = guestfs_create ();
9765 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9768 guestfs_set_error_handler (g, NULL, NULL);
9769 return (jlong) (long) g;
9772 JNIEXPORT void JNICALL
9773 Java_com_redhat_et_libguestfs_GuestFS__1close
9774 (JNIEnv *env, jobject obj, jlong jg)
9776 guestfs_h *g = (guestfs_h *) (long) jg;
9783 fun (name, style, _, _, _, _, _) ->
9785 (match fst style with
9786 | RErr -> pr "void ";
9787 | RInt _ -> pr "jint ";
9788 | RInt64 _ -> pr "jlong ";
9789 | RBool _ -> pr "jboolean ";
9790 | RConstString _ | RConstOptString _ | RString _
9791 | RBufferOut _ -> pr "jstring ";
9792 | RStruct _ | RHashtable _ ->
9794 | RStringList _ | RStructList _ ->
9798 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9799 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9801 pr " (JNIEnv *env, jobject obj, jlong jg";
9805 | Device n | Dev_or_Path n
9810 pr ", jstring j%s" n
9811 | StringList n | DeviceList n ->
9812 pr ", jobjectArray j%s" n
9814 pr ", jboolean j%s" n
9822 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9823 let error_code, no_ret =
9824 match fst style with
9825 | RErr -> pr " int r;\n"; "-1", ""
9827 | RInt _ -> pr " int r;\n"; "-1", "0"
9828 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9829 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9830 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9832 pr " jstring jr;\n";
9833 pr " char *r;\n"; "NULL", "NULL"
9835 pr " jobjectArray jr;\n";
9838 pr " jstring jstr;\n";
9839 pr " char **r;\n"; "NULL", "NULL"
9840 | RStruct (_, typ) ->
9841 pr " jobject jr;\n";
9843 pr " jfieldID fl;\n";
9844 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9845 | RStructList (_, typ) ->
9846 pr " jobjectArray jr;\n";
9848 pr " jfieldID fl;\n";
9849 pr " jobject jfl;\n";
9850 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9851 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9853 pr " jstring jr;\n";
9855 pr " size_t size;\n";
9860 | Device n | Dev_or_Path n
9865 pr " const char *%s;\n" n
9866 | StringList n | DeviceList n ->
9867 pr " int %s_len;\n" n;
9868 pr " const char **%s;\n" n
9873 pr " int64_t %s;\n" n
9877 (match fst style with
9878 | RStringList _ | RStructList _ -> true
9879 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9881 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9882 List.exists (function
9883 | StringList _ -> true
9884 | DeviceList _ -> true
9885 | _ -> false) (snd style) in
9891 (* Get the parameters. *)
9895 | Device n | Dev_or_Path n
9899 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9901 (* This is completely undocumented, but Java null becomes
9904 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9905 | StringList n | DeviceList n ->
9906 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9907 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9908 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9909 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9911 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9913 pr " %s[%s_len] = NULL;\n" n n;
9917 pr " %s = j%s;\n" n n
9920 (* Make the call. *)
9921 pr " r = guestfs_%s " name;
9922 generate_c_call_args ~handle:"g" style;
9925 (* Release the parameters. *)
9929 | Device n | Dev_or_Path n
9933 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9936 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9937 | StringList n | DeviceList n ->
9938 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9939 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9941 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9943 pr " free (%s);\n" n
9949 (* Check for errors. *)
9950 pr " if (r == %s) {\n" error_code;
9951 pr " throw_exception (env, guestfs_last_error (g));\n";
9952 pr " return %s;\n" no_ret;
9956 (match fst style with
9958 | RInt _ -> pr " return (jint) r;\n"
9959 | RBool _ -> pr " return (jboolean) r;\n"
9960 | RInt64 _ -> pr " return (jlong) r;\n"
9961 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9962 | RConstOptString _ ->
9963 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9965 pr " jr = (*env)->NewStringUTF (env, r);\n";
9969 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9970 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9971 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9972 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9973 pr " for (i = 0; i < r_len; ++i) {\n";
9974 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9975 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9976 pr " free (r[i]);\n";
9980 | RStruct (_, typ) ->
9981 let jtyp = java_name_of_struct typ in
9982 let cols = cols_of_struct typ in
9983 generate_java_struct_return typ jtyp cols
9984 | RStructList (_, typ) ->
9985 let jtyp = java_name_of_struct typ in
9986 let cols = cols_of_struct typ in
9987 generate_java_struct_list_return typ jtyp cols
9990 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9991 pr " return NULL;\n"
9993 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10002 and generate_java_struct_return typ jtyp cols =
10003 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10004 pr " jr = (*env)->AllocObject (env, cl);\n";
10008 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10009 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10012 pr " char s[33];\n";
10013 pr " memcpy (s, r->%s, 32);\n" name;
10014 pr " s[32] = 0;\n";
10015 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10016 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10020 pr " int len = r->%s_len;\n" name;
10021 pr " char s[len+1];\n";
10022 pr " memcpy (s, r->%s, len);\n" name;
10023 pr " s[len] = 0;\n";
10024 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10025 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10027 | name, (FBytes|FUInt64|FInt64) ->
10028 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10029 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10030 | name, (FUInt32|FInt32) ->
10031 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10032 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10033 | name, FOptPercent ->
10034 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10035 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10037 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10038 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10043 and generate_java_struct_list_return typ jtyp cols =
10044 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10045 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10046 pr " for (i = 0; i < r->len; ++i) {\n";
10047 pr " jfl = (*env)->AllocObject (env, cl);\n";
10051 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10052 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10055 pr " char s[33];\n";
10056 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10057 pr " s[32] = 0;\n";
10058 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10059 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10063 pr " int len = r->val[i].%s_len;\n" name;
10064 pr " char s[len+1];\n";
10065 pr " memcpy (s, r->val[i].%s, len);\n" name;
10066 pr " s[len] = 0;\n";
10067 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10068 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10070 | name, (FBytes|FUInt64|FInt64) ->
10071 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10072 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10073 | name, (FUInt32|FInt32) ->
10074 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10075 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10076 | name, FOptPercent ->
10077 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10078 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10080 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10081 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10083 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10085 pr " guestfs_free_%s_list (r);\n" typ;
10088 and generate_java_makefile_inc () =
10089 generate_header HashStyle GPLv2plus;
10091 pr "java_built_sources = \\\n";
10094 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10096 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10098 and generate_haskell_hs () =
10099 generate_header HaskellStyle LGPLv2plus;
10101 (* XXX We only know how to generate partial FFI for Haskell
10102 * at the moment. Please help out!
10104 let can_generate style =
10108 | RInt64 _, _ -> true
10110 | RConstString _, _
10111 | RConstOptString _, _
10117 | RBufferOut _, _ -> false in
10120 {-# INCLUDE <guestfs.h> #-}
10121 {-# LANGUAGE ForeignFunctionInterface #-}
10126 (* List out the names of the actions we want to export. *)
10128 fun (name, style, _, _, _, _, _) ->
10129 if can_generate style then pr ",\n %s" name
10135 -- Unfortunately some symbols duplicate ones already present
10136 -- in Prelude. We don't know which, so we hard-code a list
10138 import Prelude hiding (truncate)
10142 import Foreign.C.Types
10144 import Control.Exception
10145 import Data.Typeable
10147 data GuestfsS = GuestfsS -- represents the opaque C struct
10148 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10149 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10151 -- XXX define properly later XXX
10155 data IntBool = IntBool
10157 data StatVFS = StatVFS
10158 data Hashtable = Hashtable
10160 foreign import ccall unsafe \"guestfs_create\" c_create
10162 foreign import ccall unsafe \"&guestfs_close\" c_close
10163 :: FunPtr (GuestfsP -> IO ())
10164 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10165 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10167 create :: IO GuestfsH
10170 c_set_error_handler p nullPtr nullPtr
10171 h <- newForeignPtr c_close p
10174 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10175 :: GuestfsP -> IO CString
10177 -- last_error :: GuestfsH -> IO (Maybe String)
10178 -- last_error h = do
10179 -- str <- withForeignPtr h (\\p -> c_last_error p)
10180 -- maybePeek peekCString str
10182 last_error :: GuestfsH -> IO (String)
10184 str <- withForeignPtr h (\\p -> c_last_error p)
10185 if (str == nullPtr)
10186 then return \"no error\"
10187 else peekCString str
10191 (* Generate wrappers for each foreign function. *)
10193 fun (name, style, _, _, _, _, _) ->
10194 if can_generate style then (
10195 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10197 generate_haskell_prototype ~handle:"GuestfsP" style;
10201 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10203 pr "%s %s = do\n" name
10204 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10206 (* Convert pointer arguments using with* functions. *)
10211 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10212 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10213 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10214 | Bool _ | Int _ | Int64 _ -> ()
10216 (* Convert integer arguments. *)
10220 | Bool n -> sprintf "(fromBool %s)" n
10221 | Int n -> sprintf "(fromIntegral %s)" n
10222 | Int64 n -> sprintf "(fromIntegral %s)" n
10223 | FileIn n | FileOut n
10224 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10226 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10227 (String.concat " " ("p" :: args));
10228 (match fst style with
10229 | RErr | RInt _ | RInt64 _ | RBool _ ->
10230 pr " if (r == -1)\n";
10232 pr " err <- last_error h\n";
10234 | RConstString _ | RConstOptString _ | RString _
10235 | RStringList _ | RStruct _
10236 | RStructList _ | RHashtable _ | RBufferOut _ ->
10237 pr " if (r == nullPtr)\n";
10239 pr " err <- last_error h\n";
10242 (match fst style with
10244 pr " else return ()\n"
10246 pr " else return (fromIntegral r)\n"
10248 pr " else return (fromIntegral r)\n"
10250 pr " else return (toBool r)\n"
10252 | RConstOptString _
10259 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10265 and generate_haskell_prototype ~handle ?(hs = false) style =
10266 pr "%s -> " handle;
10267 let string = if hs then "String" else "CString" in
10268 let int = if hs then "Int" else "CInt" in
10269 let bool = if hs then "Bool" else "CInt" in
10270 let int64 = if hs then "Integer" else "Int64" in
10274 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10275 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10276 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10277 | Bool _ -> pr "%s" bool
10278 | Int _ -> pr "%s" int
10279 | Int64 _ -> pr "%s" int
10280 | FileIn _ -> pr "%s" string
10281 | FileOut _ -> pr "%s" string
10286 (match fst style with
10287 | RErr -> if not hs then pr "CInt"
10288 | RInt _ -> pr "%s" int
10289 | RInt64 _ -> pr "%s" int64
10290 | RBool _ -> pr "%s" bool
10291 | RConstString _ -> pr "%s" string
10292 | RConstOptString _ -> pr "Maybe %s" string
10293 | RString _ -> pr "%s" string
10294 | RStringList _ -> pr "[%s]" string
10295 | RStruct (_, typ) ->
10296 let name = java_name_of_struct typ in
10298 | RStructList (_, typ) ->
10299 let name = java_name_of_struct typ in
10301 | RHashtable _ -> pr "Hashtable"
10302 | RBufferOut _ -> pr "%s" string
10306 and generate_csharp () =
10307 generate_header CPlusPlusStyle LGPLv2plus;
10309 (* XXX Make this configurable by the C# assembly users. *)
10310 let library = "libguestfs.so.0" in
10313 // These C# bindings are highly experimental at present.
10315 // Firstly they only work on Linux (ie. Mono). In order to get them
10316 // to work on Windows (ie. .Net) you would need to port the library
10317 // itself to Windows first.
10319 // The second issue is that some calls are known to be incorrect and
10320 // can cause Mono to segfault. Particularly: calls which pass or
10321 // return string[], or return any structure value. This is because
10322 // we haven't worked out the correct way to do this from C#.
10324 // The third issue is that when compiling you get a lot of warnings.
10325 // We are not sure whether the warnings are important or not.
10327 // Fourthly we do not routinely build or test these bindings as part
10328 // of the make && make check cycle, which means that regressions might
10331 // Suggestions and patches are welcome.
10335 // gmcs Libguestfs.cs
10336 // mono Libguestfs.exe
10338 // (You'll probably want to add a Test class / static main function
10339 // otherwise this won't do anything useful).
10343 using System.Runtime.InteropServices;
10344 using System.Runtime.Serialization;
10345 using System.Collections;
10349 class Error : System.ApplicationException
10351 public Error (string message) : base (message) {}
10352 protected Error (SerializationInfo info, StreamingContext context) {}
10359 [DllImport (\"%s\")]
10360 static extern IntPtr guestfs_create ();
10364 _handle = guestfs_create ();
10365 if (_handle == IntPtr.Zero)
10366 throw new Error (\"could not create guestfs handle\");
10369 [DllImport (\"%s\")]
10370 static extern void guestfs_close (IntPtr h);
10374 guestfs_close (_handle);
10377 [DllImport (\"%s\")]
10378 static extern string guestfs_last_error (IntPtr h);
10380 " library library library;
10382 (* Generate C# structure bindings. We prefix struct names with
10383 * underscore because C# cannot have conflicting struct names and
10384 * method names (eg. "class stat" and "stat").
10388 pr " [StructLayout (LayoutKind.Sequential)]\n";
10389 pr " public class _%s {\n" typ;
10392 | name, FChar -> pr " char %s;\n" name
10393 | name, FString -> pr " string %s;\n" name
10395 pr " uint %s_len;\n" name;
10396 pr " string %s;\n" name
10398 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10399 pr " string %s;\n" name
10400 | name, FUInt32 -> pr " uint %s;\n" name
10401 | name, FInt32 -> pr " int %s;\n" name
10402 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10403 | name, FInt64 -> pr " long %s;\n" name
10404 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10410 (* Generate C# function bindings. *)
10412 fun (name, style, _, _, _, shortdesc, _) ->
10413 let rec csharp_return_type () =
10414 match fst style with
10416 | RBool n -> "bool"
10418 | RInt64 n -> "long"
10420 | RConstOptString n
10422 | RBufferOut n -> "string"
10423 | RStruct (_,n) -> "_" ^ n
10424 | RHashtable n -> "Hashtable"
10425 | RStringList n -> "string[]"
10426 | RStructList (_,n) -> sprintf "_%s[]" n
10428 and c_return_type () =
10429 match fst style with
10433 | RInt64 _ -> "long"
10435 | RConstOptString _
10437 | RBufferOut _ -> "string"
10438 | RStruct (_,n) -> "_" ^ n
10440 | RStringList _ -> "string[]"
10441 | RStructList (_,n) -> sprintf "_%s[]" n
10443 and c_error_comparison () =
10444 match fst style with
10448 | RInt64 _ -> "== -1"
10450 | RConstOptString _
10456 | RStructList (_,_) -> "== null"
10458 and generate_extern_prototype () =
10459 pr " static extern %s guestfs_%s (IntPtr h"
10460 (c_return_type ()) name;
10463 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10464 | FileIn n | FileOut n ->
10465 pr ", [In] string %s" n
10466 | StringList n | DeviceList n ->
10467 pr ", [In] string[] %s" n
10477 and generate_public_prototype () =
10478 pr " public %s %s (" (csharp_return_type ()) name;
10479 let comma = ref false in
10481 if !comma then pr ", ";
10486 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10487 | FileIn n | FileOut n ->
10488 next (); pr "string %s" n
10489 | StringList n | DeviceList n ->
10490 next (); pr "string[] %s" n
10492 next (); pr "bool %s" n
10494 next (); pr "int %s" n
10496 next (); pr "long %s" n
10500 and generate_call () =
10501 pr "guestfs_%s (_handle" name;
10502 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10506 pr " [DllImport (\"%s\")]\n" library;
10507 generate_extern_prototype ();
10509 pr " /// <summary>\n";
10510 pr " /// %s\n" shortdesc;
10511 pr " /// </summary>\n";
10512 generate_public_prototype ();
10514 pr " %s r;\n" (c_return_type ());
10517 pr " if (r %s)\n" (c_error_comparison ());
10518 pr " throw new Error (guestfs_last_error (_handle));\n";
10519 (match fst style with
10522 pr " return r != 0 ? true : false;\n"
10524 pr " Hashtable rr = new Hashtable ();\n";
10525 pr " for (int i = 0; i < r.Length; i += 2)\n";
10526 pr " rr.Add (r[i], r[i+1]);\n";
10528 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10529 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10535 ) all_functions_sorted;
10541 and generate_bindtests () =
10542 generate_header CStyle LGPLv2plus;
10546 #include <stdlib.h>
10547 #include <inttypes.h>
10548 #include <string.h>
10550 #include \"guestfs.h\"
10551 #include \"guestfs-internal.h\"
10552 #include \"guestfs-internal-actions.h\"
10553 #include \"guestfs_protocol.h\"
10555 #define error guestfs_error
10556 #define safe_calloc guestfs_safe_calloc
10557 #define safe_malloc guestfs_safe_malloc
10560 print_strings (char *const *argv)
10565 for (argc = 0; argv[argc] != NULL; ++argc) {
10566 if (argc > 0) printf (\", \");
10567 printf (\"\\\"%%s\\\"\", argv[argc]);
10572 /* The test0 function prints its parameters to stdout. */
10576 match test_functions with
10577 | [] -> assert false
10578 | test0 :: tests -> test0, tests in
10581 let (name, style, _, _, _, _, _) = test0 in
10582 generate_prototype ~extern:false ~semicolon:false ~newline:true
10583 ~handle:"g" ~prefix:"guestfs__" name style;
10588 | Device n | Dev_or_Path n
10591 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10592 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10593 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10594 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10595 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10596 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10598 pr " /* Java changes stdout line buffering so we need this: */\n";
10599 pr " fflush (stdout);\n";
10605 fun (name, style, _, _, _, _, _) ->
10606 if String.sub name (String.length name - 3) 3 <> "err" then (
10607 pr "/* Test normal return. */\n";
10608 generate_prototype ~extern:false ~semicolon:false ~newline:true
10609 ~handle:"g" ~prefix:"guestfs__" name style;
10611 (match fst style with
10616 pr " sscanf (val, \"%%d\", &r);\n";
10619 pr " int64_t r;\n";
10620 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10623 pr " return STREQ (val, \"true\");\n"
10625 | RConstOptString _ ->
10626 (* Can't return the input string here. Return a static
10627 * string so we ensure we get a segfault if the caller
10628 * tries to free it.
10630 pr " return \"static string\";\n"
10632 pr " return strdup (val);\n"
10634 pr " char **strs;\n";
10636 pr " sscanf (val, \"%%d\", &n);\n";
10637 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10638 pr " for (i = 0; i < n; ++i) {\n";
10639 pr " strs[i] = safe_malloc (g, 16);\n";
10640 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10642 pr " strs[n] = NULL;\n";
10643 pr " return strs;\n"
10644 | RStruct (_, typ) ->
10645 pr " struct guestfs_%s *r;\n" typ;
10646 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10648 | RStructList (_, typ) ->
10649 pr " struct guestfs_%s_list *r;\n" typ;
10650 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10651 pr " sscanf (val, \"%%d\", &r->len);\n";
10652 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10655 pr " char **strs;\n";
10657 pr " sscanf (val, \"%%d\", &n);\n";
10658 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10659 pr " for (i = 0; i < n; ++i) {\n";
10660 pr " strs[i*2] = safe_malloc (g, 16);\n";
10661 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10662 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10663 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10665 pr " strs[n*2] = NULL;\n";
10666 pr " return strs;\n"
10668 pr " return strdup (val);\n"
10673 pr "/* Test error return. */\n";
10674 generate_prototype ~extern:false ~semicolon:false ~newline:true
10675 ~handle:"g" ~prefix:"guestfs__" name style;
10677 pr " error (g, \"error\");\n";
10678 (match fst style with
10679 | RErr | RInt _ | RInt64 _ | RBool _ ->
10681 | RConstString _ | RConstOptString _
10682 | RString _ | RStringList _ | RStruct _
10686 pr " return NULL;\n"
10693 and generate_ocaml_bindtests () =
10694 generate_header OCamlStyle GPLv2plus;
10698 let g = Guestfs.create () in
10702 String.concat " " (
10705 | CallString s -> "\"" ^ s ^ "\""
10706 | CallOptString None -> "None"
10707 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10708 | CallStringList xs ->
10709 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10710 | CallInt i when i >= 0 -> string_of_int i
10711 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10712 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10713 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10714 | CallBool b -> string_of_bool b
10719 generate_lang_bindtests (
10720 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10723 pr "print_endline \"EOF\"\n"
10725 and generate_perl_bindtests () =
10726 pr "#!/usr/bin/perl -w\n";
10727 generate_header HashStyle GPLv2plus;
10734 my $g = Sys::Guestfs->new ();
10738 String.concat ", " (
10741 | CallString s -> "\"" ^ s ^ "\""
10742 | CallOptString None -> "undef"
10743 | CallOptString (Some s) -> sprintf "\"%s\"" s
10744 | CallStringList xs ->
10745 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10746 | CallInt i -> string_of_int i
10747 | CallInt64 i -> Int64.to_string i
10748 | CallBool b -> if b then "1" else "0"
10753 generate_lang_bindtests (
10754 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10757 pr "print \"EOF\\n\"\n"
10759 and generate_python_bindtests () =
10760 generate_header HashStyle GPLv2plus;
10765 g = guestfs.GuestFS ()
10769 String.concat ", " (
10772 | CallString s -> "\"" ^ s ^ "\""
10773 | CallOptString None -> "None"
10774 | CallOptString (Some s) -> sprintf "\"%s\"" s
10775 | CallStringList xs ->
10776 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10777 | CallInt i -> string_of_int i
10778 | CallInt64 i -> Int64.to_string i
10779 | CallBool b -> if b then "1" else "0"
10784 generate_lang_bindtests (
10785 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10788 pr "print \"EOF\"\n"
10790 and generate_ruby_bindtests () =
10791 generate_header HashStyle GPLv2plus;
10796 g = Guestfs::create()
10800 String.concat ", " (
10803 | CallString s -> "\"" ^ s ^ "\""
10804 | CallOptString None -> "nil"
10805 | CallOptString (Some s) -> sprintf "\"%s\"" s
10806 | CallStringList xs ->
10807 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10808 | CallInt i -> string_of_int i
10809 | CallInt64 i -> Int64.to_string i
10810 | CallBool b -> string_of_bool b
10815 generate_lang_bindtests (
10816 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10819 pr "print \"EOF\\n\"\n"
10821 and generate_java_bindtests () =
10822 generate_header CStyle GPLv2plus;
10825 import com.redhat.et.libguestfs.*;
10827 public class Bindtests {
10828 public static void main (String[] argv)
10831 GuestFS g = new GuestFS ();
10835 String.concat ", " (
10838 | CallString s -> "\"" ^ s ^ "\""
10839 | CallOptString None -> "null"
10840 | CallOptString (Some s) -> sprintf "\"%s\"" s
10841 | CallStringList xs ->
10843 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10844 | CallInt i -> string_of_int i
10845 | CallInt64 i -> Int64.to_string i
10846 | CallBool b -> string_of_bool b
10851 generate_lang_bindtests (
10852 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10856 System.out.println (\"EOF\");
10858 catch (Exception exn) {
10859 System.err.println (exn);
10866 and generate_haskell_bindtests () =
10867 generate_header HaskellStyle GPLv2plus;
10870 module Bindtests where
10871 import qualified Guestfs
10874 g <- Guestfs.create
10878 String.concat " " (
10881 | CallString s -> "\"" ^ s ^ "\""
10882 | CallOptString None -> "Nothing"
10883 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10884 | CallStringList xs ->
10885 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10886 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10887 | CallInt i -> string_of_int i
10888 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10889 | CallInt64 i -> Int64.to_string i
10890 | CallBool true -> "True"
10891 | CallBool false -> "False"
10896 generate_lang_bindtests (
10897 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10900 pr " putStrLn \"EOF\"\n"
10902 (* Language-independent bindings tests - we do it this way to
10903 * ensure there is parity in testing bindings across all languages.
10905 and generate_lang_bindtests call =
10906 call "test0" [CallString "abc"; CallOptString (Some "def");
10907 CallStringList []; CallBool false;
10908 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10909 call "test0" [CallString "abc"; CallOptString None;
10910 CallStringList []; CallBool false;
10911 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10912 call "test0" [CallString ""; CallOptString (Some "def");
10913 CallStringList []; CallBool false;
10914 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10915 call "test0" [CallString ""; CallOptString (Some "");
10916 CallStringList []; CallBool false;
10917 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10918 call "test0" [CallString "abc"; CallOptString (Some "def");
10919 CallStringList ["1"]; CallBool false;
10920 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10921 call "test0" [CallString "abc"; CallOptString (Some "def");
10922 CallStringList ["1"; "2"]; CallBool false;
10923 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10924 call "test0" [CallString "abc"; CallOptString (Some "def");
10925 CallStringList ["1"]; CallBool true;
10926 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10927 call "test0" [CallString "abc"; CallOptString (Some "def");
10928 CallStringList ["1"]; CallBool false;
10929 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10930 call "test0" [CallString "abc"; CallOptString (Some "def");
10931 CallStringList ["1"]; CallBool false;
10932 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10933 call "test0" [CallString "abc"; CallOptString (Some "def");
10934 CallStringList ["1"]; CallBool false;
10935 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10936 call "test0" [CallString "abc"; CallOptString (Some "def");
10937 CallStringList ["1"]; CallBool false;
10938 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10939 call "test0" [CallString "abc"; CallOptString (Some "def");
10940 CallStringList ["1"]; CallBool false;
10941 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10942 call "test0" [CallString "abc"; CallOptString (Some "def");
10943 CallStringList ["1"]; CallBool false;
10944 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10946 (* XXX Add here tests of the return and error functions. *)
10948 (* Code to generator bindings for virt-inspector. Currently only
10949 * implemented for OCaml code (for virt-p2v 2.0).
10951 let rng_input = "inspector/virt-inspector.rng"
10953 (* Read the input file and parse it into internal structures. This is
10954 * by no means a complete RELAX NG parser, but is just enough to be
10955 * able to parse the specific input file.
10958 | Element of string * rng list (* <element name=name/> *)
10959 | Attribute of string * rng list (* <attribute name=name/> *)
10960 | Interleave of rng list (* <interleave/> *)
10961 | ZeroOrMore of rng (* <zeroOrMore/> *)
10962 | OneOrMore of rng (* <oneOrMore/> *)
10963 | Optional of rng (* <optional/> *)
10964 | Choice of string list (* <choice><value/>*</choice> *)
10965 | Value of string (* <value>str</value> *)
10966 | Text (* <text/> *)
10968 let rec string_of_rng = function
10969 | Element (name, xs) ->
10970 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10971 | Attribute (name, xs) ->
10972 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10973 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10974 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10975 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10976 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10977 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10978 | Value value -> "Value \"" ^ value ^ "\""
10981 and string_of_rng_list xs =
10982 String.concat ", " (List.map string_of_rng xs)
10984 let rec parse_rng ?defines context = function
10986 | Xml.Element ("element", ["name", name], children) :: rest ->
10987 Element (name, parse_rng ?defines context children)
10988 :: parse_rng ?defines context rest
10989 | Xml.Element ("attribute", ["name", name], children) :: rest ->
10990 Attribute (name, parse_rng ?defines context children)
10991 :: parse_rng ?defines context rest
10992 | Xml.Element ("interleave", [], children) :: rest ->
10993 Interleave (parse_rng ?defines context children)
10994 :: parse_rng ?defines context rest
10995 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10996 let rng = parse_rng ?defines context [child] in
10998 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11000 failwithf "%s: <zeroOrMore> contains more than one child element"
11003 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11004 let rng = parse_rng ?defines context [child] in
11006 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11008 failwithf "%s: <oneOrMore> contains more than one child element"
11011 | Xml.Element ("optional", [], [child]) :: rest ->
11012 let rng = parse_rng ?defines context [child] in
11014 | [child] -> Optional child :: parse_rng ?defines context rest
11016 failwithf "%s: <optional> contains more than one child element"
11019 | Xml.Element ("choice", [], children) :: rest ->
11020 let values = List.map (
11021 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11023 failwithf "%s: can't handle anything except <value> in <choice>"
11027 :: parse_rng ?defines context rest
11028 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11029 Value value :: parse_rng ?defines context rest
11030 | Xml.Element ("text", [], []) :: rest ->
11031 Text :: parse_rng ?defines context rest
11032 | Xml.Element ("ref", ["name", name], []) :: rest ->
11033 (* Look up the reference. Because of limitations in this parser,
11034 * we can't handle arbitrarily nested <ref> yet. You can only
11035 * use <ref> from inside <start>.
11037 (match defines with
11039 failwithf "%s: contains <ref>, but no refs are defined yet" context
11041 let rng = StringMap.find name map in
11042 rng @ parse_rng ?defines context rest
11045 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11048 let xml = Xml.parse_file rng_input in
11050 | Xml.Element ("grammar", _,
11051 Xml.Element ("start", _, gram) :: defines) ->
11052 (* The <define/> elements are referenced in the <start> section,
11053 * so build a map of those first.
11055 let defines = List.fold_left (
11057 function Xml.Element ("define", ["name", name], defn) ->
11058 StringMap.add name defn map
11060 failwithf "%s: expected <define name=name/>" rng_input
11061 ) StringMap.empty defines in
11062 let defines = StringMap.mapi parse_rng defines in
11064 (* Parse the <start> clause, passing the defines. *)
11065 parse_rng ~defines "<start>" gram
11067 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11070 let name_of_field = function
11071 | Element (name, _) | Attribute (name, _)
11072 | ZeroOrMore (Element (name, _))
11073 | OneOrMore (Element (name, _))
11074 | Optional (Element (name, _)) -> name
11075 | Optional (Attribute (name, _)) -> name
11076 | Text -> (* an unnamed field in an element *)
11079 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11081 (* At the moment this function only generates OCaml types. However we
11082 * should parameterize it later so it can generate types/structs in a
11083 * variety of languages.
11085 let generate_types xs =
11086 (* A simple type is one that can be printed out directly, eg.
11087 * "string option". A complex type is one which has a name and has
11088 * to be defined via another toplevel definition, eg. a struct.
11090 * generate_type generates code for either simple or complex types.
11091 * In the simple case, it returns the string ("string option"). In
11092 * the complex case, it returns the name ("mountpoint"). In the
11093 * complex case it has to print out the definition before returning,
11094 * so it should only be called when we are at the beginning of a
11095 * new line (BOL context).
11097 let rec generate_type = function
11098 | Text -> (* string *)
11100 | Choice values -> (* [`val1|`val2|...] *)
11101 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11102 | ZeroOrMore rng -> (* <rng> list *)
11103 let t, is_simple = generate_type rng in
11104 t ^ " list (* 0 or more *)", is_simple
11105 | OneOrMore rng -> (* <rng> list *)
11106 let t, is_simple = generate_type rng in
11107 t ^ " list (* 1 or more *)", is_simple
11108 (* virt-inspector hack: bool *)
11109 | Optional (Attribute (name, [Value "1"])) ->
11111 | Optional rng -> (* <rng> list *)
11112 let t, is_simple = generate_type rng in
11113 t ^ " option", is_simple
11114 (* type name = { fields ... } *)
11115 | Element (name, fields) when is_attrs_interleave fields ->
11116 generate_type_struct name (get_attrs_interleave fields)
11117 | Element (name, [field]) (* type name = field *)
11118 | Attribute (name, [field]) ->
11119 let t, is_simple = generate_type field in
11120 if is_simple then (t, true)
11122 pr "type %s = %s\n" name t;
11125 | Element (name, fields) -> (* type name = { fields ... } *)
11126 generate_type_struct name fields
11128 failwithf "generate_type failed at: %s" (string_of_rng rng)
11130 and is_attrs_interleave = function
11131 | [Interleave _] -> true
11132 | Attribute _ :: fields -> is_attrs_interleave fields
11133 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11136 and get_attrs_interleave = function
11137 | [Interleave fields] -> fields
11138 | ((Attribute _) as field) :: fields
11139 | ((Optional (Attribute _)) as field) :: fields ->
11140 field :: get_attrs_interleave fields
11141 | _ -> assert false
11143 and generate_types xs =
11144 List.iter (fun x -> ignore (generate_type x)) xs
11146 and generate_type_struct name fields =
11147 (* Calculate the types of the fields first. We have to do this
11148 * before printing anything so we are still in BOL context.
11150 let types = List.map fst (List.map generate_type fields) in
11152 (* Special case of a struct containing just a string and another
11153 * field. Turn it into an assoc list.
11156 | ["string"; other] ->
11157 let fname1, fname2 =
11159 | [f1; f2] -> name_of_field f1, name_of_field f2
11160 | _ -> assert false in
11161 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11165 pr "type %s = {\n" name;
11167 fun (field, ftype) ->
11168 let fname = name_of_field field in
11169 pr " %s_%s : %s;\n" name fname ftype
11170 ) (List.combine fields types);
11172 (* Return the name of this type, and
11173 * false because it's not a simple type.
11180 let generate_parsers xs =
11181 (* As for generate_type above, generate_parser makes a parser for
11182 * some type, and returns the name of the parser it has generated.
11183 * Because it (may) need to print something, it should always be
11184 * called in BOL context.
11186 let rec generate_parser = function
11187 | Text -> (* string *)
11188 "string_child_or_empty"
11189 | Choice values -> (* [`val1|`val2|...] *)
11190 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11192 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11193 | ZeroOrMore rng -> (* <rng> list *)
11194 let pa = generate_parser rng in
11195 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11196 | OneOrMore rng -> (* <rng> list *)
11197 let pa = generate_parser rng in
11198 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11199 (* virt-inspector hack: bool *)
11200 | Optional (Attribute (name, [Value "1"])) ->
11201 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11202 | Optional rng -> (* <rng> list *)
11203 let pa = generate_parser rng in
11204 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11205 (* type name = { fields ... } *)
11206 | Element (name, fields) when is_attrs_interleave fields ->
11207 generate_parser_struct name (get_attrs_interleave fields)
11208 | Element (name, [field]) -> (* type name = field *)
11209 let pa = generate_parser field in
11210 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11211 pr "let %s =\n" parser_name;
11213 pr "let parse_%s = %s\n" name parser_name;
11215 | Attribute (name, [field]) ->
11216 let pa = generate_parser field in
11217 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11218 pr "let %s =\n" parser_name;
11220 pr "let parse_%s = %s\n" name parser_name;
11222 | Element (name, fields) -> (* type name = { fields ... } *)
11223 generate_parser_struct name ([], fields)
11225 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11227 and is_attrs_interleave = function
11228 | [Interleave _] -> true
11229 | Attribute _ :: fields -> is_attrs_interleave fields
11230 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11233 and get_attrs_interleave = function
11234 | [Interleave fields] -> [], fields
11235 | ((Attribute _) as field) :: fields
11236 | ((Optional (Attribute _)) as field) :: fields ->
11237 let attrs, interleaves = get_attrs_interleave fields in
11238 (field :: attrs), interleaves
11239 | _ -> assert false
11241 and generate_parsers xs =
11242 List.iter (fun x -> ignore (generate_parser x)) xs
11244 and generate_parser_struct name (attrs, interleaves) =
11245 (* Generate parsers for the fields first. We have to do this
11246 * before printing anything so we are still in BOL context.
11248 let fields = attrs @ interleaves in
11249 let pas = List.map generate_parser fields in
11251 (* Generate an intermediate tuple from all the fields first.
11252 * If the type is just a string + another field, then we will
11253 * return this directly, otherwise it is turned into a record.
11255 * RELAX NG note: This code treats <interleave> and plain lists of
11256 * fields the same. In other words, it doesn't bother enforcing
11257 * any ordering of fields in the XML.
11259 pr "let parse_%s x =\n" name;
11260 pr " let t = (\n ";
11261 let comma = ref false in
11264 if !comma then pr ",\n ";
11267 | Optional (Attribute (fname, [field])), pa ->
11269 | Optional (Element (fname, [field])), pa ->
11270 pr "%s (optional_child %S x)" pa fname
11271 | Attribute (fname, [Text]), _ ->
11272 pr "attribute %S x" fname
11273 | (ZeroOrMore _ | OneOrMore _), pa ->
11278 let fname = name_of_field field in
11279 pr "%s (child %S x)" pa fname
11280 ) (List.combine fields pas);
11284 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11288 pr " (Obj.magic t : %s)\n" name
11292 | (Optional (Attribute (fname, [field])), pa) ->
11293 pr " %s_%s =\n" name fname;
11295 | (Optional (Element (fname, [field])), pa) ->
11296 pr " %s_%s =\n" name fname;
11297 pr " (let x = optional_child %S x in\n" fname;
11300 let fname = name_of_field field in
11301 pr " %s_%s =\n" name fname;
11302 pr " (let x = child %S x in\n" fname;
11304 ) (List.combine fields pas);
11308 sprintf "parse_%s" name
11311 generate_parsers xs
11313 (* Generate ocaml/guestfs_inspector.mli. *)
11314 let generate_ocaml_inspector_mli () =
11315 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11318 (** This is an OCaml language binding to the external [virt-inspector]
11321 For more information, please read the man page [virt-inspector(1)].
11326 generate_types grammar;
11327 pr "(** The nested information returned from the {!inspect} function. *)\n";
11331 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11332 (** To inspect a libvirt domain called [name], pass a singleton
11333 list: [inspect [name]]. When using libvirt only, you may
11334 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11336 To inspect a disk image or images, pass a list of the filenames
11337 of the disk images: [inspect filenames]
11339 This function inspects the given guest or disk images and
11340 returns a list of operating system(s) found and a large amount
11341 of information about them. In the vast majority of cases,
11342 a virtual machine only contains a single operating system.
11344 If the optional [~xml] parameter is given, then this function
11345 skips running the external virt-inspector program and just
11346 parses the given XML directly (which is expected to be XML
11347 produced from a previous run of virt-inspector). The list of
11348 names and connect URI are ignored in this case.
11350 This function can throw a wide variety of exceptions, for example
11351 if the external virt-inspector program cannot be found, or if
11352 it doesn't generate valid XML.
11356 (* Generate ocaml/guestfs_inspector.ml. *)
11357 let generate_ocaml_inspector_ml () =
11358 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11363 generate_types grammar;
11367 (* Misc functions which are used by the parser code below. *)
11368 let first_child = function
11369 | Xml.Element (_, _, c::_) -> c
11370 | Xml.Element (name, _, []) ->
11371 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11372 | Xml.PCData str ->
11373 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11375 let string_child_or_empty = function
11376 | Xml.Element (_, _, [Xml.PCData s]) -> s
11377 | Xml.Element (_, _, []) -> \"\"
11378 | Xml.Element (x, _, _) ->
11379 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11381 | Xml.PCData str ->
11382 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11384 let optional_child name xml =
11385 let children = Xml.children xml in
11387 Some (List.find (function
11388 | Xml.Element (n, _, _) when n = name -> true
11389 | _ -> false) children)
11393 let child name xml =
11394 match optional_child name xml with
11397 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11399 let attribute name xml =
11400 try Xml.attrib xml name
11401 with Xml.No_attribute _ ->
11402 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11406 generate_parsers grammar;
11410 (* Run external virt-inspector, then use parser to parse the XML. *)
11411 let inspect ?connect ?xml names =
11415 if names = [] then invalid_arg \"inspect: no names given\";
11416 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11417 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11419 let cmd = List.map Filename.quote cmd in
11420 let cmd = String.concat \" \" cmd in
11421 let chan = open_process_in cmd in
11422 let xml = Xml.parse_in chan in
11423 (match close_process_in chan with
11425 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11426 | WSIGNALED i | WSTOPPED i ->
11427 failwith (\"external virt-inspector command died or stopped on sig \" ^
11432 Xml.parse_string doc in
11433 parse_operatingsystems xml
11436 (* This is used to generate the src/MAX_PROC_NR file which
11437 * contains the maximum procedure number, a surrogate for the
11438 * ABI version number. See src/Makefile.am for the details.
11440 and generate_max_proc_nr () =
11441 let proc_nrs = List.map (
11442 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11443 ) daemon_functions in
11445 let max_proc_nr = List.fold_left max 0 proc_nrs in
11447 pr "%d\n" max_proc_nr
11449 let output_to filename k =
11450 let filename_new = filename ^ ".new" in
11451 chan := open_out filename_new;
11454 chan := Pervasives.stdout;
11456 (* Is the new file different from the current file? *)
11457 if Sys.file_exists filename && files_equal filename filename_new then
11458 unlink filename_new (* same, so skip it *)
11460 (* different, overwrite old one *)
11461 (try chmod filename 0o644 with Unix_error _ -> ());
11462 rename filename_new filename;
11463 chmod filename 0o444;
11464 printf "written %s\n%!" filename;
11467 let perror msg = function
11468 | Unix_error (err, _, _) ->
11469 eprintf "%s: %s\n" msg (error_message err)
11471 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11473 (* Main program. *)
11476 try openfile "HACKING" [O_RDWR] 0
11478 | Unix_error (ENOENT, _, _) ->
11480 You are probably running this from the wrong directory.
11481 Run it from the top source directory using the command
11486 perror "open: HACKING" exn;
11489 (* Acquire a lock so parallel builds won't try to run the generator
11490 * twice at the same time. Subsequent builds will wait for the first
11491 * one to finish. Note the lock is released implicitly when the
11494 (try lockf lock_fd F_LOCK 1
11496 perror "lock: HACKING" exn;
11499 check_functions ();
11501 output_to "src/guestfs_protocol.x" generate_xdr;
11502 output_to "src/guestfs-structs.h" generate_structs_h;
11503 output_to "src/guestfs-actions.h" generate_actions_h;
11504 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11505 output_to "src/guestfs-actions.c" generate_client_actions;
11506 output_to "src/guestfs-bindtests.c" generate_bindtests;
11507 output_to "src/guestfs-structs.pod" generate_structs_pod;
11508 output_to "src/guestfs-actions.pod" generate_actions_pod;
11509 output_to "src/guestfs-availability.pod" generate_availability_pod;
11510 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11511 output_to "src/libguestfs.syms" generate_linker_script;
11512 output_to "daemon/actions.h" generate_daemon_actions_h;
11513 output_to "daemon/stubs.c" generate_daemon_actions;
11514 output_to "daemon/names.c" generate_daemon_names;
11515 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11516 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11517 output_to "capitests/tests.c" generate_tests;
11518 output_to "fish/cmds.c" generate_fish_cmds;
11519 output_to "fish/completion.c" generate_fish_completion;
11520 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11521 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11522 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11523 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11524 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11525 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11526 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11527 output_to "perl/Guestfs.xs" generate_perl_xs;
11528 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11529 output_to "perl/bindtests.pl" generate_perl_bindtests;
11530 output_to "python/guestfs-py.c" generate_python_c;
11531 output_to "python/guestfs.py" generate_python_py;
11532 output_to "python/bindtests.py" generate_python_bindtests;
11533 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11534 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11535 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11539 let cols = cols_of_struct typ in
11540 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11541 output_to filename (generate_java_struct jtyp cols);
11544 output_to "java/Makefile.inc" generate_java_makefile_inc;
11545 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11546 output_to "java/Bindtests.java" generate_java_bindtests;
11547 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11548 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11549 output_to "csharp/Libguestfs.cs" generate_csharp;
11551 (* Always generate this file last, and unconditionally. It's used
11552 * by the Makefile to know when we must re-run the generator.
11554 let chan = open_out "src/stamp-generator" in
11555 fprintf chan "1\n";
11558 printf "generated %d lines of code\n" !lines