3 * Copyright (C) 2009 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 below), and
25 * daemon/<somefile>.c to write the implementation.
27 * After editing this file, run it (./src/generator.ml) to regenerate all the
28 * output files. Note that if you are using a separate build directory you
29 * must run generator.ml from the _source_ directory.
31 * IMPORTANT: This script should NOT print any warnings. If it prints
32 * warnings, you should treat them as errors.
40 type style = ret * args
42 (* "RErr" as a return value means an int used as a simple error
43 * indication, ie. 0 or -1.
47 (* "RInt" as a return value means an int which is -1 for error
48 * or any value >= 0 on success. Only use this for smallish
49 * positive ints (0 <= i < 2^30).
53 (* "RInt64" is the same as RInt, but is guaranteed to be able
54 * to return a full 64 bit value, _except_ that -1 means error
55 * (so -1 cannot be a valid, non-error return value).
59 (* "RBool" is a bool return value which can be true/false or
64 (* "RConstString" is a string that refers to a constant value.
65 * The return value must NOT be NULL (since NULL indicates
68 * Try to avoid using this. In particular you cannot use this
69 * for values returned from the daemon, because there is no
70 * thread-safe way to return them in the C API.
72 | RConstString of string
74 (* "RConstOptString" is an even more broken version of
75 * "RConstString". The returned string may be NULL and there
76 * is no way to return an error indication. Avoid using this!
78 | RConstOptString of string
80 (* "RString" is a returned string. It must NOT be NULL, since
81 * a NULL return indicates an error. The caller frees this.
85 (* "RStringList" is a list of strings. No string in the list
86 * can be NULL. The caller frees the strings and the array.
88 | RStringList of string
90 (* "RStruct" is a function which returns a single named structure
91 * or an error indication (in C, a struct, and in other languages
92 * with varying representations, but usually very efficient). See
93 * after the function list below for the structures.
95 | RStruct of string * string (* name of retval, name of struct *)
97 (* "RStructList" is a function which returns either a list/array
98 * of structures (could be zero-length), or an error indication.
100 | RStructList of string * string (* name of retval, name of struct *)
102 (* Key-value pairs of untyped strings. Turns into a hashtable or
103 * dictionary in languages which support it. DON'T use this as a
104 * general "bucket" for results. Prefer a stronger typed return
105 * value if one is available, or write a custom struct. Don't use
106 * this if the list could potentially be very long, since it is
107 * inefficient. Keys should be unique. NULLs are not permitted.
109 | RHashtable of string
111 (* "RBufferOut" is handled almost exactly like RString, but
112 * it allows the string to contain arbitrary 8 bit data including
113 * ASCII NUL. In the C API this causes an implicit extra parameter
114 * to be added of type <size_t *size_r>. The extra parameter
115 * returns the actual size of the return buffer in bytes.
117 * Other programming languages support strings with arbitrary 8 bit
120 * At the RPC layer we have to use the opaque<> type instead of
121 * string<>. Returned data is still limited to the max message
124 | RBufferOut of string
126 and args = argt list (* Function parameters, guestfs handle is implicit. *)
128 (* Note in future we should allow a "variable args" parameter as
129 * the final parameter, to allow commands like
130 * chmod mode file [file(s)...]
131 * This is not implemented yet, but many commands (such as chmod)
132 * are currently defined with the argument order keeping this future
133 * possibility in mind.
136 | String of string (* const char *name, cannot be NULL *)
137 | Device of string (* /dev device name, cannot be NULL *)
138 | Pathname of string (* file name, cannot be NULL *)
139 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140 | OptString of string (* const char *name, may be NULL *)
141 | StringList of string(* list of strings (each string cannot be NULL) *)
142 | DeviceList of string(* list of Device names (each cannot be NULL) *)
143 | Bool of string (* boolean *)
144 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
145 (* These are treated as filenames (simple string parameters) in
146 * the C API and bindings. But in the RPC protocol, we transfer
147 * the actual file content up to or down from the daemon.
148 * FileIn: local machine -> daemon (in request)
149 * FileOut: daemon -> local machine (in reply)
150 * In guestfish (only), the special name "-" means read from
151 * stdin or write to stdout.
156 (* Opaque buffer which can contain arbitrary 8 bit data.
157 * In the C API, this is expressed as <char *, int> pair.
158 * Most other languages have a string type which can contain
159 * ASCII NUL. We use whatever type is appropriate for each
161 * Buffers are limited by the total message size. To transfer
162 * large blocks of data, use FileIn/FileOut parameters instead.
163 * To return an arbitrary buffer, use RBufferOut.
169 | ProtocolLimitWarning (* display warning about protocol size limits *)
170 | DangerWillRobinson (* flags particularly dangerous commands *)
171 | FishAlias of string (* provide an alias for this cmd in guestfish *)
172 | FishAction of string (* call this function in guestfish *)
173 | NotInFish (* do not export via guestfish *)
174 | NotInDocs (* do not add this function to documentation *)
175 | DeprecatedBy of string (* function is deprecated, use .. instead *)
177 (* You can supply zero or as many tests as you want per API call.
179 * Note that the test environment has 3 block devices, of size 500MB,
180 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181 * a fourth ISO block device with some known files on it (/dev/sdd).
183 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184 * Number of cylinders was 63 for IDE emulated disks with precisely
185 * the same size. How exactly this is calculated is a mystery.
187 * The ISO block device (/dev/sdd) comes from images/test.iso.
189 * To be able to run the tests in a reasonable amount of time,
190 * the virtual machine and block devices are reused between tests.
191 * So don't try testing kill_subprocess :-x
193 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
195 * Don't assume anything about the previous contents of the block
196 * devices. Use 'Init*' to create some initial scenarios.
198 * You can add a prerequisite clause to any individual test. This
199 * is a run-time check, which, if it fails, causes the test to be
200 * skipped. Useful if testing a command which might not work on
201 * all variations of libguestfs builds. A test that has prerequisite
202 * of 'Always' is run unconditionally.
204 * In addition, packagers can skip individual tests by setting the
205 * environment variables: eg:
206 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
207 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
209 type tests = (test_init * test_prereq * test) list
211 (* Run the command sequence and just expect nothing to fail. *)
214 (* Run the command sequence and expect the output of the final
215 * command to be the string.
217 | TestOutput of seq * string
219 (* Run the command sequence and expect the output of the final
220 * command to be the list of strings.
222 | TestOutputList of seq * string list
224 (* Run the command sequence and expect the output of the final
225 * command to be the list of block devices (could be either
226 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227 * character of each string).
229 | TestOutputListOfDevices of seq * string list
231 (* Run the command sequence and expect the output of the final
232 * command to be the integer.
234 | TestOutputInt of seq * int
236 (* Run the command sequence and expect the output of the final
237 * command to be <op> <int>, eg. ">=", "1".
239 | TestOutputIntOp of seq * string * int
241 (* Run the command sequence and expect the output of the final
242 * command to be a true value (!= 0 or != NULL).
244 | TestOutputTrue of seq
246 (* Run the command sequence and expect the output of the final
247 * command to be a false value (== 0 or == NULL, but not an error).
249 | TestOutputFalse of seq
251 (* Run the command sequence and expect the output of the final
252 * command to be a list of the given length (but don't care about
255 | TestOutputLength of seq * int
257 (* Run the command sequence and expect the output of the final
258 * command to be a buffer (RBufferOut), ie. string + size.
260 | TestOutputBuffer of seq * string
262 (* Run the command sequence and expect the output of the final
263 * command to be a structure.
265 | TestOutputStruct of seq * test_field_compare list
267 (* Run the command sequence and expect the final command (only)
270 | TestLastFail of seq
272 and test_field_compare =
273 | CompareWithInt of string * int
274 | CompareWithIntOp of string * string * int
275 | CompareWithString of string * string
276 | CompareFieldsIntEq of string * string
277 | CompareFieldsStrEq of string * string
279 (* Test prerequisites. *)
281 (* Test always runs. *)
284 (* Test is currently disabled - eg. it fails, or it tests some
285 * unimplemented feature.
289 (* 'string' is some C code (a function body) that should return
290 * true or false. The test will run if the code returns true.
294 (* As for 'If' but the test runs _unless_ the code returns true. *)
297 (* Some initial scenarios for testing. *)
299 (* Do nothing, block devices could contain random stuff including
300 * LVM PVs, and some filesystems might be mounted. This is usually
305 (* Block devices are empty and no filesystems are mounted. *)
308 (* /dev/sda contains a single partition /dev/sda1, with random
309 * content. /dev/sdb and /dev/sdc may have random content.
314 (* /dev/sda contains a single partition /dev/sda1, which is formatted
315 * as ext2, empty [except for lost+found] and mounted on /.
316 * /dev/sdb and /dev/sdc may have random content.
322 * /dev/sda1 (is a PV):
323 * /dev/VG/LV (size 8MB):
324 * formatted as ext2, empty [except for lost+found], mounted on /
325 * /dev/sdb and /dev/sdc may have random content.
329 (* /dev/sdd (the ISO, see images/ directory in source)
334 (* Sequence of commands for testing. *)
336 and cmd = string list
338 (* Note about long descriptions: When referring to another
339 * action, use the format C<guestfs_other> (ie. the full name of
340 * the C function). This will be replaced as appropriate in other
343 * Apart from that, long descriptions are just perldoc paragraphs.
346 (* Generate a random UUID (used in tests). *)
348 let chan = Unix.open_process_in "uuidgen" in
349 let uuid = input_line chan in
350 (match Unix.close_process_in chan with
351 | Unix.WEXITED 0 -> ()
353 failwith "uuidgen: process exited with non-zero status"
354 | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355 failwith "uuidgen: process signalled or stopped by signal"
359 (* These test functions are used in the language binding tests. *)
361 let test_all_args = [
364 StringList "strlist";
371 let test_all_rets = [
372 (* except for RErr, which is tested thoroughly elsewhere *)
373 "test0rint", RInt "valout";
374 "test0rint64", RInt64 "valout";
375 "test0rbool", RBool "valout";
376 "test0rconststring", RConstString "valout";
377 "test0rconstoptstring", RConstOptString "valout";
378 "test0rstring", RString "valout";
379 "test0rstringlist", RStringList "valout";
380 "test0rstruct", RStruct ("valout", "lvm_pv");
381 "test0rstructlist", RStructList ("valout", "lvm_pv");
382 "test0rhashtable", RHashtable "valout";
385 let test_functions = [
386 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
388 "internal test function - do not use",
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
394 It echos the contents of each parameter to stdout.
396 You probably don't want to call this function.");
400 [(name, (ret, [String "val"]), -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 return type correctly.
408 It converts string C<val> to the return type.
410 You probably don't want to call this function.");
411 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
413 "internal test function - do not use",
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
419 This function always returns an error.
421 You probably don't want to call this function.")]
425 (* non_daemon_functions are any functions which don't get processed
426 * in the daemon, eg. functions for setting and getting local
427 * configuration values.
430 let non_daemon_functions = test_functions @ [
431 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
433 "launch the qemu subprocess",
435 Internally libguestfs is implemented by running a virtual machine
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
441 ("wait_ready", (RErr, []), -1, [NotInFish],
443 "wait until the qemu subprocess launches (no op)",
445 This function is a no op.
447 In versions of the API E<lt> 1.0.71 you had to call this function
448 just after calling C<guestfs_launch> to wait for the launch
449 to complete. However this is no longer necessary because
450 C<guestfs_launch> now does the waiting.
452 If you see any calls to this function in code then you can just
453 remove them, unless you want to retain compatibility with older
454 versions of the API.");
456 ("kill_subprocess", (RErr, []), -1, [],
458 "kill the qemu subprocess",
460 This kills the qemu subprocess. You should never need to call this.");
462 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
464 "add an image to examine or modify",
466 This function adds a virtual machine disk image C<filename> to the
467 guest. The first time you call this function, the disk appears as IDE
468 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
471 You don't necessarily need to be root when using libguestfs. However
472 you obviously do need sufficient permissions to access the filename
473 for whatever operations you want to perform (ie. read access if you
474 just want to read the image or write access if you want to modify the
477 This is equivalent to the qemu parameter
478 C<-drive file=filename,cache=off,if=...>.
479 C<cache=off> is omitted in cases where it is not supported by
480 the underlying filesystem.
482 Note that this call checks for the existence of C<filename>. This
483 stops you from specifying other types of drive which are supported
484 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
485 the general C<guestfs_config> call instead.");
487 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
489 "add a CD-ROM disk image to examine",
491 This function adds a virtual CD-ROM disk image to the guest.
493 This is equivalent to the qemu parameter C<-cdrom filename>.
495 Note that this call checks for the existence of C<filename>. This
496 stops you from specifying other types of drive which are supported
497 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
498 the general C<guestfs_config> call instead.");
500 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
502 "add a drive in snapshot mode (read-only)",
504 This adds a drive in snapshot mode, making it effectively
507 Note that writes to the device are allowed, and will be seen for
508 the duration of the guestfs handle, but they are written
509 to a temporary file which is discarded as soon as the guestfs
510 handle is closed. We don't currently have any method to enable
511 changes to be committed, although qemu can support this.
513 This is equivalent to the qemu parameter
514 C<-drive file=filename,snapshot=on,if=...>.
516 Note that this call checks for the existence of C<filename>. This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
519 the general C<guestfs_config> call instead.");
521 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
523 "add qemu parameters",
525 This can be used to add arbitrary qemu command line parameters
526 of the form C<-param value>. Actually it's not quite arbitrary - we
527 prevent you from setting some parameters which would interfere with
528 parameters that we use.
530 The first character of C<param> string must be a C<-> (dash).
532 C<value> can be NULL.");
534 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
536 "set the qemu binary",
538 Set the qemu binary that we will use.
540 The default is chosen when the library was compiled by the
543 You can also override this by setting the C<LIBGUESTFS_QEMU>
544 environment variable.
546 Setting C<qemu> to C<NULL> restores the default qemu binary.");
548 ("get_qemu", (RConstString "qemu", []), -1, [],
549 [InitNone, Always, TestRun (
551 "get the qemu binary",
553 Return the current qemu binary.
555 This is always non-NULL. If it wasn't set already, then this will
556 return the default qemu binary name.");
558 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
560 "set the search path",
562 Set the path that libguestfs searches for kernel and initrd.img.
564 The default is C<$libdir/guestfs> unless overridden by setting
565 C<LIBGUESTFS_PATH> environment variable.
567 Setting C<path> to C<NULL> restores the default path.");
569 ("get_path", (RConstString "path", []), -1, [],
570 [InitNone, Always, TestRun (
572 "get the search path",
574 Return the current search path.
576 This is always non-NULL. If it wasn't set already, then this will
577 return the default path.");
579 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
581 "add options to kernel command line",
583 This function is used to add additional options to the
584 guest kernel command line.
586 The default is C<NULL> unless overridden by setting
587 C<LIBGUESTFS_APPEND> environment variable.
589 Setting C<append> to C<NULL> means I<no> additional options
590 are passed (libguestfs always adds a few of its own).");
592 ("get_append", (RConstOptString "append", []), -1, [],
593 (* This cannot be tested with the current framework. The
594 * function can return NULL in normal operations, which the
595 * test framework interprets as an error.
598 "get the additional kernel options",
600 Return the additional kernel options which are added to the
601 guest kernel command line.
603 If C<NULL> then no options are added.");
605 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
609 If C<autosync> is true, this enables autosync. Libguestfs will make a
610 best effort attempt to run C<guestfs_umount_all> followed by
611 C<guestfs_sync> when the handle is closed
612 (also if the program exits without closing handles).
614 This is disabled by default (except in guestfish where it is
615 enabled by default).");
617 ("get_autosync", (RBool "autosync", []), -1, [],
618 [InitNone, Always, TestRun (
619 [["get_autosync"]])],
622 Get the autosync flag.");
624 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
628 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
630 Verbose messages are disabled unless the environment variable
631 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
633 ("get_verbose", (RBool "verbose", []), -1, [],
637 This returns the verbose messages flag.");
639 ("is_ready", (RBool "ready", []), -1, [],
640 [InitNone, Always, TestOutputTrue (
642 "is ready to accept commands",
644 This returns true iff this handle is ready to accept commands
645 (in the C<READY> state).
647 For more information on states, see L<guestfs(3)>.");
649 ("is_config", (RBool "config", []), -1, [],
650 [InitNone, Always, TestOutputFalse (
652 "is in configuration state",
654 This returns true iff this handle is being configured
655 (in the C<CONFIG> state).
657 For more information on states, see L<guestfs(3)>.");
659 ("is_launching", (RBool "launching", []), -1, [],
660 [InitNone, Always, TestOutputFalse (
661 [["is_launching"]])],
662 "is launching subprocess",
664 This returns true iff this handle is launching the subprocess
665 (in the C<LAUNCHING> state).
667 For more information on states, see L<guestfs(3)>.");
669 ("is_busy", (RBool "busy", []), -1, [],
670 [InitNone, Always, TestOutputFalse (
672 "is busy processing a command",
674 This returns true iff this handle is busy processing a command
675 (in the C<BUSY> state).
677 For more information on states, see L<guestfs(3)>.");
679 ("get_state", (RInt "state", []), -1, [],
681 "get the current state",
683 This returns the current state as an opaque integer. This is
684 only useful for printing debug and internal error messages.
686 For more information on states, see L<guestfs(3)>.");
688 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
689 [InitNone, Always, TestOutputInt (
690 [["set_memsize"; "500"];
691 ["get_memsize"]], 500)],
692 "set memory allocated to the qemu subprocess",
694 This sets the memory size in megabytes allocated to the
695 qemu subprocess. This only has any effect if called before
698 You can also change this by setting the environment
699 variable C<LIBGUESTFS_MEMSIZE> before the handle is
702 For more information on the architecture of libguestfs,
703 see L<guestfs(3)>.");
705 ("get_memsize", (RInt "memsize", []), -1, [],
706 [InitNone, Always, TestOutputIntOp (
707 [["get_memsize"]], ">=", 256)],
708 "get memory allocated to the qemu subprocess",
710 This gets the memory size in megabytes allocated to the
713 If C<guestfs_set_memsize> was not called
714 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
715 then this returns the compiled-in default value for memsize.
717 For more information on the architecture of libguestfs,
718 see L<guestfs(3)>.");
720 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
721 [InitNone, Always, TestOutputIntOp (
722 [["get_pid"]], ">=", 1)],
723 "get PID of qemu subprocess",
725 Return the process ID of the qemu subprocess. If there is no
726 qemu subprocess, then this will return an error.
728 This is an internal call used for debugging and testing.");
730 ("version", (RStruct ("version", "version"), []), -1, [],
731 [InitNone, Always, TestOutputStruct (
732 [["version"]], [CompareWithInt ("major", 1)])],
733 "get the library version number",
735 Return the libguestfs version number that the program is linked
738 Note that because of dynamic linking this is not necessarily
739 the version of libguestfs that you compiled against. You can
740 compile the program, and then at runtime dynamically link
741 against a completely different C<libguestfs.so> library.
743 This call was added in version C<1.0.58>. In previous
744 versions of libguestfs there was no way to get the version
745 number. From C code you can use ELF weak linking tricks to find out if
746 this symbol exists (if it doesn't, then it's an earlier version).
748 The call returns a structure with four elements. The first
749 three (C<major>, C<minor> and C<release>) are numbers and
750 correspond to the usual version triplet. The fourth element
751 (C<extra>) is a string and is normally empty, but may be
752 used for distro-specific information.
754 To construct the original version string:
755 C<$major.$minor.$release$extra>
757 I<Note:> Don't use this call to test for availability
758 of features. Distro backports makes this unreliable.");
760 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
761 [InitNone, Always, TestOutputTrue (
762 [["set_selinux"; "true"];
764 "set SELinux enabled or disabled at appliance boot",
766 This sets the selinux flag that is passed to the appliance
767 at boot time. The default is C<selinux=0> (disabled).
769 Note that if SELinux is enabled, it is always in
770 Permissive mode (C<enforcing=0>).
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
775 ("get_selinux", (RBool "selinux", []), -1, [],
777 "get SELinux enabled flag",
779 This returns the current setting of the selinux flag which
780 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
782 For more information on the architecture of libguestfs,
783 see L<guestfs(3)>.");
785 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
786 [InitNone, Always, TestOutputFalse (
787 [["set_trace"; "false"];
789 "enable or disable command traces",
791 If the command trace flag is set to 1, then commands are
792 printed on stdout before they are executed in a format
793 which is very similar to the one used by guestfish. In
794 other words, you can run a program with this enabled, and
795 you will get out a script which you can feed to guestfish
796 to perform the same set of actions.
798 If you want to trace C API calls into libguestfs (and
799 other libraries) then possibly a better way is to use
800 the external ltrace(1) command.
802 Command traces are disabled unless the environment variable
803 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
805 ("get_trace", (RBool "trace", []), -1, [],
807 "get command trace enabled flag",
809 Return the command trace flag.");
813 (* daemon_functions are any functions which cause some action
814 * to take place in the daemon.
817 let daemon_functions = [
818 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
819 [InitEmpty, Always, TestOutput (
820 [["sfdiskM"; "/dev/sda"; ","];
821 ["mkfs"; "ext2"; "/dev/sda1"];
822 ["mount"; "/dev/sda1"; "/"];
823 ["write_file"; "/new"; "new file contents"; "0"];
824 ["cat"; "/new"]], "new file contents")],
825 "mount a guest disk at a position in the filesystem",
827 Mount a guest disk at a position in the filesystem. Block devices
828 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
829 the guest. If those block devices contain partitions, they will have
830 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
833 The rules are the same as for L<mount(2)>: A filesystem must
834 first be mounted on C</> before others can be mounted. Other
835 filesystems can only be mounted on directories which already
838 The mounted filesystem is writable, if we have sufficient permissions
839 on the underlying device.
841 The filesystem options C<sync> and C<noatime> are set with this
842 call, in order to improve reliability.");
844 ("sync", (RErr, []), 2, [],
845 [ InitEmpty, Always, TestRun [["sync"]]],
846 "sync disks, writes are flushed through to the disk image",
848 This syncs the disk, so that any writes are flushed through to the
849 underlying disk image.
851 You should always call this if you have modified a disk image, before
852 closing the handle.");
854 ("touch", (RErr, [Pathname "path"]), 3, [],
855 [InitBasicFS, Always, TestOutputTrue (
857 ["exists"; "/new"]])],
858 "update file timestamps or create a new file",
860 Touch acts like the L<touch(1)> command. It can be used to
861 update the timestamps on a file, or, if the file does not exist,
862 to create a new zero-length file.");
864 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
865 [InitISOFS, Always, TestOutput (
866 [["cat"; "/known-2"]], "abcdef\n")],
867 "list the contents of a file",
869 Return the contents of the file named C<path>.
871 Note that this function cannot correctly handle binary files
872 (specifically, files containing C<\\0> character which is treated
873 as end of string). For those you need to use the C<guestfs_read_file>
874 or C<guestfs_download> functions which have a more complex interface.");
876 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
877 [], (* XXX Tricky to test because it depends on the exact format
878 * of the 'ls -l' command, which changes between F10 and F11.
880 "list the files in a directory (long format)",
882 List the files in C<directory> (relative to the root directory,
883 there is no cwd) in the format of 'ls -la'.
885 This command is mostly useful for interactive sessions. It
886 is I<not> intended that you try to parse the output string.");
888 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
889 [InitBasicFS, Always, TestOutputList (
892 ["touch"; "/newest"];
893 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
894 "list the files in a directory",
896 List the files in C<directory> (relative to the root directory,
897 there is no cwd). The '.' and '..' entries are not returned, but
898 hidden files are shown.
900 This command is mostly useful for interactive sessions. Programs
901 should probably use C<guestfs_readdir> instead.");
903 ("list_devices", (RStringList "devices", []), 7, [],
904 [InitEmpty, Always, TestOutputListOfDevices (
905 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
906 "list the block devices",
908 List all the block devices.
910 The full block device names are returned, eg. C</dev/sda>");
912 ("list_partitions", (RStringList "partitions", []), 8, [],
913 [InitBasicFS, Always, TestOutputListOfDevices (
914 [["list_partitions"]], ["/dev/sda1"]);
915 InitEmpty, Always, TestOutputListOfDevices (
916 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
917 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
918 "list the partitions",
920 List all the partitions detected on all block devices.
922 The full partition device names are returned, eg. C</dev/sda1>
924 This does not return logical volumes. For that you will need to
925 call C<guestfs_lvs>.");
927 ("pvs", (RStringList "physvols", []), 9, [],
928 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
929 [["pvs"]], ["/dev/sda1"]);
930 InitEmpty, Always, TestOutputListOfDevices (
931 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
932 ["pvcreate"; "/dev/sda1"];
933 ["pvcreate"; "/dev/sda2"];
934 ["pvcreate"; "/dev/sda3"];
935 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
936 "list the LVM physical volumes (PVs)",
938 List all the physical volumes detected. This is the equivalent
939 of the L<pvs(8)> command.
941 This returns a list of just the device names that contain
942 PVs (eg. C</dev/sda2>).
944 See also C<guestfs_pvs_full>.");
946 ("vgs", (RStringList "volgroups", []), 10, [],
947 [InitBasicFSonLVM, Always, TestOutputList (
949 InitEmpty, Always, TestOutputList (
950 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
951 ["pvcreate"; "/dev/sda1"];
952 ["pvcreate"; "/dev/sda2"];
953 ["pvcreate"; "/dev/sda3"];
954 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
955 ["vgcreate"; "VG2"; "/dev/sda3"];
956 ["vgs"]], ["VG1"; "VG2"])],
957 "list the LVM volume groups (VGs)",
959 List all the volumes groups detected. This is the equivalent
960 of the L<vgs(8)> command.
962 This returns a list of just the volume group names that were
963 detected (eg. C<VolGroup00>).
965 See also C<guestfs_vgs_full>.");
967 ("lvs", (RStringList "logvols", []), 11, [],
968 [InitBasicFSonLVM, Always, TestOutputList (
969 [["lvs"]], ["/dev/VG/LV"]);
970 InitEmpty, Always, TestOutputList (
971 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
972 ["pvcreate"; "/dev/sda1"];
973 ["pvcreate"; "/dev/sda2"];
974 ["pvcreate"; "/dev/sda3"];
975 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
976 ["vgcreate"; "VG2"; "/dev/sda3"];
977 ["lvcreate"; "LV1"; "VG1"; "50"];
978 ["lvcreate"; "LV2"; "VG1"; "50"];
979 ["lvcreate"; "LV3"; "VG2"; "50"];
980 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
981 "list the LVM logical volumes (LVs)",
983 List all the logical volumes detected. This is the equivalent
984 of the L<lvs(8)> command.
986 This returns a list of the logical volume device names
987 (eg. C</dev/VolGroup00/LogVol00>).
989 See also C<guestfs_lvs_full>.");
991 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
992 [], (* XXX how to test? *)
993 "list the LVM physical volumes (PVs)",
995 List all the physical volumes detected. This is the equivalent
996 of the L<pvs(8)> command. The \"full\" version includes all fields.");
998 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
999 [], (* XXX how to test? *)
1000 "list the LVM volume groups (VGs)",
1002 List all the volumes groups detected. This is the equivalent
1003 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1005 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1006 [], (* XXX how to test? *)
1007 "list the LVM logical volumes (LVs)",
1009 List all the logical volumes detected. This is the equivalent
1010 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1012 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1013 [InitISOFS, Always, TestOutputList (
1014 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1015 InitISOFS, Always, TestOutputList (
1016 [["read_lines"; "/empty"]], [])],
1017 "read file as lines",
1019 Return the contents of the file named C<path>.
1021 The file contents are returned as a list of lines. Trailing
1022 C<LF> and C<CRLF> character sequences are I<not> returned.
1024 Note that this function cannot correctly handle binary files
1025 (specifically, files containing C<\\0> character which is treated
1026 as end of line). For those you need to use the C<guestfs_read_file>
1027 function which has a more complex interface.");
1029 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1030 [], (* XXX Augeas code needs tests. *)
1031 "create a new Augeas handle",
1033 Create a new Augeas handle for editing configuration files.
1034 If there was any previous Augeas handle associated with this
1035 guestfs session, then it is closed.
1037 You must call this before using any other C<guestfs_aug_*>
1040 C<root> is the filesystem root. C<root> must not be NULL,
1043 The flags are the same as the flags defined in
1044 E<lt>augeas.hE<gt>, the logical I<or> of the following
1049 =item C<AUG_SAVE_BACKUP> = 1
1051 Keep the original file with a C<.augsave> extension.
1053 =item C<AUG_SAVE_NEWFILE> = 2
1055 Save changes into a file with extension C<.augnew>, and
1056 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1058 =item C<AUG_TYPE_CHECK> = 4
1060 Typecheck lenses (can be expensive).
1062 =item C<AUG_NO_STDINC> = 8
1064 Do not use standard load path for modules.
1066 =item C<AUG_SAVE_NOOP> = 16
1068 Make save a no-op, just record what would have been changed.
1070 =item C<AUG_NO_LOAD> = 32
1072 Do not load the tree in C<guestfs_aug_init>.
1076 To close the handle, you can call C<guestfs_aug_close>.
1078 To find out more about Augeas, see L<http://augeas.net/>.");
1080 ("aug_close", (RErr, []), 26, [],
1081 [], (* XXX Augeas code needs tests. *)
1082 "close the current Augeas handle",
1084 Close the current Augeas handle and free up any resources
1085 used by it. After calling this, you have to call
1086 C<guestfs_aug_init> again before you can use any other
1087 Augeas functions.");
1089 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1090 [], (* XXX Augeas code needs tests. *)
1091 "define an Augeas variable",
1093 Defines an Augeas variable C<name> whose value is the result
1094 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1097 On success this returns the number of nodes in C<expr>, or
1098 C<0> if C<expr> evaluates to something which is not a nodeset.");
1100 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1101 [], (* XXX Augeas code needs tests. *)
1102 "define an Augeas node",
1104 Defines a variable C<name> whose value is the result of
1107 If C<expr> evaluates to an empty nodeset, a node is created,
1108 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1109 C<name> will be the nodeset containing that single node.
1111 On success this returns a pair containing the
1112 number of nodes in the nodeset, and a boolean flag
1113 if a node was created.");
1115 ("aug_get", (RString "val", [String "augpath"]), 19, [],
1116 [], (* XXX Augeas code needs tests. *)
1117 "look up the value of an Augeas path",
1119 Look up the value associated with C<path>. If C<path>
1120 matches exactly one node, the C<value> is returned.");
1122 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1123 [], (* XXX Augeas code needs tests. *)
1124 "set Augeas path to value",
1126 Set the value associated with C<path> to C<value>.");
1128 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1129 [], (* XXX Augeas code needs tests. *)
1130 "insert a sibling Augeas node",
1132 Create a new sibling C<label> for C<path>, inserting it into
1133 the tree before or after C<path> (depending on the boolean
1136 C<path> must match exactly one existing node in the tree, and
1137 C<label> must be a label, ie. not contain C</>, C<*> or end
1138 with a bracketed index C<[N]>.");
1140 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1141 [], (* XXX Augeas code needs tests. *)
1142 "remove an Augeas path",
1144 Remove C<path> and all of its children.
1146 On success this returns the number of entries which were removed.");
1148 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1149 [], (* XXX Augeas code needs tests. *)
1152 Move the node C<src> to C<dest>. C<src> must match exactly
1153 one node. C<dest> is overwritten if it exists.");
1155 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1156 [], (* XXX Augeas code needs tests. *)
1157 "return Augeas nodes which match augpath",
1159 Returns a list of paths which match the path expression C<path>.
1160 The returned paths are sufficiently qualified so that they match
1161 exactly one node in the current tree.");
1163 ("aug_save", (RErr, []), 25, [],
1164 [], (* XXX Augeas code needs tests. *)
1165 "write all pending Augeas changes to disk",
1167 This writes all pending changes to disk.
1169 The flags which were passed to C<guestfs_aug_init> affect exactly
1170 how files are saved.");
1172 ("aug_load", (RErr, []), 27, [],
1173 [], (* XXX Augeas code needs tests. *)
1174 "load files into the tree",
1176 Load files into the tree.
1178 See C<aug_load> in the Augeas documentation for the full gory
1181 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1182 [], (* XXX Augeas code needs tests. *)
1183 "list Augeas nodes under augpath",
1185 This is just a shortcut for listing C<guestfs_aug_match>
1186 C<path/*> and sorting the resulting nodes into alphabetical order.");
1188 ("rm", (RErr, [Pathname "path"]), 29, [],
1189 [InitBasicFS, Always, TestRun
1192 InitBasicFS, Always, TestLastFail
1194 InitBasicFS, Always, TestLastFail
1199 Remove the single file C<path>.");
1201 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1202 [InitBasicFS, Always, TestRun
1205 InitBasicFS, Always, TestLastFail
1206 [["rmdir"; "/new"]];
1207 InitBasicFS, Always, TestLastFail
1209 ["rmdir"; "/new"]]],
1210 "remove a directory",
1212 Remove the single directory C<path>.");
1214 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1215 [InitBasicFS, Always, TestOutputFalse
1217 ["mkdir"; "/new/foo"];
1218 ["touch"; "/new/foo/bar"];
1220 ["exists"; "/new"]]],
1221 "remove a file or directory recursively",
1223 Remove the file or directory C<path>, recursively removing the
1224 contents if its a directory. This is like the C<rm -rf> shell
1227 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1228 [InitBasicFS, Always, TestOutputTrue
1230 ["is_dir"; "/new"]];
1231 InitBasicFS, Always, TestLastFail
1232 [["mkdir"; "/new/foo/bar"]]],
1233 "create a directory",
1235 Create a directory named C<path>.");
1237 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1238 [InitBasicFS, Always, TestOutputTrue
1239 [["mkdir_p"; "/new/foo/bar"];
1240 ["is_dir"; "/new/foo/bar"]];
1241 InitBasicFS, Always, TestOutputTrue
1242 [["mkdir_p"; "/new/foo/bar"];
1243 ["is_dir"; "/new/foo"]];
1244 InitBasicFS, Always, TestOutputTrue
1245 [["mkdir_p"; "/new/foo/bar"];
1246 ["is_dir"; "/new"]];
1247 (* Regression tests for RHBZ#503133: *)
1248 InitBasicFS, Always, TestRun
1250 ["mkdir_p"; "/new"]];
1251 InitBasicFS, Always, TestLastFail
1253 ["mkdir_p"; "/new"]]],
1254 "create a directory and parents",
1256 Create a directory named C<path>, creating any parent directories
1257 as necessary. This is like the C<mkdir -p> shell command.");
1259 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1260 [], (* XXX Need stat command to test *)
1263 Change the mode (permissions) of C<path> to C<mode>. Only
1264 numeric modes are supported.");
1266 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1267 [], (* XXX Need stat command to test *)
1268 "change file owner and group",
1270 Change the file owner to C<owner> and group to C<group>.
1272 Only numeric uid and gid are supported. If you want to use
1273 names, you will need to locate and parse the password file
1274 yourself (Augeas support makes this relatively easy).");
1276 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1277 [InitISOFS, Always, TestOutputTrue (
1278 [["exists"; "/empty"]]);
1279 InitISOFS, Always, TestOutputTrue (
1280 [["exists"; "/directory"]])],
1281 "test if file or directory exists",
1283 This returns C<true> if and only if there is a file, directory
1284 (or anything) with the given C<path> name.
1286 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1288 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1289 [InitISOFS, Always, TestOutputTrue (
1290 [["is_file"; "/known-1"]]);
1291 InitISOFS, Always, TestOutputFalse (
1292 [["is_file"; "/directory"]])],
1293 "test if file exists",
1295 This returns C<true> if and only if there is a file
1296 with the given C<path> name. Note that it returns false for
1297 other objects like directories.
1299 See also C<guestfs_stat>.");
1301 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1302 [InitISOFS, Always, TestOutputFalse (
1303 [["is_dir"; "/known-3"]]);
1304 InitISOFS, Always, TestOutputTrue (
1305 [["is_dir"; "/directory"]])],
1306 "test if file exists",
1308 This returns C<true> if and only if there is a directory
1309 with the given C<path> name. Note that it returns false for
1310 other objects like files.
1312 See also C<guestfs_stat>.");
1314 ("pvcreate", (RErr, [Device "device"]), 39, [],
1315 [InitEmpty, Always, TestOutputListOfDevices (
1316 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1317 ["pvcreate"; "/dev/sda1"];
1318 ["pvcreate"; "/dev/sda2"];
1319 ["pvcreate"; "/dev/sda3"];
1320 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1321 "create an LVM physical volume",
1323 This creates an LVM physical volume on the named C<device>,
1324 where C<device> should usually be a partition name such
1327 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1328 [InitEmpty, Always, TestOutputList (
1329 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1330 ["pvcreate"; "/dev/sda1"];
1331 ["pvcreate"; "/dev/sda2"];
1332 ["pvcreate"; "/dev/sda3"];
1333 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1334 ["vgcreate"; "VG2"; "/dev/sda3"];
1335 ["vgs"]], ["VG1"; "VG2"])],
1336 "create an LVM volume group",
1338 This creates an LVM volume group called C<volgroup>
1339 from the non-empty list of physical volumes C<physvols>.");
1341 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1342 [InitEmpty, Always, TestOutputList (
1343 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1344 ["pvcreate"; "/dev/sda1"];
1345 ["pvcreate"; "/dev/sda2"];
1346 ["pvcreate"; "/dev/sda3"];
1347 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1348 ["vgcreate"; "VG2"; "/dev/sda3"];
1349 ["lvcreate"; "LV1"; "VG1"; "50"];
1350 ["lvcreate"; "LV2"; "VG1"; "50"];
1351 ["lvcreate"; "LV3"; "VG2"; "50"];
1352 ["lvcreate"; "LV4"; "VG2"; "50"];
1353 ["lvcreate"; "LV5"; "VG2"; "50"];
1355 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1356 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1357 "create an LVM volume group",
1359 This creates an LVM volume group called C<logvol>
1360 on the volume group C<volgroup>, with C<size> megabytes.");
1362 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1363 [InitEmpty, Always, TestOutput (
1364 [["sfdiskM"; "/dev/sda"; ","];
1365 ["mkfs"; "ext2"; "/dev/sda1"];
1366 ["mount"; "/dev/sda1"; "/"];
1367 ["write_file"; "/new"; "new file contents"; "0"];
1368 ["cat"; "/new"]], "new file contents")],
1369 "make a filesystem",
1371 This creates a filesystem on C<device> (usually a partition
1372 or LVM logical volume). The filesystem type is C<fstype>, for
1375 ("sfdisk", (RErr, [Device "device";
1376 Int "cyls"; Int "heads"; Int "sectors";
1377 StringList "lines"]), 43, [DangerWillRobinson],
1379 "create partitions on a block device",
1381 This is a direct interface to the L<sfdisk(8)> program for creating
1382 partitions on block devices.
1384 C<device> should be a block device, for example C</dev/sda>.
1386 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1387 and sectors on the device, which are passed directly to sfdisk as
1388 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1389 of these, then the corresponding parameter is omitted. Usually for
1390 'large' disks, you can just pass C<0> for these, but for small
1391 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1392 out the right geometry and you will need to tell it.
1394 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1395 information refer to the L<sfdisk(8)> manpage.
1397 To create a single partition occupying the whole disk, you would
1398 pass C<lines> as a single element list, when the single element being
1399 the string C<,> (comma).
1401 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1403 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1404 [InitBasicFS, Always, TestOutput (
1405 [["write_file"; "/new"; "new file contents"; "0"];
1406 ["cat"; "/new"]], "new file contents");
1407 InitBasicFS, Always, TestOutput (
1408 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1409 ["cat"; "/new"]], "\nnew file contents\n");
1410 InitBasicFS, Always, TestOutput (
1411 [["write_file"; "/new"; "\n\n"; "0"];
1412 ["cat"; "/new"]], "\n\n");
1413 InitBasicFS, Always, TestOutput (
1414 [["write_file"; "/new"; ""; "0"];
1415 ["cat"; "/new"]], "");
1416 InitBasicFS, Always, TestOutput (
1417 [["write_file"; "/new"; "\n\n\n"; "0"];
1418 ["cat"; "/new"]], "\n\n\n");
1419 InitBasicFS, Always, TestOutput (
1420 [["write_file"; "/new"; "\n"; "0"];
1421 ["cat"; "/new"]], "\n")],
1424 This call creates a file called C<path>. The contents of the
1425 file is the string C<content> (which can contain any 8 bit data),
1426 with length C<size>.
1428 As a special case, if C<size> is C<0>
1429 then the length is calculated using C<strlen> (so in this case
1430 the content cannot contain embedded ASCII NULs).
1432 I<NB.> Owing to a bug, writing content containing ASCII NUL
1433 characters does I<not> work, even if the length is specified.
1434 We hope to resolve this bug in a future version. In the meantime
1435 use C<guestfs_upload>.");
1437 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1438 [InitEmpty, Always, TestOutputListOfDevices (
1439 [["sfdiskM"; "/dev/sda"; ","];
1440 ["mkfs"; "ext2"; "/dev/sda1"];
1441 ["mount"; "/dev/sda1"; "/"];
1442 ["mounts"]], ["/dev/sda1"]);
1443 InitEmpty, Always, TestOutputList (
1444 [["sfdiskM"; "/dev/sda"; ","];
1445 ["mkfs"; "ext2"; "/dev/sda1"];
1446 ["mount"; "/dev/sda1"; "/"];
1449 "unmount a filesystem",
1451 This unmounts the given filesystem. The filesystem may be
1452 specified either by its mountpoint (path) or the device which
1453 contains the filesystem.");
1455 ("mounts", (RStringList "devices", []), 46, [],
1456 [InitBasicFS, Always, TestOutputListOfDevices (
1457 [["mounts"]], ["/dev/sda1"])],
1458 "show mounted filesystems",
1460 This returns the list of currently mounted filesystems. It returns
1461 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1463 Some internal mounts are not shown.
1465 See also: C<guestfs_mountpoints>");
1467 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1468 [InitBasicFS, Always, TestOutputList (
1471 (* check that umount_all can unmount nested mounts correctly: *)
1472 InitEmpty, Always, TestOutputList (
1473 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1474 ["mkfs"; "ext2"; "/dev/sda1"];
1475 ["mkfs"; "ext2"; "/dev/sda2"];
1476 ["mkfs"; "ext2"; "/dev/sda3"];
1477 ["mount"; "/dev/sda1"; "/"];
1479 ["mount"; "/dev/sda2"; "/mp1"];
1480 ["mkdir"; "/mp1/mp2"];
1481 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1482 ["mkdir"; "/mp1/mp2/mp3"];
1485 "unmount all filesystems",
1487 This unmounts all mounted filesystems.
1489 Some internal mounts are not unmounted by this call.");
1491 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1493 "remove all LVM LVs, VGs and PVs",
1495 This command removes all LVM logical volumes, volume groups
1496 and physical volumes.");
1498 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1499 [InitISOFS, Always, TestOutput (
1500 [["file"; "/empty"]], "empty");
1501 InitISOFS, Always, TestOutput (
1502 [["file"; "/known-1"]], "ASCII text");
1503 InitISOFS, Always, TestLastFail (
1504 [["file"; "/notexists"]])],
1505 "determine file type",
1507 This call uses the standard L<file(1)> command to determine
1508 the type or contents of the file. This also works on devices,
1509 for example to find out whether a partition contains a filesystem.
1511 This call will also transparently look inside various types
1514 The exact command which runs is C<file -zbsL path>. Note in
1515 particular that the filename is not prepended to the output
1516 (the C<-b> option).");
1518 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1519 [InitBasicFS, Always, TestOutput (
1520 [["upload"; "test-command"; "/test-command"];
1521 ["chmod"; "0o755"; "/test-command"];
1522 ["command"; "/test-command 1"]], "Result1");
1523 InitBasicFS, Always, TestOutput (
1524 [["upload"; "test-command"; "/test-command"];
1525 ["chmod"; "0o755"; "/test-command"];
1526 ["command"; "/test-command 2"]], "Result2\n");
1527 InitBasicFS, Always, TestOutput (
1528 [["upload"; "test-command"; "/test-command"];
1529 ["chmod"; "0o755"; "/test-command"];
1530 ["command"; "/test-command 3"]], "\nResult3");
1531 InitBasicFS, Always, TestOutput (
1532 [["upload"; "test-command"; "/test-command"];
1533 ["chmod"; "0o755"; "/test-command"];
1534 ["command"; "/test-command 4"]], "\nResult4\n");
1535 InitBasicFS, Always, TestOutput (
1536 [["upload"; "test-command"; "/test-command"];
1537 ["chmod"; "0o755"; "/test-command"];
1538 ["command"; "/test-command 5"]], "\nResult5\n\n");
1539 InitBasicFS, Always, TestOutput (
1540 [["upload"; "test-command"; "/test-command"];
1541 ["chmod"; "0o755"; "/test-command"];
1542 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1543 InitBasicFS, Always, TestOutput (
1544 [["upload"; "test-command"; "/test-command"];
1545 ["chmod"; "0o755"; "/test-command"];
1546 ["command"; "/test-command 7"]], "");
1547 InitBasicFS, Always, TestOutput (
1548 [["upload"; "test-command"; "/test-command"];
1549 ["chmod"; "0o755"; "/test-command"];
1550 ["command"; "/test-command 8"]], "\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["upload"; "test-command"; "/test-command"];
1553 ["chmod"; "0o755"; "/test-command"];
1554 ["command"; "/test-command 9"]], "\n\n");
1555 InitBasicFS, Always, TestOutput (
1556 [["upload"; "test-command"; "/test-command"];
1557 ["chmod"; "0o755"; "/test-command"];
1558 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1559 InitBasicFS, Always, TestOutput (
1560 [["upload"; "test-command"; "/test-command"];
1561 ["chmod"; "0o755"; "/test-command"];
1562 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1563 InitBasicFS, Always, TestLastFail (
1564 [["upload"; "test-command"; "/test-command"];
1565 ["chmod"; "0o755"; "/test-command"];
1566 ["command"; "/test-command"]])],
1567 "run a command from the guest filesystem",
1569 This call runs a command from the guest filesystem. The
1570 filesystem must be mounted, and must contain a compatible
1571 operating system (ie. something Linux, with the same
1572 or compatible processor architecture).
1574 The single parameter is an argv-style list of arguments.
1575 The first element is the name of the program to run.
1576 Subsequent elements are parameters. The list must be
1577 non-empty (ie. must contain a program name). Note that
1578 the command runs directly, and is I<not> invoked via
1579 the shell (see C<guestfs_sh>).
1581 The return value is anything printed to I<stdout> by
1584 If the command returns a non-zero exit status, then
1585 this function returns an error message. The error message
1586 string is the content of I<stderr> from the command.
1588 The C<$PATH> environment variable will contain at least
1589 C</usr/bin> and C</bin>. If you require a program from
1590 another location, you should provide the full path in the
1593 Shared libraries and data files required by the program
1594 must be available on filesystems which are mounted in the
1595 correct places. It is the caller's responsibility to ensure
1596 all filesystems that are needed are mounted at the right
1599 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1600 [InitBasicFS, Always, TestOutputList (
1601 [["upload"; "test-command"; "/test-command"];
1602 ["chmod"; "0o755"; "/test-command"];
1603 ["command_lines"; "/test-command 1"]], ["Result1"]);
1604 InitBasicFS, Always, TestOutputList (
1605 [["upload"; "test-command"; "/test-command"];
1606 ["chmod"; "0o755"; "/test-command"];
1607 ["command_lines"; "/test-command 2"]], ["Result2"]);
1608 InitBasicFS, Always, TestOutputList (
1609 [["upload"; "test-command"; "/test-command"];
1610 ["chmod"; "0o755"; "/test-command"];
1611 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1612 InitBasicFS, Always, TestOutputList (
1613 [["upload"; "test-command"; "/test-command"];
1614 ["chmod"; "0o755"; "/test-command"];
1615 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1616 InitBasicFS, Always, TestOutputList (
1617 [["upload"; "test-command"; "/test-command"];
1618 ["chmod"; "0o755"; "/test-command"];
1619 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1620 InitBasicFS, Always, TestOutputList (
1621 [["upload"; "test-command"; "/test-command"];
1622 ["chmod"; "0o755"; "/test-command"];
1623 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1624 InitBasicFS, Always, TestOutputList (
1625 [["upload"; "test-command"; "/test-command"];
1626 ["chmod"; "0o755"; "/test-command"];
1627 ["command_lines"; "/test-command 7"]], []);
1628 InitBasicFS, Always, TestOutputList (
1629 [["upload"; "test-command"; "/test-command"];
1630 ["chmod"; "0o755"; "/test-command"];
1631 ["command_lines"; "/test-command 8"]], [""]);
1632 InitBasicFS, Always, TestOutputList (
1633 [["upload"; "test-command"; "/test-command"];
1634 ["chmod"; "0o755"; "/test-command"];
1635 ["command_lines"; "/test-command 9"]], ["";""]);
1636 InitBasicFS, Always, TestOutputList (
1637 [["upload"; "test-command"; "/test-command"];
1638 ["chmod"; "0o755"; "/test-command"];
1639 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1640 InitBasicFS, Always, TestOutputList (
1641 [["upload"; "test-command"; "/test-command"];
1642 ["chmod"; "0o755"; "/test-command"];
1643 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1644 "run a command, returning lines",
1646 This is the same as C<guestfs_command>, but splits the
1647 result into a list of lines.
1649 See also: C<guestfs_sh_lines>");
1651 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1652 [InitISOFS, Always, TestOutputStruct (
1653 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1654 "get file information",
1656 Returns file information for the given C<path>.
1658 This is the same as the C<stat(2)> system call.");
1660 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1661 [InitISOFS, Always, TestOutputStruct (
1662 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1663 "get file information for a symbolic link",
1665 Returns file information for the given C<path>.
1667 This is the same as C<guestfs_stat> except that if C<path>
1668 is a symbolic link, then the link is stat-ed, not the file it
1671 This is the same as the C<lstat(2)> system call.");
1673 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1674 [InitISOFS, Always, TestOutputStruct (
1675 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1676 "get file system statistics",
1678 Returns file system statistics for any mounted file system.
1679 C<path> should be a file or directory in the mounted file system
1680 (typically it is the mount point itself, but it doesn't need to be).
1682 This is the same as the C<statvfs(2)> system call.");
1684 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1686 "get ext2/ext3/ext4 superblock details",
1688 This returns the contents of the ext2, ext3 or ext4 filesystem
1689 superblock on C<device>.
1691 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1692 manpage for more details. The list of fields returned isn't
1693 clearly defined, and depends on both the version of C<tune2fs>
1694 that libguestfs was built against, and the filesystem itself.");
1696 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1697 [InitEmpty, Always, TestOutputTrue (
1698 [["blockdev_setro"; "/dev/sda"];
1699 ["blockdev_getro"; "/dev/sda"]])],
1700 "set block device to read-only",
1702 Sets the block device named C<device> to read-only.
1704 This uses the L<blockdev(8)> command.");
1706 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1707 [InitEmpty, Always, TestOutputFalse (
1708 [["blockdev_setrw"; "/dev/sda"];
1709 ["blockdev_getro"; "/dev/sda"]])],
1710 "set block device to read-write",
1712 Sets the block device named C<device> to read-write.
1714 This uses the L<blockdev(8)> command.");
1716 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1717 [InitEmpty, Always, TestOutputTrue (
1718 [["blockdev_setro"; "/dev/sda"];
1719 ["blockdev_getro"; "/dev/sda"]])],
1720 "is block device set to read-only",
1722 Returns a boolean indicating if the block device is read-only
1723 (true if read-only, false if not).
1725 This uses the L<blockdev(8)> command.");
1727 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1728 [InitEmpty, Always, TestOutputInt (
1729 [["blockdev_getss"; "/dev/sda"]], 512)],
1730 "get sectorsize of block device",
1732 This returns the size of sectors on a block device.
1733 Usually 512, but can be larger for modern devices.
1735 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1738 This uses the L<blockdev(8)> command.");
1740 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1741 [InitEmpty, Always, TestOutputInt (
1742 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1743 "get blocksize of block device",
1745 This returns the block size of a device.
1747 (Note this is different from both I<size in blocks> and
1748 I<filesystem block size>).
1750 This uses the L<blockdev(8)> command.");
1752 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1754 "set blocksize of block device",
1756 This sets the block size of a device.
1758 (Note this is different from both I<size in blocks> and
1759 I<filesystem block size>).
1761 This uses the L<blockdev(8)> command.");
1763 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1764 [InitEmpty, Always, TestOutputInt (
1765 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1766 "get total size of device in 512-byte sectors",
1768 This returns the size of the device in units of 512-byte sectors
1769 (even if the sectorsize isn't 512 bytes ... weird).
1771 See also C<guestfs_blockdev_getss> for the real sector size of
1772 the device, and C<guestfs_blockdev_getsize64> for the more
1773 useful I<size in bytes>.
1775 This uses the L<blockdev(8)> command.");
1777 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1778 [InitEmpty, Always, TestOutputInt (
1779 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1780 "get total size of device in bytes",
1782 This returns the size of the device in bytes.
1784 See also C<guestfs_blockdev_getsz>.
1786 This uses the L<blockdev(8)> command.");
1788 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1789 [InitEmpty, Always, TestRun
1790 [["blockdev_flushbufs"; "/dev/sda"]]],
1791 "flush device buffers",
1793 This tells the kernel to flush internal buffers associated
1796 This uses the L<blockdev(8)> command.");
1798 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1799 [InitEmpty, Always, TestRun
1800 [["blockdev_rereadpt"; "/dev/sda"]]],
1801 "reread partition table",
1803 Reread the partition table on C<device>.
1805 This uses the L<blockdev(8)> command.");
1807 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1808 [InitBasicFS, Always, TestOutput (
1809 (* Pick a file from cwd which isn't likely to change. *)
1810 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1811 ["checksum"; "md5"; "/COPYING.LIB"]],
1812 Digest.to_hex (Digest.file "COPYING.LIB"))],
1813 "upload a file from the local machine",
1815 Upload local file C<filename> to C<remotefilename> on the
1818 C<filename> can also be a named pipe.
1820 See also C<guestfs_download>.");
1822 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1823 [InitBasicFS, Always, TestOutput (
1824 (* Pick a file from cwd which isn't likely to change. *)
1825 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1826 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1827 ["upload"; "testdownload.tmp"; "/upload"];
1828 ["checksum"; "md5"; "/upload"]],
1829 Digest.to_hex (Digest.file "COPYING.LIB"))],
1830 "download a file to the local machine",
1832 Download file C<remotefilename> and save it as C<filename>
1833 on the local machine.
1835 C<filename> can also be a named pipe.
1837 See also C<guestfs_upload>, C<guestfs_cat>.");
1839 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1840 [InitISOFS, Always, TestOutput (
1841 [["checksum"; "crc"; "/known-3"]], "2891671662");
1842 InitISOFS, Always, TestLastFail (
1843 [["checksum"; "crc"; "/notexists"]]);
1844 InitISOFS, Always, TestOutput (
1845 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1846 InitISOFS, Always, TestOutput (
1847 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1848 InitISOFS, Always, TestOutput (
1849 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1850 InitISOFS, Always, TestOutput (
1851 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1852 InitISOFS, Always, TestOutput (
1853 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1854 InitISOFS, Always, TestOutput (
1855 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1856 "compute MD5, SHAx or CRC checksum of file",
1858 This call computes the MD5, SHAx or CRC checksum of the
1861 The type of checksum to compute is given by the C<csumtype>
1862 parameter which must have one of the following values:
1868 Compute the cyclic redundancy check (CRC) specified by POSIX
1869 for the C<cksum> command.
1873 Compute the MD5 hash (using the C<md5sum> program).
1877 Compute the SHA1 hash (using the C<sha1sum> program).
1881 Compute the SHA224 hash (using the C<sha224sum> program).
1885 Compute the SHA256 hash (using the C<sha256sum> program).
1889 Compute the SHA384 hash (using the C<sha384sum> program).
1893 Compute the SHA512 hash (using the C<sha512sum> program).
1897 The checksum is returned as a printable string.");
1899 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1900 [InitBasicFS, Always, TestOutput (
1901 [["tar_in"; "../images/helloworld.tar"; "/"];
1902 ["cat"; "/hello"]], "hello\n")],
1903 "unpack tarfile to directory",
1905 This command uploads and unpacks local file C<tarfile> (an
1906 I<uncompressed> tar file) into C<directory>.
1908 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1910 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1912 "pack directory into tarfile",
1914 This command packs the contents of C<directory> and downloads
1915 it to local file C<tarfile>.
1917 To download a compressed tarball, use C<guestfs_tgz_out>.");
1919 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1920 [InitBasicFS, Always, TestOutput (
1921 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1922 ["cat"; "/hello"]], "hello\n")],
1923 "unpack compressed tarball to directory",
1925 This command uploads and unpacks local file C<tarball> (a
1926 I<gzip compressed> tar file) into C<directory>.
1928 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1930 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1932 "pack directory into compressed tarball",
1934 This command packs the contents of C<directory> and downloads
1935 it to local file C<tarball>.
1937 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1939 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1940 [InitBasicFS, Always, TestLastFail (
1942 ["mount_ro"; "/dev/sda1"; "/"];
1943 ["touch"; "/new"]]);
1944 InitBasicFS, Always, TestOutput (
1945 [["write_file"; "/new"; "data"; "0"];
1947 ["mount_ro"; "/dev/sda1"; "/"];
1948 ["cat"; "/new"]], "data")],
1949 "mount a guest disk, read-only",
1951 This is the same as the C<guestfs_mount> command, but it
1952 mounts the filesystem with the read-only (I<-o ro>) flag.");
1954 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1956 "mount a guest disk with mount options",
1958 This is the same as the C<guestfs_mount> command, but it
1959 allows you to set the mount options as for the
1960 L<mount(8)> I<-o> flag.");
1962 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1964 "mount a guest disk with mount options and vfstype",
1966 This is the same as the C<guestfs_mount> command, but it
1967 allows you to set both the mount options and the vfstype
1968 as for the L<mount(8)> I<-o> and I<-t> flags.");
1970 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1972 "debugging and internals",
1974 The C<guestfs_debug> command exposes some internals of
1975 C<guestfsd> (the guestfs daemon) that runs inside the
1978 There is no comprehensive help for this command. You have
1979 to look at the file C<daemon/debug.c> in the libguestfs source
1980 to find out what you can do.");
1982 ("lvremove", (RErr, [Device "device"]), 77, [],
1983 [InitEmpty, Always, TestOutputList (
1984 [["sfdiskM"; "/dev/sda"; ","];
1985 ["pvcreate"; "/dev/sda1"];
1986 ["vgcreate"; "VG"; "/dev/sda1"];
1987 ["lvcreate"; "LV1"; "VG"; "50"];
1988 ["lvcreate"; "LV2"; "VG"; "50"];
1989 ["lvremove"; "/dev/VG/LV1"];
1990 ["lvs"]], ["/dev/VG/LV2"]);
1991 InitEmpty, Always, TestOutputList (
1992 [["sfdiskM"; "/dev/sda"; ","];
1993 ["pvcreate"; "/dev/sda1"];
1994 ["vgcreate"; "VG"; "/dev/sda1"];
1995 ["lvcreate"; "LV1"; "VG"; "50"];
1996 ["lvcreate"; "LV2"; "VG"; "50"];
1997 ["lvremove"; "/dev/VG"];
1999 InitEmpty, Always, TestOutputList (
2000 [["sfdiskM"; "/dev/sda"; ","];
2001 ["pvcreate"; "/dev/sda1"];
2002 ["vgcreate"; "VG"; "/dev/sda1"];
2003 ["lvcreate"; "LV1"; "VG"; "50"];
2004 ["lvcreate"; "LV2"; "VG"; "50"];
2005 ["lvremove"; "/dev/VG"];
2007 "remove an LVM logical volume",
2009 Remove an LVM logical volume C<device>, where C<device> is
2010 the path to the LV, such as C</dev/VG/LV>.
2012 You can also remove all LVs in a volume group by specifying
2013 the VG name, C</dev/VG>.");
2015 ("vgremove", (RErr, [String "vgname"]), 78, [],
2016 [InitEmpty, Always, TestOutputList (
2017 [["sfdiskM"; "/dev/sda"; ","];
2018 ["pvcreate"; "/dev/sda1"];
2019 ["vgcreate"; "VG"; "/dev/sda1"];
2020 ["lvcreate"; "LV1"; "VG"; "50"];
2021 ["lvcreate"; "LV2"; "VG"; "50"];
2024 InitEmpty, Always, TestOutputList (
2025 [["sfdiskM"; "/dev/sda"; ","];
2026 ["pvcreate"; "/dev/sda1"];
2027 ["vgcreate"; "VG"; "/dev/sda1"];
2028 ["lvcreate"; "LV1"; "VG"; "50"];
2029 ["lvcreate"; "LV2"; "VG"; "50"];
2032 "remove an LVM volume group",
2034 Remove an LVM volume group C<vgname>, (for example C<VG>).
2036 This also forcibly removes all logical volumes in the volume
2039 ("pvremove", (RErr, [Device "device"]), 79, [],
2040 [InitEmpty, Always, TestOutputListOfDevices (
2041 [["sfdiskM"; "/dev/sda"; ","];
2042 ["pvcreate"; "/dev/sda1"];
2043 ["vgcreate"; "VG"; "/dev/sda1"];
2044 ["lvcreate"; "LV1"; "VG"; "50"];
2045 ["lvcreate"; "LV2"; "VG"; "50"];
2047 ["pvremove"; "/dev/sda1"];
2049 InitEmpty, Always, TestOutputListOfDevices (
2050 [["sfdiskM"; "/dev/sda"; ","];
2051 ["pvcreate"; "/dev/sda1"];
2052 ["vgcreate"; "VG"; "/dev/sda1"];
2053 ["lvcreate"; "LV1"; "VG"; "50"];
2054 ["lvcreate"; "LV2"; "VG"; "50"];
2056 ["pvremove"; "/dev/sda1"];
2058 InitEmpty, Always, TestOutputListOfDevices (
2059 [["sfdiskM"; "/dev/sda"; ","];
2060 ["pvcreate"; "/dev/sda1"];
2061 ["vgcreate"; "VG"; "/dev/sda1"];
2062 ["lvcreate"; "LV1"; "VG"; "50"];
2063 ["lvcreate"; "LV2"; "VG"; "50"];
2065 ["pvremove"; "/dev/sda1"];
2067 "remove an LVM physical volume",
2069 This wipes a physical volume C<device> so that LVM will no longer
2072 The implementation uses the C<pvremove> command which refuses to
2073 wipe physical volumes that contain any volume groups, so you have
2074 to remove those first.");
2076 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2077 [InitBasicFS, Always, TestOutput (
2078 [["set_e2label"; "/dev/sda1"; "testlabel"];
2079 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2080 "set the ext2/3/4 filesystem label",
2082 This sets the ext2/3/4 filesystem label of the filesystem on
2083 C<device> to C<label>. Filesystem labels are limited to
2086 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2087 to return the existing label on a filesystem.");
2089 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2091 "get the ext2/3/4 filesystem label",
2093 This returns the ext2/3/4 filesystem label of the filesystem on
2096 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2097 (let uuid = uuidgen () in
2098 [InitBasicFS, Always, TestOutput (
2099 [["set_e2uuid"; "/dev/sda1"; uuid];
2100 ["get_e2uuid"; "/dev/sda1"]], uuid);
2101 InitBasicFS, Always, TestOutput (
2102 [["set_e2uuid"; "/dev/sda1"; "clear"];
2103 ["get_e2uuid"; "/dev/sda1"]], "");
2104 (* We can't predict what UUIDs will be, so just check the commands run. *)
2105 InitBasicFS, Always, TestRun (
2106 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2107 InitBasicFS, Always, TestRun (
2108 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2109 "set the ext2/3/4 filesystem UUID",
2111 This sets the ext2/3/4 filesystem UUID of the filesystem on
2112 C<device> to C<uuid>. The format of the UUID and alternatives
2113 such as C<clear>, C<random> and C<time> are described in the
2114 L<tune2fs(8)> manpage.
2116 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2117 to return the existing UUID of a filesystem.");
2119 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2121 "get the ext2/3/4 filesystem UUID",
2123 This returns the ext2/3/4 filesystem UUID of the filesystem on
2126 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2127 [InitBasicFS, Always, TestOutputInt (
2128 [["umount"; "/dev/sda1"];
2129 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2130 InitBasicFS, Always, TestOutputInt (
2131 [["umount"; "/dev/sda1"];
2132 ["zero"; "/dev/sda1"];
2133 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2134 "run the filesystem checker",
2136 This runs the filesystem checker (fsck) on C<device> which
2137 should have filesystem type C<fstype>.
2139 The returned integer is the status. See L<fsck(8)> for the
2140 list of status codes from C<fsck>.
2148 Multiple status codes can be summed together.
2152 A non-zero return code can mean \"success\", for example if
2153 errors have been corrected on the filesystem.
2157 Checking or repairing NTFS volumes is not supported
2162 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2164 ("zero", (RErr, [Device "device"]), 85, [],
2165 [InitBasicFS, Always, TestOutput (
2166 [["umount"; "/dev/sda1"];
2167 ["zero"; "/dev/sda1"];
2168 ["file"; "/dev/sda1"]], "data")],
2169 "write zeroes to the device",
2171 This command writes zeroes over the first few blocks of C<device>.
2173 How many blocks are zeroed isn't specified (but it's I<not> enough
2174 to securely wipe the device). It should be sufficient to remove
2175 any partition tables, filesystem superblocks and so on.
2177 See also: C<guestfs_scrub_device>.");
2179 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2180 (* Test disabled because grub-install incompatible with virtio-blk driver.
2181 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2183 [InitBasicFS, Disabled, TestOutputTrue (
2184 [["grub_install"; "/"; "/dev/sda1"];
2185 ["is_dir"; "/boot"]])],
2188 This command installs GRUB (the Grand Unified Bootloader) on
2189 C<device>, with the root directory being C<root>.");
2191 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2192 [InitBasicFS, Always, TestOutput (
2193 [["write_file"; "/old"; "file content"; "0"];
2194 ["cp"; "/old"; "/new"];
2195 ["cat"; "/new"]], "file content");
2196 InitBasicFS, Always, TestOutputTrue (
2197 [["write_file"; "/old"; "file content"; "0"];
2198 ["cp"; "/old"; "/new"];
2199 ["is_file"; "/old"]]);
2200 InitBasicFS, Always, TestOutput (
2201 [["write_file"; "/old"; "file content"; "0"];
2203 ["cp"; "/old"; "/dir/new"];
2204 ["cat"; "/dir/new"]], "file content")],
2207 This copies a file from C<src> to C<dest> where C<dest> is
2208 either a destination filename or destination directory.");
2210 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2211 [InitBasicFS, Always, TestOutput (
2212 [["mkdir"; "/olddir"];
2213 ["mkdir"; "/newdir"];
2214 ["write_file"; "/olddir/file"; "file content"; "0"];
2215 ["cp_a"; "/olddir"; "/newdir"];
2216 ["cat"; "/newdir/olddir/file"]], "file content")],
2217 "copy a file or directory recursively",
2219 This copies a file or directory from C<src> to C<dest>
2220 recursively using the C<cp -a> command.");
2222 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2223 [InitBasicFS, Always, TestOutput (
2224 [["write_file"; "/old"; "file content"; "0"];
2225 ["mv"; "/old"; "/new"];
2226 ["cat"; "/new"]], "file content");
2227 InitBasicFS, Always, TestOutputFalse (
2228 [["write_file"; "/old"; "file content"; "0"];
2229 ["mv"; "/old"; "/new"];
2230 ["is_file"; "/old"]])],
2233 This moves a file from C<src> to C<dest> where C<dest> is
2234 either a destination filename or destination directory.");
2236 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2237 [InitEmpty, Always, TestRun (
2238 [["drop_caches"; "3"]])],
2239 "drop kernel page cache, dentries and inodes",
2241 This instructs the guest kernel to drop its page cache,
2242 and/or dentries and inode caches. The parameter C<whattodrop>
2243 tells the kernel what precisely to drop, see
2244 L<http://linux-mm.org/Drop_Caches>
2246 Setting C<whattodrop> to 3 should drop everything.
2248 This automatically calls L<sync(2)> before the operation,
2249 so that the maximum guest memory is freed.");
2251 ("dmesg", (RString "kmsgs", []), 91, [],
2252 [InitEmpty, Always, TestRun (
2254 "return kernel messages",
2256 This returns the kernel messages (C<dmesg> output) from
2257 the guest kernel. This is sometimes useful for extended
2258 debugging of problems.
2260 Another way to get the same information is to enable
2261 verbose messages with C<guestfs_set_verbose> or by setting
2262 the environment variable C<LIBGUESTFS_DEBUG=1> before
2263 running the program.");
2265 ("ping_daemon", (RErr, []), 92, [],
2266 [InitEmpty, Always, TestRun (
2267 [["ping_daemon"]])],
2268 "ping the guest daemon",
2270 This is a test probe into the guestfs daemon running inside
2271 the qemu subprocess. Calling this function checks that the
2272 daemon responds to the ping message, without affecting the daemon
2273 or attached block device(s) in any other way.");
2275 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2276 [InitBasicFS, Always, TestOutputTrue (
2277 [["write_file"; "/file1"; "contents of a file"; "0"];
2278 ["cp"; "/file1"; "/file2"];
2279 ["equal"; "/file1"; "/file2"]]);
2280 InitBasicFS, Always, TestOutputFalse (
2281 [["write_file"; "/file1"; "contents of a file"; "0"];
2282 ["write_file"; "/file2"; "contents of another file"; "0"];
2283 ["equal"; "/file1"; "/file2"]]);
2284 InitBasicFS, Always, TestLastFail (
2285 [["equal"; "/file1"; "/file2"]])],
2286 "test if two files have equal contents",
2288 This compares the two files C<file1> and C<file2> and returns
2289 true if their content is exactly equal, or false otherwise.
2291 The external L<cmp(1)> program is used for the comparison.");
2293 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2294 [InitISOFS, Always, TestOutputList (
2295 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2296 InitISOFS, Always, TestOutputList (
2297 [["strings"; "/empty"]], [])],
2298 "print the printable strings in a file",
2300 This runs the L<strings(1)> command on a file and returns
2301 the list of printable strings found.");
2303 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2304 [InitISOFS, Always, TestOutputList (
2305 [["strings_e"; "b"; "/known-5"]], []);
2306 InitBasicFS, Disabled, TestOutputList (
2307 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2308 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2309 "print the printable strings in a file",
2311 This is like the C<guestfs_strings> command, but allows you to
2312 specify the encoding.
2314 See the L<strings(1)> manpage for the full list of encodings.
2316 Commonly useful encodings are C<l> (lower case L) which will
2317 show strings inside Windows/x86 files.
2319 The returned strings are transcoded to UTF-8.");
2321 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2322 [InitISOFS, Always, TestOutput (
2323 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2324 (* Test for RHBZ#501888c2 regression which caused large hexdump
2325 * commands to segfault.
2327 InitISOFS, Always, TestRun (
2328 [["hexdump"; "/100krandom"]])],
2329 "dump a file in hexadecimal",
2331 This runs C<hexdump -C> on the given C<path>. The result is
2332 the human-readable, canonical hex dump of the file.");
2334 ("zerofree", (RErr, [Device "device"]), 97, [],
2335 [InitNone, Always, TestOutput (
2336 [["sfdiskM"; "/dev/sda"; ","];
2337 ["mkfs"; "ext3"; "/dev/sda1"];
2338 ["mount"; "/dev/sda1"; "/"];
2339 ["write_file"; "/new"; "test file"; "0"];
2340 ["umount"; "/dev/sda1"];
2341 ["zerofree"; "/dev/sda1"];
2342 ["mount"; "/dev/sda1"; "/"];
2343 ["cat"; "/new"]], "test file")],
2344 "zero unused inodes and disk blocks on ext2/3 filesystem",
2346 This runs the I<zerofree> program on C<device>. This program
2347 claims to zero unused inodes and disk blocks on an ext2/3
2348 filesystem, thus making it possible to compress the filesystem
2351 You should B<not> run this program if the filesystem is
2354 It is possible that using this program can damage the filesystem
2355 or data on the filesystem.");
2357 ("pvresize", (RErr, [Device "device"]), 98, [],
2359 "resize an LVM physical volume",
2361 This resizes (expands or shrinks) an existing LVM physical
2362 volume to match the new size of the underlying device.");
2364 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2365 Int "cyls"; Int "heads"; Int "sectors";
2366 String "line"]), 99, [DangerWillRobinson],
2368 "modify a single partition on a block device",
2370 This runs L<sfdisk(8)> option to modify just the single
2371 partition C<n> (note: C<n> counts from 1).
2373 For other parameters, see C<guestfs_sfdisk>. You should usually
2374 pass C<0> for the cyls/heads/sectors parameters.");
2376 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2378 "display the partition table",
2380 This displays the partition table on C<device>, in the
2381 human-readable output of the L<sfdisk(8)> command. It is
2382 not intended to be parsed.");
2384 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2386 "display the kernel geometry",
2388 This displays the kernel's idea of the geometry of C<device>.
2390 The result is in human-readable format, and not designed to
2393 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2395 "display the disk geometry from the partition table",
2397 This displays the disk geometry of C<device> read from the
2398 partition table. Especially in the case where the underlying
2399 block device has been resized, this can be different from the
2400 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2402 The result is in human-readable format, and not designed to
2405 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2407 "activate or deactivate all volume groups",
2409 This command activates or (if C<activate> is false) deactivates
2410 all logical volumes in all volume groups.
2411 If activated, then they are made known to the
2412 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2413 then those devices disappear.
2415 This command is the same as running C<vgchange -a y|n>");
2417 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2419 "activate or deactivate some volume groups",
2421 This command activates or (if C<activate> is false) deactivates
2422 all logical volumes in the listed volume groups C<volgroups>.
2423 If activated, then they are made known to the
2424 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2425 then those devices disappear.
2427 This command is the same as running C<vgchange -a y|n volgroups...>
2429 Note that if C<volgroups> is an empty list then B<all> volume groups
2430 are activated or deactivated.");
2432 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2433 [InitNone, Always, TestOutput (
2434 [["sfdiskM"; "/dev/sda"; ","];
2435 ["pvcreate"; "/dev/sda1"];
2436 ["vgcreate"; "VG"; "/dev/sda1"];
2437 ["lvcreate"; "LV"; "VG"; "10"];
2438 ["mkfs"; "ext2"; "/dev/VG/LV"];
2439 ["mount"; "/dev/VG/LV"; "/"];
2440 ["write_file"; "/new"; "test content"; "0"];
2442 ["lvresize"; "/dev/VG/LV"; "20"];
2443 ["e2fsck_f"; "/dev/VG/LV"];
2444 ["resize2fs"; "/dev/VG/LV"];
2445 ["mount"; "/dev/VG/LV"; "/"];
2446 ["cat"; "/new"]], "test content")],
2447 "resize an LVM logical volume",
2449 This resizes (expands or shrinks) an existing LVM logical
2450 volume to C<mbytes>. When reducing, data in the reduced part
2453 ("resize2fs", (RErr, [Device "device"]), 106, [],
2454 [], (* lvresize tests this *)
2455 "resize an ext2/ext3 filesystem",
2457 This resizes an ext2 or ext3 filesystem to match the size of
2458 the underlying device.
2460 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2461 on the C<device> before calling this command. For unknown reasons
2462 C<resize2fs> sometimes gives an error about this and sometimes not.
2463 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2464 calling this function.");
2466 ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2467 [InitBasicFS, Always, TestOutputList (
2468 [["find"; "/"]], ["lost+found"]);
2469 InitBasicFS, Always, TestOutputList (
2473 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2474 InitBasicFS, Always, TestOutputList (
2475 [["mkdir_p"; "/a/b/c"];
2476 ["touch"; "/a/b/c/d"];
2477 ["find"; "/a/b/"]], ["c"; "c/d"])],
2478 "find all files and directories",
2480 This command lists out all files and directories, recursively,
2481 starting at C<directory>. It is essentially equivalent to
2482 running the shell command C<find directory -print> but some
2483 post-processing happens on the output, described below.
2485 This returns a list of strings I<without any prefix>. Thus
2486 if the directory structure was:
2492 then the returned list from C<guestfs_find> C</tmp> would be
2500 If C<directory> is not a directory, then this command returns
2503 The returned list is sorted.");
2505 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2506 [], (* lvresize tests this *)
2507 "check an ext2/ext3 filesystem",
2509 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2510 filesystem checker on C<device>, noninteractively (C<-p>),
2511 even if the filesystem appears to be clean (C<-f>).
2513 This command is only needed because of C<guestfs_resize2fs>
2514 (q.v.). Normally you should use C<guestfs_fsck>.");
2516 ("sleep", (RErr, [Int "secs"]), 109, [],
2517 [InitNone, Always, TestRun (
2519 "sleep for some seconds",
2521 Sleep for C<secs> seconds.");
2523 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2524 [InitNone, Always, TestOutputInt (
2525 [["sfdiskM"; "/dev/sda"; ","];
2526 ["mkfs"; "ntfs"; "/dev/sda1"];
2527 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2528 InitNone, Always, TestOutputInt (
2529 [["sfdiskM"; "/dev/sda"; ","];
2530 ["mkfs"; "ext2"; "/dev/sda1"];
2531 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2532 "probe NTFS volume",
2534 This command runs the L<ntfs-3g.probe(8)> command which probes
2535 an NTFS C<device> for mountability. (Not all NTFS volumes can
2536 be mounted read-write, and some cannot be mounted at all).
2538 C<rw> is a boolean flag. Set it to true if you want to test
2539 if the volume can be mounted read-write. Set it to false if
2540 you want to test if the volume can be mounted read-only.
2542 The return value is an integer which C<0> if the operation
2543 would succeed, or some non-zero value documented in the
2544 L<ntfs-3g.probe(8)> manual page.");
2546 ("sh", (RString "output", [String "command"]), 111, [],
2547 [], (* XXX needs tests *)
2548 "run a command via the shell",
2550 This call runs a command from the guest filesystem via the
2553 This is like C<guestfs_command>, but passes the command to:
2555 /bin/sh -c \"command\"
2557 Depending on the guest's shell, this usually results in
2558 wildcards being expanded, shell expressions being interpolated
2561 All the provisos about C<guestfs_command> apply to this call.");
2563 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2564 [], (* XXX needs tests *)
2565 "run a command via the shell returning lines",
2567 This is the same as C<guestfs_sh>, but splits the result
2568 into a list of lines.
2570 See also: C<guestfs_command_lines>");
2572 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2573 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2574 * code in stubs.c, since all valid glob patterns must start with "/".
2575 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2577 [InitBasicFS, Always, TestOutputList (
2578 [["mkdir_p"; "/a/b/c"];
2579 ["touch"; "/a/b/c/d"];
2580 ["touch"; "/a/b/c/e"];
2581 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2582 InitBasicFS, Always, TestOutputList (
2583 [["mkdir_p"; "/a/b/c"];
2584 ["touch"; "/a/b/c/d"];
2585 ["touch"; "/a/b/c/e"];
2586 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2587 InitBasicFS, Always, TestOutputList (
2588 [["mkdir_p"; "/a/b/c"];
2589 ["touch"; "/a/b/c/d"];
2590 ["touch"; "/a/b/c/e"];
2591 ["glob_expand"; "/a/*/x/*"]], [])],
2592 "expand a wildcard path",
2594 This command searches for all the pathnames matching
2595 C<pattern> according to the wildcard expansion rules
2598 If no paths match, then this returns an empty list
2599 (note: not an error).
2601 It is just a wrapper around the C L<glob(3)> function
2602 with flags C<GLOB_MARK|GLOB_BRACE>.
2603 See that manual page for more details.");
2605 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2606 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2607 [["scrub_device"; "/dev/sdc"]])],
2608 "scrub (securely wipe) a device",
2610 This command writes patterns over C<device> to make data retrieval
2613 It is an interface to the L<scrub(1)> program. See that
2614 manual page for more details.");
2616 ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2617 [InitBasicFS, Always, TestRun (
2618 [["write_file"; "/file"; "content"; "0"];
2619 ["scrub_file"; "/file"]])],
2620 "scrub (securely wipe) a file",
2622 This command writes patterns over a file to make data retrieval
2625 The file is I<removed> after scrubbing.
2627 It is an interface to the L<scrub(1)> program. See that
2628 manual page for more details.");
2630 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2631 [], (* XXX needs testing *)
2632 "scrub (securely wipe) free space",
2634 This command creates the directory C<dir> and then fills it
2635 with files until the filesystem is full, and scrubs the files
2636 as for C<guestfs_scrub_file>, and deletes them.
2637 The intention is to scrub any free space on the partition
2640 It is an interface to the L<scrub(1)> program. See that
2641 manual page for more details.");
2643 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2644 [InitBasicFS, Always, TestRun (
2646 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2647 "create a temporary directory",
2649 This command creates a temporary directory. The
2650 C<template> parameter should be a full pathname for the
2651 temporary directory name with the final six characters being
2654 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2655 the second one being suitable for Windows filesystems.
2657 The name of the temporary directory that was created
2660 The temporary directory is created with mode 0700
2661 and is owned by root.
2663 The caller is responsible for deleting the temporary
2664 directory and its contents after use.
2666 See also: L<mkdtemp(3)>");
2668 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2669 [InitISOFS, Always, TestOutputInt (
2670 [["wc_l"; "/10klines"]], 10000)],
2671 "count lines in a file",
2673 This command counts the lines in a file, using the
2674 C<wc -l> external command.");
2676 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2677 [InitISOFS, Always, TestOutputInt (
2678 [["wc_w"; "/10klines"]], 10000)],
2679 "count words in a file",
2681 This command counts the words in a file, using the
2682 C<wc -w> external command.");
2684 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2685 [InitISOFS, Always, TestOutputInt (
2686 [["wc_c"; "/100kallspaces"]], 102400)],
2687 "count characters in a file",
2689 This command counts the characters in a file, using the
2690 C<wc -c> external command.");
2692 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2693 [InitISOFS, Always, TestOutputList (
2694 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2695 "return first 10 lines of a file",
2697 This command returns up to the first 10 lines of a file as
2698 a list of strings.");
2700 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2701 [InitISOFS, Always, TestOutputList (
2702 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2703 InitISOFS, Always, TestOutputList (
2704 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2705 InitISOFS, Always, TestOutputList (
2706 [["head_n"; "0"; "/10klines"]], [])],
2707 "return first N lines of a file",
2709 If the parameter C<nrlines> is a positive number, this returns the first
2710 C<nrlines> lines of the file C<path>.
2712 If the parameter C<nrlines> is a negative number, this returns lines
2713 from the file C<path>, excluding the last C<nrlines> lines.
2715 If the parameter C<nrlines> is zero, this returns an empty list.");
2717 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2718 [InitISOFS, Always, TestOutputList (
2719 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2720 "return last 10 lines of a file",
2722 This command returns up to the last 10 lines of a file as
2723 a list of strings.");
2725 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2726 [InitISOFS, Always, TestOutputList (
2727 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2728 InitISOFS, Always, TestOutputList (
2729 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2730 InitISOFS, Always, TestOutputList (
2731 [["tail_n"; "0"; "/10klines"]], [])],
2732 "return last N lines of a file",
2734 If the parameter C<nrlines> is a positive number, this returns the last
2735 C<nrlines> lines of the file C<path>.
2737 If the parameter C<nrlines> is a negative number, this returns lines
2738 from the file C<path>, starting with the C<-nrlines>th line.
2740 If the parameter C<nrlines> is zero, this returns an empty list.");
2742 ("df", (RString "output", []), 125, [],
2743 [], (* XXX Tricky to test because it depends on the exact format
2744 * of the 'df' command and other imponderables.
2746 "report file system disk space usage",
2748 This command runs the C<df> command to report disk space used.
2750 This command is mostly useful for interactive sessions. It
2751 is I<not> intended that you try to parse the output string.
2752 Use C<statvfs> from programs.");
2754 ("df_h", (RString "output", []), 126, [],
2755 [], (* XXX Tricky to test because it depends on the exact format
2756 * of the 'df' command and other imponderables.
2758 "report file system disk space usage (human readable)",
2760 This command runs the C<df -h> command to report disk space used
2761 in human-readable format.
2763 This command is mostly useful for interactive sessions. It
2764 is I<not> intended that you try to parse the output string.
2765 Use C<statvfs> from programs.");
2767 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2768 [InitISOFS, Always, TestOutputInt (
2769 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2770 "estimate file space usage",
2772 This command runs the C<du -s> command to estimate file space
2775 C<path> can be a file or a directory. If C<path> is a directory
2776 then the estimate includes the contents of the directory and all
2777 subdirectories (recursively).
2779 The result is the estimated size in I<kilobytes>
2780 (ie. units of 1024 bytes).");
2782 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2783 [InitISOFS, Always, TestOutputList (
2784 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2785 "list files in an initrd",
2787 This command lists out files contained in an initrd.
2789 The files are listed without any initial C</> character. The
2790 files are listed in the order they appear (not necessarily
2791 alphabetical). Directory names are listed as separate items.
2793 Old Linux kernels (2.4 and earlier) used a compressed ext2
2794 filesystem as initrd. We I<only> support the newer initramfs
2795 format (compressed cpio files).");
2797 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2799 "mount a file using the loop device",
2801 This command lets you mount C<file> (a filesystem image
2802 in a file) on a mount point. It is entirely equivalent to
2803 the command C<mount -o loop file mountpoint>.");
2805 ("mkswap", (RErr, [Device "device"]), 130, [],
2806 [InitEmpty, Always, TestRun (
2807 [["sfdiskM"; "/dev/sda"; ","];
2808 ["mkswap"; "/dev/sda1"]])],
2809 "create a swap partition",
2811 Create a swap partition on C<device>.");
2813 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2814 [InitEmpty, Always, TestRun (
2815 [["sfdiskM"; "/dev/sda"; ","];
2816 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2817 "create a swap partition with a label",
2819 Create a swap partition on C<device> with label C<label>.
2821 Note that you cannot attach a swap label to a block device
2822 (eg. C</dev/sda>), just to a partition. This appears to be
2823 a limitation of the kernel or swap tools.");
2825 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2826 (let uuid = uuidgen () in
2827 [InitEmpty, Always, TestRun (
2828 [["sfdiskM"; "/dev/sda"; ","];
2829 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2830 "create a swap partition with an explicit UUID",
2832 Create a swap partition on C<device> with UUID C<uuid>.");
2834 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2835 [InitBasicFS, Always, TestOutputStruct (
2836 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2837 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2838 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2839 InitBasicFS, Always, TestOutputStruct (
2840 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2841 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2842 "make block, character or FIFO devices",
2844 This call creates block or character special devices, or
2845 named pipes (FIFOs).
2847 The C<mode> parameter should be the mode, using the standard
2848 constants. C<devmajor> and C<devminor> are the
2849 device major and minor numbers, only used when creating block
2850 and character special devices.");
2852 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2853 [InitBasicFS, Always, TestOutputStruct (
2854 [["mkfifo"; "0o777"; "/node"];
2855 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2856 "make FIFO (named pipe)",
2858 This call creates a FIFO (named pipe) called C<path> with
2859 mode C<mode>. It is just a convenient wrapper around
2860 C<guestfs_mknod>.");
2862 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2863 [InitBasicFS, Always, TestOutputStruct (
2864 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2865 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2866 "make block device node",
2868 This call creates a block device node called C<path> with
2869 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2870 It is just a convenient wrapper around C<guestfs_mknod>.");
2872 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2873 [InitBasicFS, Always, TestOutputStruct (
2874 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2875 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2876 "make char device node",
2878 This call creates a char device node called C<path> with
2879 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2880 It is just a convenient wrapper around C<guestfs_mknod>.");
2882 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2883 [], (* XXX umask is one of those stateful things that we should
2884 * reset between each test.
2886 "set file mode creation mask (umask)",
2888 This function sets the mask used for creating new files and
2889 device nodes to C<mask & 0777>.
2891 Typical umask values would be C<022> which creates new files
2892 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2893 C<002> which creates new files with permissions like
2894 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2896 The default umask is C<022>. This is important because it
2897 means that directories and device nodes will be created with
2898 C<0644> or C<0755> mode even if you specify C<0777>.
2900 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2902 This call returns the previous umask.");
2904 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2906 "read directories entries",
2908 This returns the list of directory entries in directory C<dir>.
2910 All entries in the directory are returned, including C<.> and
2911 C<..>. The entries are I<not> sorted, but returned in the same
2912 order as the underlying filesystem.
2914 Also this call returns basic file type information about each
2915 file. The C<ftyp> field will contain one of the following characters:
2953 The L<readdir(3)> returned a C<d_type> field with an
2958 This function is primarily intended for use by programs. To
2959 get a simple list of names, use C<guestfs_ls>. To get a printable
2960 directory for human consumption, use C<guestfs_ll>.");
2962 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2964 "create partitions on a block device",
2966 This is a simplified interface to the C<guestfs_sfdisk>
2967 command, where partition sizes are specified in megabytes
2968 only (rounded to the nearest cylinder) and you don't need
2969 to specify the cyls, heads and sectors parameters which
2970 were rarely if ever used anyway.
2972 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2974 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
2976 "determine file type inside a compressed file",
2978 This command runs C<file> after first decompressing C<path>
2981 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2983 Since 1.0.63, use C<guestfs_file> instead which can now
2984 process compressed files.");
2986 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
2988 "list extended attributes of a file or directory",
2990 This call lists the extended attributes of the file or directory
2993 At the system call level, this is a combination of the
2994 L<listxattr(2)> and L<getxattr(2)> calls.
2996 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2998 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3000 "list extended attributes of a file or directory",
3002 This is the same as C<guestfs_getxattrs>, but if C<path>
3003 is a symbolic link, then it returns the extended attributes
3004 of the link itself.");
3006 ("setxattr", (RErr, [String "xattr";
3007 String "val"; Int "vallen"; (* will be BufferIn *)
3008 Pathname "path"]), 143, [],
3010 "set extended attribute of a file or directory",
3012 This call sets the extended attribute named C<xattr>
3013 of the file C<path> to the value C<val> (of length C<vallen>).
3014 The value is arbitrary 8 bit data.
3016 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3018 ("lsetxattr", (RErr, [String "xattr";
3019 String "val"; Int "vallen"; (* will be BufferIn *)
3020 Pathname "path"]), 144, [],
3022 "set extended attribute of a file or directory",
3024 This is the same as C<guestfs_setxattr>, but if C<path>
3025 is a symbolic link, then it sets an extended attribute
3026 of the link itself.");
3028 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3030 "remove extended attribute of a file or directory",
3032 This call removes the extended attribute named C<xattr>
3033 of the file C<path>.
3035 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3037 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3039 "remove extended attribute of a file or directory",
3041 This is the same as C<guestfs_removexattr>, but if C<path>
3042 is a symbolic link, then it removes an extended attribute
3043 of the link itself.");
3045 ("mountpoints", (RHashtable "mps", []), 147, [],
3049 This call is similar to C<guestfs_mounts>. That call returns
3050 a list of devices. This one returns a hash table (map) of
3051 device name to directory where the device is mounted.");
3053 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3054 (* This is a special case: while you would expect a parameter
3055 * of type "Pathname", that doesn't work, because it implies
3056 * NEED_ROOT in the generated calling code in stubs.c, and
3057 * this function cannot use NEED_ROOT.
3060 "create a mountpoint",
3062 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3063 specialized calls that can be used to create extra mountpoints
3064 before mounting the first filesystem.
3066 These calls are I<only> necessary in some very limited circumstances,
3067 mainly the case where you want to mount a mix of unrelated and/or
3068 read-only filesystems together.
3070 For example, live CDs often contain a \"Russian doll\" nest of
3071 filesystems, an ISO outer layer, with a squashfs image inside, with
3072 an ext2/3 image inside that. You can unpack this as follows
3075 add-ro Fedora-11-i686-Live.iso
3078 mkmountpoint /squash
3081 mount-loop /cd/LiveOS/squashfs.img /squash
3082 mount-loop /squash/LiveOS/ext3fs.img /ext3
3084 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3086 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3088 "remove a mountpoint",
3090 This calls removes a mountpoint that was previously created
3091 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3092 for full details.");
3094 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3095 [InitISOFS, Always, TestOutputBuffer (
3096 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3099 This calls returns the contents of the file C<path> as a
3102 Unlike C<guestfs_cat>, this function can correctly
3103 handle files that contain embedded ASCII NUL characters.
3104 However unlike C<guestfs_download>, this function is limited
3105 in the total size of file that can be handled.");
3107 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3108 [InitISOFS, Always, TestOutputList (
3109 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3110 InitISOFS, Always, TestOutputList (
3111 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3112 "return lines matching a pattern",
3114 This calls the external C<grep> program and returns the
3117 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3118 [InitISOFS, Always, TestOutputList (
3119 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3120 "return lines matching a pattern",
3122 This calls the external C<egrep> program and returns the
3125 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3126 [InitISOFS, Always, TestOutputList (
3127 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3128 "return lines matching a pattern",
3130 This calls the external C<fgrep> program and returns the
3133 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3134 [InitISOFS, Always, TestOutputList (
3135 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3136 "return lines matching a pattern",
3138 This calls the external C<grep -i> program and returns the
3141 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3142 [InitISOFS, Always, TestOutputList (
3143 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3144 "return lines matching a pattern",
3146 This calls the external C<egrep -i> program and returns the
3149 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3150 [InitISOFS, Always, TestOutputList (
3151 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3152 "return lines matching a pattern",
3154 This calls the external C<fgrep -i> program and returns the
3157 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3158 [InitISOFS, Always, TestOutputList (
3159 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3160 "return lines matching a pattern",
3162 This calls the external C<zgrep> program and returns the
3165 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3166 [InitISOFS, Always, TestOutputList (
3167 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3168 "return lines matching a pattern",
3170 This calls the external C<zegrep> program and returns the
3173 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3174 [InitISOFS, Always, TestOutputList (
3175 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3176 "return lines matching a pattern",
3178 This calls the external C<zfgrep> program and returns the
3181 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3182 [InitISOFS, Always, TestOutputList (
3183 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3184 "return lines matching a pattern",
3186 This calls the external C<zgrep -i> program and returns the
3189 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3190 [InitISOFS, Always, TestOutputList (
3191 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3192 "return lines matching a pattern",
3194 This calls the external C<zegrep -i> program and returns the
3197 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3198 [InitISOFS, Always, TestOutputList (
3199 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3200 "return lines matching a pattern",
3202 This calls the external C<zfgrep -i> program and returns the
3205 ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3206 [InitISOFS, Always, TestOutput (
3207 [["realpath"; "/../directory"]], "/directory")],
3208 "canonicalized absolute pathname",
3210 Return the canonicalized absolute pathname of C<path>. The
3211 returned path has no C<.>, C<..> or symbolic link path elements.");
3213 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3214 [InitBasicFS, Always, TestOutputStruct (
3217 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3218 "create a hard link",
3220 This command creates a hard link using the C<ln> command.");
3222 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3223 [InitBasicFS, Always, TestOutputStruct (
3226 ["ln_f"; "/a"; "/b"];
3227 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3228 "create a hard link",
3230 This command creates a hard link using the C<ln -f> command.
3231 The C<-f> option removes the link (C<linkname>) if it exists already.");
3233 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3234 [InitBasicFS, Always, TestOutputStruct (
3236 ["ln_s"; "a"; "/b"];
3237 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3238 "create a symbolic link",
3240 This command creates a symbolic link using the C<ln -s> command.");
3242 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3243 [InitBasicFS, Always, TestOutput (
3244 [["mkdir_p"; "/a/b"];
3245 ["touch"; "/a/b/c"];
3246 ["ln_sf"; "../d"; "/a/b/c"];
3247 ["readlink"; "/a/b/c"]], "../d")],
3248 "create a symbolic link",
3250 This command creates a symbolic link using the C<ln -sf> command,
3251 The C<-f> option removes the link (C<linkname>) if it exists already.");
3253 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3254 [] (* XXX tested above *),
3255 "read the target of a symbolic link",
3257 This command reads the target of a symbolic link.");
3259 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3260 [InitBasicFS, Always, TestOutputStruct (
3261 [["fallocate"; "/a"; "1000000"];
3262 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3263 "preallocate a file in the guest filesystem",
3265 This command preallocates a file (containing zero bytes) named
3266 C<path> of size C<len> bytes. If the file exists already, it
3269 Do not confuse this with the guestfish-specific
3270 C<alloc> command which allocates a file in the host and
3271 attaches it as a device.");
3273 ("swapon_device", (RErr, [Device "device"]), 170, [],
3274 [InitPartition, Always, TestRun (
3275 [["mkswap"; "/dev/sda1"];
3276 ["swapon_device"; "/dev/sda1"];
3277 ["swapoff_device"; "/dev/sda1"]])],
3278 "enable swap on device",
3280 This command enables the libguestfs appliance to use the
3281 swap device or partition named C<device>. The increased
3282 memory is made available for all commands, for example
3283 those run using C<guestfs_command> or C<guestfs_sh>.
3285 Note that you should not swap to existing guest swap
3286 partitions unless you know what you are doing. They may
3287 contain hibernation information, or other information that
3288 the guest doesn't want you to trash. You also risk leaking
3289 information about the host to the guest this way. Instead,
3290 attach a new host device to the guest and swap on that.");
3292 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3293 [], (* XXX tested by swapon_device *)
3294 "disable swap on device",
3296 This command disables the libguestfs appliance swap
3297 device or partition named C<device>.
3298 See C<guestfs_swapon_device>.");
3300 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3301 [InitBasicFS, Always, TestRun (
3302 [["fallocate"; "/swap"; "8388608"];
3303 ["mkswap_file"; "/swap"];
3304 ["swapon_file"; "/swap"];
3305 ["swapoff_file"; "/swap"]])],
3306 "enable swap on file",
3308 This command enables swap to a file.
3309 See C<guestfs_swapon_device> for other notes.");
3311 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3312 [], (* XXX tested by swapon_file *)
3313 "disable swap on file",
3315 This command disables the libguestfs appliance swap on file.");
3317 ("swapon_label", (RErr, [String "label"]), 174, [],
3318 [InitEmpty, Always, TestRun (
3319 [["sfdiskM"; "/dev/sdb"; ","];
3320 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3321 ["swapon_label"; "swapit"];
3322 ["swapoff_label"; "swapit"];
3323 ["zero"; "/dev/sdb"];
3324 ["blockdev_rereadpt"; "/dev/sdb"]])],
3325 "enable swap on labeled swap partition",
3327 This command enables swap to a labeled swap partition.
3328 See C<guestfs_swapon_device> for other notes.");
3330 ("swapoff_label", (RErr, [String "label"]), 175, [],
3331 [], (* XXX tested by swapon_label *)
3332 "disable swap on labeled swap partition",
3334 This command disables the libguestfs appliance swap on
3335 labeled swap partition.");
3337 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3338 (let uuid = uuidgen () in
3339 [InitEmpty, Always, TestRun (
3340 [["mkswap_U"; uuid; "/dev/sdb"];
3341 ["swapon_uuid"; uuid];
3342 ["swapoff_uuid"; uuid]])]),
3343 "enable swap on swap partition by UUID",
3345 This command enables swap to a swap partition with the given UUID.
3346 See C<guestfs_swapon_device> for other notes.");
3348 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3349 [], (* XXX tested by swapon_uuid *)
3350 "disable swap on swap partition by UUID",
3352 This command disables the libguestfs appliance swap partition
3353 with the given UUID.");
3355 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3356 [InitBasicFS, Always, TestRun (
3357 [["fallocate"; "/swap"; "8388608"];
3358 ["mkswap_file"; "/swap"]])],
3359 "create a swap file",
3363 This command just writes a swap file signature to an existing
3364 file. To create the file itself, use something like C<guestfs_fallocate>.");
3366 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3367 [InitISOFS, Always, TestRun (
3368 [["inotify_init"; "0"]])],
3369 "create an inotify handle",
3371 This command creates a new inotify handle.
3372 The inotify subsystem can be used to notify events which happen to
3373 objects in the guest filesystem.
3375 C<maxevents> is the maximum number of events which will be
3376 queued up between calls to C<guestfs_inotify_read> or
3377 C<guestfs_inotify_files>.
3378 If this is passed as C<0>, then the kernel (or previously set)
3379 default is used. For Linux 2.6.29 the default was 16384 events.
3380 Beyond this limit, the kernel throws away events, but records
3381 the fact that it threw them away by setting a flag
3382 C<IN_Q_OVERFLOW> in the returned structure list (see
3383 C<guestfs_inotify_read>).
3385 Before any events are generated, you have to add some
3386 watches to the internal watch list. See:
3387 C<guestfs_inotify_add_watch>,
3388 C<guestfs_inotify_rm_watch> and
3389 C<guestfs_inotify_watch_all>.
3391 Queued up events should be read periodically by calling
3392 C<guestfs_inotify_read>
3393 (or C<guestfs_inotify_files> which is just a helpful
3394 wrapper around C<guestfs_inotify_read>). If you don't
3395 read the events out often enough then you risk the internal
3398 The handle should be closed after use by calling
3399 C<guestfs_inotify_close>. This also removes any
3400 watches automatically.
3402 See also L<inotify(7)> for an overview of the inotify interface
3403 as exposed by the Linux kernel, which is roughly what we expose
3404 via libguestfs. Note that there is one global inotify handle
3405 per libguestfs instance.");
3407 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3408 [InitBasicFS, Always, TestOutputList (
3409 [["inotify_init"; "0"];
3410 ["inotify_add_watch"; "/"; "1073741823"];
3413 ["inotify_files"]], ["a"; "b"])],
3414 "add an inotify watch",
3416 Watch C<path> for the events listed in C<mask>.
3418 Note that if C<path> is a directory then events within that
3419 directory are watched, but this does I<not> happen recursively
3420 (in subdirectories).
3422 Note for non-C or non-Linux callers: the inotify events are
3423 defined by the Linux kernel ABI and are listed in
3424 C</usr/include/sys/inotify.h>.");
3426 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3428 "remove an inotify watch",
3430 Remove a previously defined inotify watch.
3431 See C<guestfs_inotify_add_watch>.");
3433 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3435 "return list of inotify events",
3437 Return the complete queue of events that have happened
3438 since the previous read call.
3440 If no events have happened, this returns an empty list.
3442 I<Note>: In order to make sure that all events have been
3443 read, you must call this function repeatedly until it
3444 returns an empty list. The reason is that the call will
3445 read events up to the maximum appliance-to-host message
3446 size and leave remaining events in the queue.");
3448 ("inotify_files", (RStringList "paths", []), 183, [],
3450 "return list of watched files that had events",
3452 This function is a helpful wrapper around C<guestfs_inotify_read>
3453 which just returns a list of pathnames of objects that were
3454 touched. The returned pathnames are sorted and deduplicated.");
3456 ("inotify_close", (RErr, []), 184, [],
3458 "close the inotify handle",
3460 This closes the inotify handle which was previously
3461 opened by inotify_init. It removes all watches, throws
3462 away any pending events, and deallocates all resources.");
3464 ("setcon", (RErr, [String "context"]), 185, [],
3466 "set SELinux security context",
3468 This sets the SELinux security context of the daemon
3469 to the string C<context>.
3471 See the documentation about SELINUX in L<guestfs(3)>.");
3473 ("getcon", (RString "context", []), 186, [],
3475 "get SELinux security context",
3477 This gets the SELinux security context of the daemon.
3479 See the documentation about SELINUX in L<guestfs(3)>,
3480 and C<guestfs_setcon>");
3482 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3483 [InitEmpty, Always, TestOutput (
3484 [["sfdiskM"; "/dev/sda"; ","];
3485 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3486 ["mount"; "/dev/sda1"; "/"];
3487 ["write_file"; "/new"; "new file contents"; "0"];
3488 ["cat"; "/new"]], "new file contents")],
3489 "make a filesystem with block size",
3491 This call is similar to C<guestfs_mkfs>, but it allows you to
3492 control the block size of the resulting filesystem. Supported
3493 block sizes depend on the filesystem type, but typically they
3494 are C<1024>, C<2048> or C<4096> only.");
3496 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3497 [InitEmpty, Always, TestOutput (
3498 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3499 ["mke2journal"; "4096"; "/dev/sda1"];
3500 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3501 ["mount"; "/dev/sda2"; "/"];
3502 ["write_file"; "/new"; "new file contents"; "0"];
3503 ["cat"; "/new"]], "new file contents")],
3504 "make ext2/3/4 external journal",
3506 This creates an ext2 external journal on C<device>. It is equivalent
3509 mke2fs -O journal_dev -b blocksize device");
3511 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3512 [InitEmpty, Always, TestOutput (
3513 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3514 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3515 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3516 ["mount"; "/dev/sda2"; "/"];
3517 ["write_file"; "/new"; "new file contents"; "0"];
3518 ["cat"; "/new"]], "new file contents")],
3519 "make ext2/3/4 external journal with label",
3521 This creates an ext2 external journal on C<device> with label C<label>.");
3523 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3524 (let uuid = uuidgen () in
3525 [InitEmpty, Always, TestOutput (
3526 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3527 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3528 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3529 ["mount"; "/dev/sda2"; "/"];
3530 ["write_file"; "/new"; "new file contents"; "0"];
3531 ["cat"; "/new"]], "new file contents")]),
3532 "make ext2/3/4 external journal with UUID",
3534 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3536 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3538 "make ext2/3/4 filesystem with external journal",
3540 This creates an ext2/3/4 filesystem on C<device> with
3541 an external journal on C<journal>. It is equivalent
3544 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3546 See also C<guestfs_mke2journal>.");
3548 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3550 "make ext2/3/4 filesystem with external journal",
3552 This creates an ext2/3/4 filesystem on C<device> with
3553 an external journal on the journal labeled C<label>.
3555 See also C<guestfs_mke2journal_L>.");
3557 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3559 "make ext2/3/4 filesystem with external journal",
3561 This creates an ext2/3/4 filesystem on C<device> with
3562 an external journal on the journal with UUID C<uuid>.
3564 See also C<guestfs_mke2journal_U>.");
3566 ("modprobe", (RErr, [String "modulename"]), 194, [],
3567 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3568 "load a kernel module",
3570 This loads a kernel module in the appliance.
3572 The kernel module must have been whitelisted when libguestfs
3573 was built (see C<appliance/kmod.whitelist.in> in the source).");
3575 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3576 [InitNone, Always, TestOutput (
3577 [["echo_daemon"; "This is a test"]], "This is a test"
3579 "echo arguments back to the client",
3581 This command concatenate the list of C<words> passed with single spaces between
3582 them and returns the resulting string.
3584 You can use this command to test the connection through to the daemon.
3586 See also C<guestfs_ping_daemon>.");
3590 let all_functions = non_daemon_functions @ daemon_functions
3592 (* In some places we want the functions to be displayed sorted
3593 * alphabetically, so this is useful:
3595 let all_functions_sorted =
3596 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3597 compare n1 n2) all_functions
3599 (* Field types for structures. *)
3601 | FChar (* C 'char' (really, a 7 bit byte). *)
3602 | FString (* nul-terminated ASCII string, NOT NULL. *)
3603 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3608 | FBytes (* Any int measure that counts bytes. *)
3609 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3610 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3612 (* Because we generate extra parsing code for LVM command line tools,
3613 * we have to pull out the LVM columns separately here.
3623 "pv_attr", FString (* XXX *);
3624 "pv_pe_count", FInt64;
3625 "pv_pe_alloc_count", FInt64;
3628 "pv_mda_count", FInt64;
3629 "pv_mda_free", FBytes;
3630 (* Not in Fedora 10:
3631 "pv_mda_size", FBytes;
3638 "vg_attr", FString (* XXX *);
3641 "vg_sysid", FString;
3642 "vg_extent_size", FBytes;
3643 "vg_extent_count", FInt64;
3644 "vg_free_count", FInt64;
3649 "snap_count", FInt64;
3652 "vg_mda_count", FInt64;
3653 "vg_mda_free", FBytes;
3654 (* Not in Fedora 10:
3655 "vg_mda_size", FBytes;
3661 "lv_attr", FString (* XXX *);
3664 "lv_kernel_major", FInt64;
3665 "lv_kernel_minor", FInt64;
3667 "seg_count", FInt64;
3669 "snap_percent", FOptPercent;
3670 "copy_percent", FOptPercent;
3673 "mirror_log", FString;
3677 (* Names and fields in all structures (in RStruct and RStructList)
3681 (* The old RIntBool return type, only ever used for aug_defnode. Do
3682 * not use this struct in any new code.
3685 "i", FInt32; (* for historical compatibility *)
3686 "b", FInt32; (* for historical compatibility *)
3689 (* LVM PVs, VGs, LVs. *)
3690 "lvm_pv", lvm_pv_cols;
3691 "lvm_vg", lvm_vg_cols;
3692 "lvm_lv", lvm_lv_cols;
3694 (* Column names and types from stat structures.
3695 * NB. Can't use things like 'st_atime' because glibc header files
3696 * define some of these as macros. Ugh.
3727 (* Column names in dirent structure. *)
3730 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3735 (* Version numbers. *)
3743 (* Extended attribute. *)
3745 "attrname", FString;
3749 (* Inotify events. *)
3753 "in_cookie", FUInt32;
3756 ] (* end of structs *)
3758 (* Ugh, Java has to be different ..
3759 * These names are also used by the Haskell bindings.
3761 let java_structs = [
3762 "int_bool", "IntBool";
3767 "statvfs", "StatVFS";
3769 "version", "Version";
3771 "inotify_event", "INotifyEvent";
3774 (* What structs are actually returned. *)
3775 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3777 (* Returns a list of RStruct/RStructList structs that are returned
3778 * by any function. Each element of returned list is a pair:
3780 * (structname, RStructOnly)
3781 * == there exists function which returns RStruct (_, structname)
3782 * (structname, RStructListOnly)
3783 * == there exists function which returns RStructList (_, structname)
3784 * (structname, RStructAndList)
3785 * == there are functions returning both RStruct (_, structname)
3786 * and RStructList (_, structname)
3789 (* ||| is a "logical OR" for rstructs_used_t *)
3793 | _, RStructAndList -> RStructAndList
3794 | RStructOnly, RStructListOnly
3795 | RStructListOnly, RStructOnly -> RStructAndList
3796 | RStructOnly, RStructOnly -> RStructOnly
3797 | RStructListOnly, RStructListOnly -> RStructListOnly
3800 let h = Hashtbl.create 13 in
3802 (* if elem->oldv exists, update entry using ||| operator,
3803 * else just add elem->newv to the hash
3805 let update elem newv =
3806 try let oldv = Hashtbl.find h elem in
3807 Hashtbl.replace h elem (newv ||| oldv)
3808 with Not_found -> Hashtbl.add h elem newv
3812 fun (_, style, _, _, _, _, _) ->
3813 match fst style with
3814 | RStruct (_, structname) -> update structname RStructOnly
3815 | RStructList (_, structname) -> update structname RStructListOnly
3819 (* return key->values as a list of (key,value) *)
3820 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3826 | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3827 | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3828 | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3832 (* Used for testing language bindings. *)
3834 | CallString of string
3835 | CallOptString of string option
3836 | CallStringList of string list
3840 (* Used to memoize the result of pod2text. *)
3841 let pod2text_memo_filename = "src/.pod2text.data"
3842 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3844 let chan = open_in pod2text_memo_filename in
3845 let v = input_value chan in
3849 _ -> Hashtbl.create 13
3850 let pod2text_memo_updated () =
3851 let chan = open_out pod2text_memo_filename in
3852 output_value chan pod2text_memo;
3855 (* Useful functions.
3856 * Note we don't want to use any external OCaml libraries which
3857 * makes this a bit harder than it should be.
3859 let failwithf fs = ksprintf failwith fs
3861 let replace_char s c1 c2 =
3862 let s2 = String.copy s in
3863 let r = ref false in
3864 for i = 0 to String.length s2 - 1 do
3865 if String.unsafe_get s2 i = c1 then (
3866 String.unsafe_set s2 i c2;
3870 if not !r then s else s2
3874 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3876 let triml ?(test = isspace) str =
3878 let n = ref (String.length str) in
3879 while !n > 0 && test str.[!i]; do
3884 else String.sub str !i !n
3886 let trimr ?(test = isspace) str =
3887 let n = ref (String.length str) in
3888 while !n > 0 && test str.[!n-1]; do
3891 if !n = String.length str then str
3892 else String.sub str 0 !n
3894 let trim ?(test = isspace) str =
3895 trimr ~test (triml ~test str)
3897 let rec find s sub =
3898 let len = String.length s in
3899 let sublen = String.length sub in
3901 if i <= len-sublen then (
3903 if j < sublen then (
3904 if s.[i+j] = sub.[j] then loop2 (j+1)
3910 if r = -1 then loop (i+1) else r
3916 let rec replace_str s s1 s2 =
3917 let len = String.length s in
3918 let sublen = String.length s1 in
3919 let i = find s s1 in
3922 let s' = String.sub s 0 i in
3923 let s'' = String.sub s (i+sublen) (len-i-sublen) in
3924 s' ^ s2 ^ replace_str s'' s1 s2
3927 let rec string_split sep str =
3928 let len = String.length str in
3929 let seplen = String.length sep in
3930 let i = find str sep in
3931 if i = -1 then [str]
3933 let s' = String.sub str 0 i in
3934 let s'' = String.sub str (i+seplen) (len-i-seplen) in
3935 s' :: string_split sep s''
3938 let files_equal n1 n2 =
3939 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3940 match Sys.command cmd with
3943 | i -> failwithf "%s: failed with error code %d" cmd i
3945 let rec filter_map f = function
3949 | Some y -> y :: filter_map f xs
3950 | None -> filter_map f xs
3952 let rec find_map f = function
3953 | [] -> raise Not_found
3957 | None -> find_map f xs
3960 let rec loop i = function
3962 | x :: xs -> f i x; loop (i+1) xs
3967 let rec loop i = function
3969 | x :: xs -> let r = f i x in r :: loop (i+1) xs
3973 let name_of_argt = function
3974 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
3975 | StringList n | DeviceList n | Bool n | Int n
3976 | FileIn n | FileOut n -> n
3978 let java_name_of_struct typ =
3979 try List.assoc typ java_structs
3982 "java_name_of_struct: no java_structs entry corresponding to %s" typ
3984 let cols_of_struct typ =
3985 try List.assoc typ structs
3987 failwithf "cols_of_struct: unknown struct %s" typ
3989 let seq_of_test = function
3990 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3991 | TestOutputListOfDevices (s, _)
3992 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3993 | TestOutputTrue s | TestOutputFalse s
3994 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3995 | TestOutputStruct (s, _)
3996 | TestLastFail s -> s
3998 (* Handling for function flags. *)
3999 let protocol_limit_warning =
4000 "Because of the message protocol, there is a transfer limit
4001 of somewhere between 2MB and 4MB. To transfer large files you should use
4004 let danger_will_robinson =
4005 "B<This command is dangerous. Without careful use you
4006 can easily destroy all your data>."
4008 let deprecation_notice flags =
4011 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4013 sprintf "This function is deprecated.
4014 In new code, use the C<%s> call instead.
4016 Deprecated functions will not be removed from the API, but the
4017 fact that they are deprecated indicates that there are problems
4018 with correct use of these functions." alt in
4023 (* Check function names etc. for consistency. *)
4024 let check_functions () =
4025 let contains_uppercase str =
4026 let len = String.length str in
4028 if i >= len then false
4031 if c >= 'A' && c <= 'Z' then true
4038 (* Check function names. *)
4040 fun (name, _, _, _, _, _, _) ->
4041 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4042 failwithf "function name %s does not need 'guestfs' prefix" name;
4044 failwithf "function name is empty";
4045 if name.[0] < 'a' || name.[0] > 'z' then
4046 failwithf "function name %s must start with lowercase a-z" name;
4047 if String.contains name '-' then
4048 failwithf "function name %s should not contain '-', use '_' instead."
4052 (* Check function parameter/return names. *)
4054 fun (name, style, _, _, _, _, _) ->
4055 let check_arg_ret_name n =
4056 if contains_uppercase n then
4057 failwithf "%s param/ret %s should not contain uppercase chars"
4059 if String.contains n '-' || String.contains n '_' then
4060 failwithf "%s param/ret %s should not contain '-' or '_'"
4063 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;
4064 if n = "int" || n = "char" || n = "short" || n = "long" then
4065 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4066 if n = "i" || n = "n" then
4067 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4068 if n = "argv" || n = "args" then
4069 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4071 (* List Haskell, OCaml and C keywords here.
4072 * http://www.haskell.org/haskellwiki/Keywords
4073 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4074 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4075 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4076 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4077 * Omitting _-containing words, since they're handled above.
4078 * Omitting the OCaml reserved word, "val", is ok,
4079 * and saves us from renaming several parameters.
4082 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4083 "char"; "class"; "const"; "constraint"; "continue"; "data";
4084 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4085 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4086 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4087 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4088 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4089 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4090 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4091 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4092 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4093 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4094 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4095 "volatile"; "when"; "where"; "while";
4097 if List.mem n reserved then
4098 failwithf "%s has param/ret using reserved word %s" name n;
4101 (match fst style with
4103 | RInt n | RInt64 n | RBool n
4104 | RConstString n | RConstOptString n | RString n
4105 | RStringList n | RStruct (n, _) | RStructList (n, _)
4106 | RHashtable n | RBufferOut n ->
4107 check_arg_ret_name n
4109 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4112 (* Check short descriptions. *)
4114 fun (name, _, _, _, _, shortdesc, _) ->
4115 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4116 failwithf "short description of %s should begin with lowercase." name;
4117 let c = shortdesc.[String.length shortdesc-1] in
4118 if c = '\n' || c = '.' then
4119 failwithf "short description of %s should not end with . or \\n." name
4122 (* Check long dscriptions. *)
4124 fun (name, _, _, _, _, _, longdesc) ->
4125 if longdesc.[String.length longdesc-1] = '\n' then
4126 failwithf "long description of %s should not end with \\n." name
4129 (* Check proc_nrs. *)
4131 fun (name, _, proc_nr, _, _, _, _) ->
4132 if proc_nr <= 0 then
4133 failwithf "daemon function %s should have proc_nr > 0" name
4137 fun (name, _, proc_nr, _, _, _, _) ->
4138 if proc_nr <> -1 then
4139 failwithf "non-daemon function %s should have proc_nr -1" name
4140 ) non_daemon_functions;
4143 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4146 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4147 let rec loop = function
4150 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4152 | (name1,nr1) :: (name2,nr2) :: _ ->
4153 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4161 (* Ignore functions that have no tests. We generate a
4162 * warning when the user does 'make check' instead.
4164 | name, _, _, _, [], _, _ -> ()
4165 | name, _, _, _, tests, _, _ ->
4169 match seq_of_test test with
4171 failwithf "%s has a test containing an empty sequence" name
4172 | cmds -> List.map List.hd cmds
4174 let funcs = List.flatten funcs in
4176 let tested = List.mem name funcs in
4179 failwithf "function %s has tests but does not test itself" name
4182 (* 'pr' prints to the current output file. *)
4183 let chan = ref stdout
4184 let pr fs = ksprintf (output_string !chan) fs
4186 (* Generate a header block in a number of standard styles. *)
4187 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4188 type license = GPLv2 | LGPLv2
4190 let generate_header comment license =
4191 let c = match comment with
4192 | CStyle -> pr "/* "; " *"
4193 | HashStyle -> pr "# "; "#"
4194 | OCamlStyle -> pr "(* "; " *"
4195 | HaskellStyle -> pr "{- "; " " in
4196 pr "libguestfs generated file\n";
4197 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4198 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4200 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4204 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4205 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4206 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4207 pr "%s (at your option) any later version.\n" c;
4209 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4210 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4211 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4212 pr "%s GNU General Public License for more details.\n" c;
4214 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4215 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4216 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4219 pr "%s This library is free software; you can redistribute it and/or\n" c;
4220 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4221 pr "%s License as published by the Free Software Foundation; either\n" c;
4222 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4224 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4225 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4226 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4227 pr "%s Lesser General Public License for more details.\n" c;
4229 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4230 pr "%s License along with this library; if not, write to the Free Software\n" c;
4231 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4234 | CStyle -> pr " */\n"
4236 | OCamlStyle -> pr " *)\n"
4237 | HaskellStyle -> pr "-}\n"
4241 (* Start of main code generation functions below this line. *)
4243 (* Generate the pod documentation for the C API. *)
4244 let rec generate_actions_pod () =
4246 fun (shortname, style, _, flags, _, _, longdesc) ->
4247 if not (List.mem NotInDocs flags) then (
4248 let name = "guestfs_" ^ shortname in
4249 pr "=head2 %s\n\n" name;
4251 generate_prototype ~extern:false ~handle:"handle" name style;
4253 pr "%s\n\n" longdesc;
4254 (match fst style with
4256 pr "This function returns 0 on success or -1 on error.\n\n"
4258 pr "On error this function returns -1.\n\n"
4260 pr "On error this function returns -1.\n\n"
4262 pr "This function returns a C truth value on success or -1 on error.\n\n"
4264 pr "This function returns a string, or NULL on error.
4265 The string is owned by the guest handle and must I<not> be freed.\n\n"
4266 | RConstOptString _ ->
4267 pr "This function returns a string which may be NULL.
4268 There is way to return an error from this function.
4269 The string is owned by the guest handle and must I<not> be freed.\n\n"
4271 pr "This function returns a string, or NULL on error.
4272 I<The caller must free the returned string after use>.\n\n"
4274 pr "This function returns a NULL-terminated array of strings
4275 (like L<environ(3)>), or NULL if there was an error.
4276 I<The caller must free the strings and the array after use>.\n\n"
4277 | RStruct (_, typ) ->
4278 pr "This function returns a C<struct guestfs_%s *>,
4279 or NULL if there was an error.
4280 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4281 | RStructList (_, typ) ->
4282 pr "This function returns a C<struct guestfs_%s_list *>
4283 (see E<lt>guestfs-structs.hE<gt>),
4284 or NULL if there was an error.
4285 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4287 pr "This function returns a NULL-terminated array of
4288 strings, or NULL if there was an error.
4289 The array of strings will always have length C<2n+1>, where
4290 C<n> keys and values alternate, followed by the trailing NULL entry.
4291 I<The caller must free the strings and the array after use>.\n\n"
4293 pr "This function returns a buffer, or NULL on error.
4294 The size of the returned buffer is written to C<*size_r>.
4295 I<The caller must free the returned buffer after use>.\n\n"
4297 if List.mem ProtocolLimitWarning flags then
4298 pr "%s\n\n" protocol_limit_warning;
4299 if List.mem DangerWillRobinson flags then
4300 pr "%s\n\n" danger_will_robinson;
4301 match deprecation_notice flags with
4303 | Some txt -> pr "%s\n\n" txt
4305 ) all_functions_sorted
4307 and generate_structs_pod () =
4308 (* Structs documentation. *)
4311 pr "=head2 guestfs_%s\n" typ;
4313 pr " struct guestfs_%s {\n" typ;
4316 | name, FChar -> pr " char %s;\n" name
4317 | name, FUInt32 -> pr " uint32_t %s;\n" name
4318 | name, FInt32 -> pr " int32_t %s;\n" name
4319 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4320 | name, FInt64 -> pr " int64_t %s;\n" name
4321 | name, FString -> pr " char *%s;\n" name
4323 pr " /* The next two fields describe a byte array. */\n";
4324 pr " uint32_t %s_len;\n" name;
4325 pr " char *%s;\n" name
4327 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4328 pr " char %s[32];\n" name
4329 | name, FOptPercent ->
4330 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4331 pr " float %s;\n" name
4335 pr " struct guestfs_%s_list {\n" typ;
4336 pr " uint32_t len; /* Number of elements in list. */\n";
4337 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4340 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4341 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4346 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4347 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4349 * We have to use an underscore instead of a dash because otherwise
4350 * rpcgen generates incorrect code.
4352 * This header is NOT exported to clients, but see also generate_structs_h.
4354 and generate_xdr () =
4355 generate_header CStyle LGPLv2;
4357 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4358 pr "typedef string str<>;\n";
4361 (* Internal structures. *)
4365 pr "struct guestfs_int_%s {\n" typ;
4367 | name, FChar -> pr " char %s;\n" name
4368 | name, FString -> pr " string %s<>;\n" name
4369 | name, FBuffer -> pr " opaque %s<>;\n" name
4370 | name, FUUID -> pr " opaque %s[32];\n" name
4371 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4372 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4373 | name, FOptPercent -> pr " float %s;\n" name
4377 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4382 fun (shortname, style, _, _, _, _, _) ->
4383 let name = "guestfs_" ^ shortname in
4385 (match snd style with
4388 pr "struct %s_args {\n" name;
4391 | Pathname n | Device n | Dev_or_Path n | String n -> pr " string %s<>;\n" n
4392 | OptString n -> pr " str *%s;\n" n
4393 | StringList n | DeviceList n -> pr " str %s<>;\n" n
4394 | Bool n -> pr " bool %s;\n" n
4395 | Int n -> pr " int %s;\n" n
4396 | FileIn _ | FileOut _ -> ()
4400 (match fst style with
4403 pr "struct %s_ret {\n" name;
4407 pr "struct %s_ret {\n" name;
4408 pr " hyper %s;\n" n;
4411 pr "struct %s_ret {\n" name;
4414 | RConstString _ | RConstOptString _ ->
4415 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4417 pr "struct %s_ret {\n" name;
4418 pr " string %s<>;\n" n;
4421 pr "struct %s_ret {\n" name;
4422 pr " str %s<>;\n" n;
4424 | RStruct (n, typ) ->
4425 pr "struct %s_ret {\n" name;
4426 pr " guestfs_int_%s %s;\n" typ n;
4428 | RStructList (n, typ) ->
4429 pr "struct %s_ret {\n" name;
4430 pr " guestfs_int_%s_list %s;\n" typ n;
4433 pr "struct %s_ret {\n" name;
4434 pr " str %s<>;\n" n;
4437 pr "struct %s_ret {\n" name;
4438 pr " opaque %s<>;\n" n;
4443 (* Table of procedure numbers. *)
4444 pr "enum guestfs_procedure {\n";
4446 fun (shortname, _, proc_nr, _, _, _, _) ->
4447 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4449 pr " GUESTFS_PROC_NR_PROCS\n";
4453 (* Having to choose a maximum message size is annoying for several
4454 * reasons (it limits what we can do in the API), but it (a) makes
4455 * the protocol a lot simpler, and (b) provides a bound on the size
4456 * of the daemon which operates in limited memory space. For large
4457 * file transfers you should use FTP.
4459 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4462 (* Message header, etc. *)
4464 /* The communication protocol is now documented in the guestfs(3)
4468 const GUESTFS_PROGRAM = 0x2000F5F5;
4469 const GUESTFS_PROTOCOL_VERSION = 1;
4471 /* These constants must be larger than any possible message length. */
4472 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4473 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4475 enum guestfs_message_direction {
4476 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4477 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4480 enum guestfs_message_status {
4481 GUESTFS_STATUS_OK = 0,
4482 GUESTFS_STATUS_ERROR = 1
4485 const GUESTFS_ERROR_LEN = 256;
4487 struct guestfs_message_error {
4488 string error_message<GUESTFS_ERROR_LEN>;
4491 struct guestfs_message_header {
4492 unsigned prog; /* GUESTFS_PROGRAM */
4493 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4494 guestfs_procedure proc; /* GUESTFS_PROC_x */
4495 guestfs_message_direction direction;
4496 unsigned serial; /* message serial number */
4497 guestfs_message_status status;
4500 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4502 struct guestfs_chunk {
4503 int cancel; /* if non-zero, transfer is cancelled */
4504 /* data size is 0 bytes if the transfer has finished successfully */
4505 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4509 (* Generate the guestfs-structs.h file. *)
4510 and generate_structs_h () =
4511 generate_header CStyle LGPLv2;
4513 (* This is a public exported header file containing various
4514 * structures. The structures are carefully written to have
4515 * exactly the same in-memory format as the XDR structures that
4516 * we use on the wire to the daemon. The reason for creating
4517 * copies of these structures here is just so we don't have to
4518 * export the whole of guestfs_protocol.h (which includes much
4519 * unrelated and XDR-dependent stuff that we don't want to be
4520 * public, or required by clients).
4522 * To reiterate, we will pass these structures to and from the
4523 * client with a simple assignment or memcpy, so the format
4524 * must be identical to what rpcgen / the RFC defines.
4527 (* Public structures. *)
4530 pr "struct guestfs_%s {\n" typ;
4533 | name, FChar -> pr " char %s;\n" name
4534 | name, FString -> pr " char *%s;\n" name
4536 pr " uint32_t %s_len;\n" name;
4537 pr " char *%s;\n" name
4538 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4539 | name, FUInt32 -> pr " uint32_t %s;\n" name
4540 | name, FInt32 -> pr " int32_t %s;\n" name
4541 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4542 | name, FInt64 -> pr " int64_t %s;\n" name
4543 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4547 pr "struct guestfs_%s_list {\n" typ;
4548 pr " uint32_t len;\n";
4549 pr " struct guestfs_%s *val;\n" typ;
4552 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4553 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4557 (* Generate the guestfs-actions.h file. *)
4558 and generate_actions_h () =
4559 generate_header CStyle LGPLv2;
4561 fun (shortname, style, _, _, _, _, _) ->
4562 let name = "guestfs_" ^ shortname in
4563 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4567 (* Generate the guestfs-internal-actions.h file. *)
4568 and generate_internal_actions_h () =
4569 generate_header CStyle LGPLv2;
4571 fun (shortname, style, _, _, _, _, _) ->
4572 let name = "guestfs__" ^ shortname in
4573 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4575 ) non_daemon_functions
4577 (* Generate the client-side dispatch stubs. *)
4578 and generate_client_actions () =
4579 generate_header CStyle LGPLv2;
4585 #include \"guestfs.h\"
4586 #include \"guestfs-internal-actions.h\"
4587 #include \"guestfs_protocol.h\"
4589 #define error guestfs_error
4590 //#define perrorf guestfs_perrorf
4591 //#define safe_malloc guestfs_safe_malloc
4592 #define safe_realloc guestfs_safe_realloc
4593 //#define safe_strdup guestfs_safe_strdup
4594 #define safe_memdup guestfs_safe_memdup
4596 /* Check the return message from a call for validity. */
4598 check_reply_header (guestfs_h *g,
4599 const struct guestfs_message_header *hdr,
4600 unsigned int proc_nr, unsigned int serial)
4602 if (hdr->prog != GUESTFS_PROGRAM) {
4603 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4606 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4607 error (g, \"wrong protocol version (%%d/%%d)\",
4608 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4611 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4612 error (g, \"unexpected message direction (%%d/%%d)\",
4613 hdr->direction, GUESTFS_DIRECTION_REPLY);
4616 if (hdr->proc != proc_nr) {
4617 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4620 if (hdr->serial != serial) {
4621 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4628 /* Check we are in the right state to run a high-level action. */
4630 check_state (guestfs_h *g, const char *caller)
4632 if (!guestfs__is_ready (g)) {
4633 if (guestfs__is_config (g) || guestfs__is_launching (g))
4634 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4637 error (g, \"%%s called from the wrong state, %%d != READY\",
4638 caller, guestfs__get_state (g));
4646 (* Generate code to generate guestfish call traces. *)
4647 let trace_call shortname style =
4648 pr " if (guestfs__get_trace (g)) {\n";
4651 List.exists (function
4652 | StringList _ | DeviceList _ -> true
4653 | _ -> false) (snd style) in
4659 pr " printf (\"%s\");\n" shortname;
4662 | String n (* strings *)
4668 (* guestfish doesn't support string escaping, so neither do we *)
4669 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
4670 | OptString n -> (* string option *)
4671 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4672 pr " else printf (\" null\");\n"
4674 | DeviceList n -> (* string list *)
4675 pr " putchar (' ');\n";
4676 pr " putchar ('\"');\n";
4677 pr " for (i = 0; %s[i]; ++i) {\n" n;
4678 pr " if (i > 0) putchar (' ');\n";
4679 pr " fputs (%s[i], stdout);\n" n;
4681 pr " putchar ('\"');\n";
4682 | Bool n -> (* boolean *)
4683 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
4684 | Int n -> (* int *)
4685 pr " printf (\" %%d\", %s);\n" n
4687 pr " putchar ('\\n');\n";
4692 (* For non-daemon functions, generate a wrapper around each function. *)
4694 fun (shortname, style, _, _, _, _, _) ->
4695 let name = "guestfs_" ^ shortname in
4697 generate_prototype ~extern:false ~semicolon:false ~newline:true
4698 ~handle:"g" name style;
4700 trace_call shortname style;
4701 pr " return guestfs__%s " shortname;
4702 generate_c_call_args ~handle:"g" style;
4706 ) non_daemon_functions;
4708 (* Client-side stubs for each function. *)
4710 fun (shortname, style, _, _, _, _, _) ->
4711 let name = "guestfs_" ^ shortname in
4713 (* Generate the action stub. *)
4714 generate_prototype ~extern:false ~semicolon:false ~newline:true
4715 ~handle:"g" name style;
4718 match fst style with
4719 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4720 | RConstString _ | RConstOptString _ ->
4721 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4722 | RString _ | RStringList _
4723 | RStruct _ | RStructList _
4724 | RHashtable _ | RBufferOut _ ->
4729 (match snd style with
4731 | _ -> pr " struct %s_args args;\n" name
4734 pr " guestfs_message_header hdr;\n";
4735 pr " guestfs_message_error err;\n";
4737 match fst style with
4739 | RConstString _ | RConstOptString _ ->
4740 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4742 | RBool _ | RString _ | RStringList _
4743 | RStruct _ | RStructList _
4744 | RHashtable _ | RBufferOut _ ->
4745 pr " struct %s_ret ret;\n" name;
4748 pr " int serial;\n";
4751 trace_call shortname style;
4752 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4753 pr " guestfs___set_busy (g);\n";
4756 (* Send the main header and arguments. *)
4757 (match snd style with
4759 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4760 (String.uppercase shortname)
4764 | Pathname n | Device n | Dev_or_Path n | String n ->
4765 pr " args.%s = (char *) %s;\n" n n
4767 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
4768 | StringList n | DeviceList n ->
4769 pr " args.%s.%s_val = (char **) %s;\n" n n n;
4770 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4772 pr " args.%s = %s;\n" n n
4774 pr " args.%s = %s;\n" n n
4775 | FileIn _ | FileOut _ -> ()
4777 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4778 (String.uppercase shortname);
4779 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4782 pr " if (serial == -1) {\n";
4783 pr " guestfs___end_busy (g);\n";
4784 pr " return %s;\n" error_code;
4788 (* Send any additional files (FileIn) requested. *)
4789 let need_read_reply_label = ref false in
4793 pr " r = guestfs___send_file (g, %s);\n" n;
4794 pr " if (r == -1) {\n";
4795 pr " guestfs___end_busy (g);\n";
4796 pr " return %s;\n" error_code;
4798 pr " if (r == -2) /* daemon cancelled */\n";
4799 pr " goto read_reply;\n";
4800 need_read_reply_label := true;
4805 (* Wait for the reply from the remote end. *)
4806 if !need_read_reply_label then pr " read_reply:\n";
4807 pr " memset (&hdr, 0, sizeof hdr);\n";
4808 pr " memset (&err, 0, sizeof err);\n";
4809 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
4811 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
4815 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
4818 pr " if (r == -1) {\n";
4819 pr " guestfs___end_busy (g);\n";
4820 pr " return %s;\n" error_code;
4824 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4825 (String.uppercase shortname);
4826 pr " guestfs___end_busy (g);\n";
4827 pr " return %s;\n" error_code;
4831 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
4832 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
4833 pr " free (err.error_message);\n";
4834 pr " guestfs___end_busy (g);\n";
4835 pr " return %s;\n" error_code;
4839 (* Expecting to receive further files (FileOut)? *)
4843 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
4844 pr " guestfs___end_busy (g);\n";
4845 pr " return %s;\n" error_code;
4851 pr " guestfs___end_busy (g);\n";
4853 (match fst style with
4854 | RErr -> pr " return 0;\n"
4855 | RInt n | RInt64 n | RBool n ->
4856 pr " return ret.%s;\n" n
4857 | RConstString _ | RConstOptString _ ->
4858 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4860 pr " return ret.%s; /* caller will free */\n" n
4861 | RStringList n | RHashtable n ->
4862 pr " /* caller will free this, but we need to add a NULL entry */\n";
4863 pr " ret.%s.%s_val =\n" n n;
4864 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
4865 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
4867 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
4868 pr " return ret.%s.%s_val;\n" n n
4870 pr " /* caller will free this */\n";
4871 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4872 | RStructList (n, _) ->
4873 pr " /* caller will free this */\n";
4874 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4876 pr " *size_r = ret.%s.%s_len;\n" n n;
4877 pr " return ret.%s.%s_val; /* caller will free */\n" n n
4883 (* Functions to free structures. *)
4884 pr "/* Structure-freeing functions. These rely on the fact that the\n";
4885 pr " * structure format is identical to the XDR format. See note in\n";
4886 pr " * generator.ml.\n";
4893 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4895 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4901 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4903 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4910 (* Generate daemon/actions.h. *)
4911 and generate_daemon_actions_h () =
4912 generate_header CStyle GPLv2;
4914 pr "#include \"../src/guestfs_protocol.h\"\n";
4918 fun (name, style, _, _, _, _, _) ->
4920 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4924 (* Generate the server-side stubs. *)
4925 and generate_daemon_actions () =
4926 generate_header CStyle GPLv2;
4928 pr "#include <config.h>\n";
4930 pr "#include <stdio.h>\n";
4931 pr "#include <stdlib.h>\n";
4932 pr "#include <string.h>\n";
4933 pr "#include <inttypes.h>\n";
4934 pr "#include <ctype.h>\n";
4935 pr "#include <rpc/types.h>\n";
4936 pr "#include <rpc/xdr.h>\n";
4938 pr "#include \"daemon.h\"\n";
4939 pr "#include \"../src/guestfs_protocol.h\"\n";
4940 pr "#include \"actions.h\"\n";
4944 fun (name, style, _, _, _, _, _) ->
4945 (* Generate server-side stubs. *)
4946 pr "static void %s_stub (XDR *xdr_in)\n" name;
4949 match fst style with
4950 | RErr | RInt _ -> pr " int r;\n"; "-1"
4951 | RInt64 _ -> pr " int64_t r;\n"; "-1"
4952 | RBool _ -> pr " int r;\n"; "-1"
4953 | RConstString _ | RConstOptString _ ->
4954 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4955 | RString _ -> pr " char *r;\n"; "NULL"
4956 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
4957 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
4958 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
4960 pr " size_t size;\n";
4964 (match snd style with
4967 pr " struct guestfs_%s_args args;\n" name;
4970 | Device n | Dev_or_Path n
4973 | OptString n -> pr " char *%s;\n" n
4974 | StringList n | DeviceList n -> pr " char **%s;\n" n
4975 | Bool n -> pr " int %s;\n" n
4976 | Int n -> pr " int %s;\n" n
4977 | FileIn _ | FileOut _ -> ()
4982 (match snd style with
4985 pr " memset (&args, 0, sizeof args);\n";
4987 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4988 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4992 pr " char *%s = args.%s;\n" n n
4994 let pr_list_handling_code n =
4995 pr " %s = realloc (args.%s.%s_val,\n" n n n;
4996 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4997 pr " if (%s == NULL) {\n" n;
4998 pr " reply_with_perror (\"realloc\");\n";
5001 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5002 pr " args.%s.%s_val = %s;\n" n n n;
5008 pr " ABS_PATH (%s, goto done);\n" n;
5011 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5014 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5015 | String n -> pr_args n
5016 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5018 pr_list_handling_code n;
5020 pr_list_handling_code n;
5021 pr " /* Ensure that each is a device,\n";
5022 pr " * and perform device name translation. */\n";
5023 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5024 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5026 | Bool n -> pr " %s = args.%s;\n" n n
5027 | Int n -> pr " %s = args.%s;\n" n n
5028 | FileIn _ | FileOut _ -> ()
5034 (* this is used at least for do_equal *)
5035 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5036 (* Emit NEED_ROOT just once, even when there are two or
5037 more Pathname args *)
5038 pr " NEED_ROOT (goto done);\n";
5041 (* Don't want to call the impl with any FileIn or FileOut
5042 * parameters, since these go "outside" the RPC protocol.
5045 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5047 pr " r = do_%s " name;
5048 generate_c_call_args (fst style, args');
5051 pr " if (r == %s)\n" error_code;
5052 pr " /* do_%s has already called reply_with_error */\n" name;
5056 (* If there are any FileOut parameters, then the impl must
5057 * send its own reply.
5060 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5062 pr " /* do_%s has already sent a reply */\n" name
5064 match fst style with
5065 | RErr -> pr " reply (NULL, NULL);\n"
5066 | RInt n | RInt64 n | RBool n ->
5067 pr " struct guestfs_%s_ret ret;\n" name;
5068 pr " ret.%s = r;\n" n;
5069 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5071 | RConstString _ | RConstOptString _ ->
5072 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5074 pr " struct guestfs_%s_ret ret;\n" name;
5075 pr " ret.%s = r;\n" n;
5076 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5079 | RStringList n | RHashtable n ->
5080 pr " struct guestfs_%s_ret ret;\n" name;
5081 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5082 pr " ret.%s.%s_val = r;\n" n n;
5083 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5085 pr " free_strings (r);\n"
5087 pr " struct guestfs_%s_ret ret;\n" name;
5088 pr " ret.%s = *r;\n" n;
5089 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5091 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5093 | RStructList (n, _) ->
5094 pr " struct guestfs_%s_ret ret;\n" name;
5095 pr " ret.%s = *r;\n" n;
5096 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5098 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5101 pr " struct guestfs_%s_ret ret;\n" name;
5102 pr " ret.%s.%s_val = r;\n" n n;
5103 pr " ret.%s.%s_len = size;\n" n n;
5104 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5109 (* Free the args. *)
5110 (match snd style with
5115 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5122 (* Dispatch function. *)
5123 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5125 pr " switch (proc_nr) {\n";
5128 fun (name, style, _, _, _, _, _) ->
5129 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5130 pr " %s_stub (xdr_in);\n" name;
5135 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";
5140 (* LVM columns and tokenization functions. *)
5141 (* XXX This generates crap code. We should rethink how we
5147 pr "static const char *lvm_%s_cols = \"%s\";\n"
5148 typ (String.concat "," (List.map fst cols));
5151 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5153 pr " char *tok, *p, *next;\n";
5157 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5160 pr " if (!str) {\n";
5161 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5164 pr " if (!*str || isspace (*str)) {\n";
5165 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5170 fun (name, coltype) ->
5171 pr " if (!tok) {\n";
5172 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5175 pr " p = strchrnul (tok, ',');\n";
5176 pr " if (*p) next = p+1; else next = NULL;\n";
5177 pr " *p = '\\0';\n";
5180 pr " r->%s = strdup (tok);\n" name;
5181 pr " if (r->%s == NULL) {\n" name;
5182 pr " perror (\"strdup\");\n";
5186 pr " for (i = j = 0; i < 32; ++j) {\n";
5187 pr " if (tok[j] == '\\0') {\n";
5188 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5190 pr " } else if (tok[j] != '-')\n";
5191 pr " r->%s[i++] = tok[j];\n" name;
5194 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5195 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5199 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5200 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5204 pr " if (tok[0] == '\\0')\n";
5205 pr " r->%s = -1;\n" name;
5206 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5207 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5210 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5211 assert false (* can never be an LVM column *)
5213 pr " tok = next;\n";
5216 pr " if (tok != NULL) {\n";
5217 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5224 pr "guestfs_int_lvm_%s_list *\n" typ;
5225 pr "parse_command_line_%ss (void)\n" typ;
5227 pr " char *out, *err;\n";
5228 pr " char *p, *pend;\n";
5230 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
5231 pr " void *newp;\n";
5233 pr " ret = malloc (sizeof *ret);\n";
5234 pr " if (!ret) {\n";
5235 pr " reply_with_perror (\"malloc\");\n";
5236 pr " return NULL;\n";
5239 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5240 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5242 pr " r = command (&out, &err,\n";
5243 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
5244 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5245 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5246 pr " if (r == -1) {\n";
5247 pr " reply_with_error (\"%%s\", err);\n";
5248 pr " free (out);\n";
5249 pr " free (err);\n";
5250 pr " free (ret);\n";
5251 pr " return NULL;\n";
5254 pr " free (err);\n";
5256 pr " /* Tokenize each line of the output. */\n";
5259 pr " while (p) {\n";
5260 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
5261 pr " if (pend) {\n";
5262 pr " *pend = '\\0';\n";
5266 pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
5269 pr " if (!*p) { /* Empty line? Skip it. */\n";
5274 pr " /* Allocate some space to store this next entry. */\n";
5275 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5276 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5277 pr " if (newp == NULL) {\n";
5278 pr " reply_with_perror (\"realloc\");\n";
5279 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5280 pr " free (ret);\n";
5281 pr " free (out);\n";
5282 pr " return NULL;\n";
5284 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5286 pr " /* Tokenize the next entry. */\n";
5287 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5288 pr " if (r == -1) {\n";
5289 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5290 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5291 pr " free (ret);\n";
5292 pr " free (out);\n";
5293 pr " return NULL;\n";
5300 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5302 pr " free (out);\n";
5303 pr " return ret;\n";
5306 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5308 (* Generate a list of function names, for debugging in the daemon.. *)
5309 and generate_daemon_names () =
5310 generate_header CStyle GPLv2;
5312 pr "#include <config.h>\n";
5314 pr "#include \"daemon.h\"\n";
5317 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5318 pr "const char *function_names[] = {\n";
5320 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5324 (* Generate the tests. *)
5325 and generate_tests () =
5326 generate_header CStyle GPLv2;
5333 #include <sys/types.h>
5336 #include \"guestfs.h\"
5338 static guestfs_h *g;
5339 static int suppress_error = 0;
5341 static void print_error (guestfs_h *g, void *data, const char *msg)
5343 if (!suppress_error)
5344 fprintf (stderr, \"%%s\\n\", msg);
5347 /* FIXME: nearly identical code appears in fish.c */
5348 static void print_strings (char *const *argv)
5352 for (argc = 0; argv[argc] != NULL; ++argc)
5353 printf (\"\\t%%s\\n\", argv[argc]);
5357 static void print_table (char const *const *argv)
5361 for (i = 0; argv[i] != NULL; i += 2)
5362 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5368 (* Generate a list of commands which are not tested anywhere. *)
5369 pr "static void no_test_warnings (void)\n";
5372 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5374 fun (_, _, _, _, tests, _, _) ->
5375 let tests = filter_map (
5377 | (_, (Always|If _|Unless _), test) -> Some test
5378 | (_, Disabled, _) -> None
5380 let seq = List.concat (List.map seq_of_test tests) in
5381 let cmds_tested = List.map List.hd seq in
5382 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5386 fun (name, _, _, _, _, _, _) ->
5387 if not (Hashtbl.mem hash name) then
5388 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5394 (* Generate the actual tests. Note that we generate the tests
5395 * in reverse order, deliberately, so that (in general) the
5396 * newest tests run first. This makes it quicker and easier to
5401 fun (name, _, _, _, tests, _, _) ->
5402 mapi (generate_one_test name) tests
5403 ) (List.rev all_functions) in
5404 let test_names = List.concat test_names in
5405 let nr_tests = List.length test_names in
5408 int main (int argc, char *argv[])
5411 unsigned long int n_failed = 0;
5412 const char *filename;
5414 int nr_tests, test_num = 0;
5416 setbuf (stdout, NULL);
5418 no_test_warnings ();
5420 g = guestfs_create ();
5422 printf (\"guestfs_create FAILED\\n\");
5426 guestfs_set_error_handler (g, print_error, NULL);
5428 guestfs_set_path (g, \"../appliance\");
5430 filename = \"test1.img\";
5431 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5436 if (lseek (fd, %d, SEEK_SET) == -1) {
5442 if (write (fd, &c, 1) == -1) {
5448 if (close (fd) == -1) {
5453 if (guestfs_add_drive (g, filename) == -1) {
5454 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5458 filename = \"test2.img\";
5459 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5464 if (lseek (fd, %d, SEEK_SET) == -1) {
5470 if (write (fd, &c, 1) == -1) {
5476 if (close (fd) == -1) {
5481 if (guestfs_add_drive (g, filename) == -1) {
5482 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5486 filename = \"test3.img\";
5487 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5492 if (lseek (fd, %d, SEEK_SET) == -1) {
5498 if (write (fd, &c, 1) == -1) {
5504 if (close (fd) == -1) {
5509 if (guestfs_add_drive (g, filename) == -1) {
5510 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5514 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5515 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5519 if (guestfs_launch (g) == -1) {
5520 printf (\"guestfs_launch FAILED\\n\");
5524 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5527 /* Cancel previous alarm. */
5532 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5536 pr " test_num++;\n";
5537 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5538 pr " if (%s () == -1) {\n" test_name;
5539 pr " printf (\"%s FAILED\\n\");\n" test_name;
5540 pr " n_failed++;\n";
5545 pr " guestfs_close (g);\n";
5546 pr " unlink (\"test1.img\");\n";
5547 pr " unlink (\"test2.img\");\n";
5548 pr " unlink (\"test3.img\");\n";
5551 pr " if (n_failed > 0) {\n";
5552 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5560 and generate_one_test name i (init, prereq, test) =
5561 let test_name = sprintf "test_%s_%d" name i in
5564 static int %s_skip (void)
5568 str = getenv (\"TEST_ONLY\");
5570 return strstr (str, \"%s\") == NULL;
5571 str = getenv (\"SKIP_%s\");
5572 if (str && strcmp (str, \"1\") == 0) return 1;
5573 str = getenv (\"SKIP_TEST_%s\");
5574 if (str && strcmp (str, \"1\") == 0) return 1;
5578 " test_name name (String.uppercase test_name) (String.uppercase name);
5581 | Disabled | Always -> ()
5582 | If code | Unless code ->
5583 pr "static int %s_prereq (void)\n" test_name;
5591 static int %s (void)
5594 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5598 " test_name test_name test_name;
5602 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5604 pr " if (! %s_prereq ()) {\n" test_name;
5605 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5609 generate_one_test_body name i test_name init test;
5611 pr " if (%s_prereq ()) {\n" test_name;
5612 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5616 generate_one_test_body name i test_name init test;
5618 generate_one_test_body name i test_name init test
5626 and generate_one_test_body name i test_name init test =
5628 | InitNone (* XXX at some point, InitNone and InitEmpty became
5629 * folded together as the same thing. Really we should
5630 * make InitNone do nothing at all, but the tests may
5631 * need to be checked to make sure this is OK.
5634 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5635 List.iter (generate_test_command_call test_name)
5636 [["blockdev_setrw"; "/dev/sda"];
5640 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5641 List.iter (generate_test_command_call test_name)
5642 [["blockdev_setrw"; "/dev/sda"];
5645 ["sfdiskM"; "/dev/sda"; ","]]
5647 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5648 List.iter (generate_test_command_call test_name)
5649 [["blockdev_setrw"; "/dev/sda"];
5652 ["sfdiskM"; "/dev/sda"; ","];
5653 ["mkfs"; "ext2"; "/dev/sda1"];
5654 ["mount"; "/dev/sda1"; "/"]]
5655 | InitBasicFSonLVM ->
5656 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5658 List.iter (generate_test_command_call test_name)
5659 [["blockdev_setrw"; "/dev/sda"];
5662 ["sfdiskM"; "/dev/sda"; ","];
5663 ["pvcreate"; "/dev/sda1"];
5664 ["vgcreate"; "VG"; "/dev/sda1"];
5665 ["lvcreate"; "LV"; "VG"; "8"];
5666 ["mkfs"; "ext2"; "/dev/VG/LV"];
5667 ["mount"; "/dev/VG/LV"; "/"]]
5669 pr " /* InitISOFS for %s */\n" test_name;
5670 List.iter (generate_test_command_call test_name)
5671 [["blockdev_setrw"; "/dev/sda"];
5674 ["mount_ro"; "/dev/sdd"; "/"]]
5677 let get_seq_last = function
5679 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5682 let seq = List.rev seq in
5683 List.rev (List.tl seq), List.hd seq
5688 pr " /* TestRun for %s (%d) */\n" name i;
5689 List.iter (generate_test_command_call test_name) seq
5690 | TestOutput (seq, expected) ->
5691 pr " /* TestOutput for %s (%d) */\n" name i;
5692 pr " const char *expected = \"%s\";\n" (c_quote expected);
5693 let seq, last = get_seq_last seq in
5695 pr " if (strcmp (r, expected) != 0) {\n";
5696 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5700 List.iter (generate_test_command_call test_name) seq;
5701 generate_test_command_call ~test test_name last
5702 | TestOutputList (seq, expected) ->
5703 pr " /* TestOutputList for %s (%d) */\n" name i;
5704 let seq, last = get_seq_last seq in
5708 pr " if (!r[%d]) {\n" i;
5709 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5710 pr " print_strings (r);\n";
5714 pr " const char *expected = \"%s\";\n" (c_quote str);
5715 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5716 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5721 pr " if (r[%d] != NULL) {\n" (List.length expected);
5722 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5724 pr " print_strings (r);\n";
5728 List.iter (generate_test_command_call test_name) seq;
5729 generate_test_command_call ~test test_name last
5730 | TestOutputListOfDevices (seq, expected) ->
5731 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
5732 let seq, last = get_seq_last seq in
5736 pr " if (!r[%d]) {\n" i;
5737 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5738 pr " print_strings (r);\n";
5742 pr " const char *expected = \"%s\";\n" (c_quote str);
5743 pr " r[%d][5] = 's';\n" i;
5744 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5745 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5750 pr " if (r[%d] != NULL) {\n" (List.length expected);
5751 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5753 pr " print_strings (r);\n";
5757 List.iter (generate_test_command_call test_name) seq;
5758 generate_test_command_call ~test test_name last
5759 | TestOutputInt (seq, expected) ->
5760 pr " /* TestOutputInt for %s (%d) */\n" name i;
5761 let seq, last = get_seq_last seq in
5763 pr " if (r != %d) {\n" expected;
5764 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5770 List.iter (generate_test_command_call test_name) seq;
5771 generate_test_command_call ~test test_name last
5772 | TestOutputIntOp (seq, op, expected) ->
5773 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
5774 let seq, last = get_seq_last seq in
5776 pr " if (! (r %s %d)) {\n" op expected;
5777 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5778 test_name op expected;
5783 List.iter (generate_test_command_call test_name) seq;
5784 generate_test_command_call ~test test_name last
5785 | TestOutputTrue seq ->
5786 pr " /* TestOutputTrue for %s (%d) */\n" name i;
5787 let seq, last = get_seq_last seq in
5790 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5795 List.iter (generate_test_command_call test_name) seq;
5796 generate_test_command_call ~test test_name last
5797 | TestOutputFalse seq ->
5798 pr " /* TestOutputFalse for %s (%d) */\n" name i;
5799 let seq, last = get_seq_last seq in
5802 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5807 List.iter (generate_test_command_call test_name) seq;
5808 generate_test_command_call ~test test_name last
5809 | TestOutputLength (seq, expected) ->
5810 pr " /* TestOutputLength for %s (%d) */\n" name i;
5811 let seq, last = get_seq_last seq in
5814 pr " for (j = 0; j < %d; ++j)\n" expected;
5815 pr " if (r[j] == NULL) {\n";
5816 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
5818 pr " print_strings (r);\n";
5821 pr " if (r[j] != NULL) {\n";
5822 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
5824 pr " print_strings (r);\n";
5828 List.iter (generate_test_command_call test_name) seq;
5829 generate_test_command_call ~test test_name last
5830 | TestOutputBuffer (seq, expected) ->
5831 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
5832 pr " const char *expected = \"%s\";\n" (c_quote expected);
5833 let seq, last = get_seq_last seq in
5834 let len = String.length expected in
5836 pr " if (size != %d) {\n" len;
5837 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5840 pr " if (strncmp (r, expected, size) != 0) {\n";
5841 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5845 List.iter (generate_test_command_call test_name) seq;
5846 generate_test_command_call ~test test_name last
5847 | TestOutputStruct (seq, checks) ->
5848 pr " /* TestOutputStruct for %s (%d) */\n" name i;
5849 let seq, last = get_seq_last seq in
5853 | CompareWithInt (field, expected) ->
5854 pr " if (r->%s != %d) {\n" field expected;
5855 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5856 test_name field expected;
5857 pr " (int) r->%s);\n" field;
5860 | CompareWithIntOp (field, op, expected) ->
5861 pr " if (!(r->%s %s %d)) {\n" field op expected;
5862 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5863 test_name field op expected;
5864 pr " (int) r->%s);\n" field;
5867 | CompareWithString (field, expected) ->
5868 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5869 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5870 test_name field expected;
5871 pr " r->%s);\n" field;
5874 | CompareFieldsIntEq (field1, field2) ->
5875 pr " if (r->%s != r->%s) {\n" field1 field2;
5876 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5877 test_name field1 field2;
5878 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
5881 | CompareFieldsStrEq (field1, field2) ->
5882 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5883 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5884 test_name field1 field2;
5885 pr " r->%s, r->%s);\n" field1 field2;
5890 List.iter (generate_test_command_call test_name) seq;
5891 generate_test_command_call ~test test_name last
5892 | TestLastFail seq ->
5893 pr " /* TestLastFail for %s (%d) */\n" name i;
5894 let seq, last = get_seq_last seq in
5895 List.iter (generate_test_command_call test_name) seq;
5896 generate_test_command_call test_name ~expect_error:true last
5898 (* Generate the code to run a command, leaving the result in 'r'.
5899 * If you expect to get an error then you should set expect_error:true.
5901 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5903 | [] -> assert false
5905 (* Look up the command to find out what args/ret it has. *)
5908 let _, style, _, _, _, _, _ =
5909 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5912 failwithf "%s: in test, command %s was not found" test_name name in
5914 if List.length (snd style) <> List.length args then
5915 failwithf "%s: in test, wrong number of args given to %s"
5922 | OptString n, "NULL" -> ()
5925 | Dev_or_Path n, arg
5927 | OptString n, arg ->
5928 pr " const char *%s = \"%s\";\n" n (c_quote arg);
5931 | FileIn _, _ | FileOut _, _ -> ()
5932 | StringList n, arg | DeviceList n, arg ->
5933 let strs = string_split " " arg in
5936 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
5938 pr " const char *const %s[] = {\n" n;
5940 fun i _ -> pr " %s_%d,\n" n i
5944 ) (List.combine (snd style) args);
5947 match fst style with
5948 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
5949 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5950 | RConstString _ | RConstOptString _ ->
5951 pr " const char *r;\n"; "NULL"
5952 | RString _ -> pr " char *r;\n"; "NULL"
5953 | RStringList _ | RHashtable _ ->
5957 | RStruct (_, typ) ->
5958 pr " struct guestfs_%s *r;\n" typ; "NULL"
5959 | RStructList (_, typ) ->
5960 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
5963 pr " size_t size;\n";
5966 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
5967 pr " r = guestfs_%s (g" name;
5969 (* Generate the parameters. *)
5972 | OptString _, "NULL" -> pr ", NULL"
5974 | Device n, _ | Dev_or_Path n, _
5978 | FileIn _, arg | FileOut _, arg ->
5979 pr ", \"%s\"" (c_quote arg)
5980 | StringList n, _ | DeviceList n, _ ->
5981 pr ", (char **) %s" n
5984 try int_of_string arg
5985 with Failure "int_of_string" ->
5986 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5989 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5990 ) (List.combine (snd style) args);
5992 (match fst style with
5993 | RBufferOut _ -> pr ", &size"
5999 if not expect_error then
6000 pr " if (r == %s)\n" error_code
6002 pr " if (r != %s)\n" error_code;
6005 (* Insert the test code. *)
6011 (match fst style with
6012 | RErr | RInt _ | RInt64 _ | RBool _
6013 | RConstString _ | RConstOptString _ -> ()
6014 | RString _ | RBufferOut _ -> pr " free (r);\n"
6015 | RStringList _ | RHashtable _ ->
6016 pr " for (i = 0; r[i] != NULL; ++i)\n";
6017 pr " free (r[i]);\n";
6019 | RStruct (_, typ) ->
6020 pr " guestfs_free_%s (r);\n" typ
6021 | RStructList (_, typ) ->
6022 pr " guestfs_free_%s_list (r);\n" typ
6028 let str = replace_str str "\r" "\\r" in
6029 let str = replace_str str "\n" "\\n" in
6030 let str = replace_str str "\t" "\\t" in
6031 let str = replace_str str "\000" "\\0" in
6034 (* Generate a lot of different functions for guestfish. *)
6035 and generate_fish_cmds () =
6036 generate_header CStyle GPLv2;
6040 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6042 let all_functions_sorted =
6044 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6045 ) all_functions_sorted in
6047 pr "#include <stdio.h>\n";
6048 pr "#include <stdlib.h>\n";
6049 pr "#include <string.h>\n";
6050 pr "#include <inttypes.h>\n";
6051 pr "#include <ctype.h>\n";
6053 pr "#include <guestfs.h>\n";
6054 pr "#include \"fish.h\"\n";
6057 (* list_commands function, which implements guestfish -h *)
6058 pr "void list_commands (void)\n";
6060 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6061 pr " list_builtin_commands ();\n";
6063 fun (name, _, _, flags, _, shortdesc, _) ->
6064 let name = replace_char name '_' '-' in
6065 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6067 ) all_functions_sorted;
6068 pr " printf (\" %%s\\n\",";
6069 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6073 (* display_command function, which implements guestfish -h cmd *)
6074 pr "void display_command (const char *cmd)\n";
6077 fun (name, style, _, flags, _, shortdesc, longdesc) ->
6078 let name2 = replace_char name '_' '-' in
6080 try find_map (function FishAlias n -> Some n | _ -> None) flags
6081 with Not_found -> name in
6082 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6084 match snd style with
6088 name2 (String.concat "> <" (List.map name_of_argt args)) in
6091 if List.mem ProtocolLimitWarning flags then
6092 ("\n\n" ^ protocol_limit_warning)
6095 (* For DangerWillRobinson commands, we should probably have
6096 * guestfish prompt before allowing you to use them (especially
6097 * in interactive mode). XXX
6101 if List.mem DangerWillRobinson flags then
6102 ("\n\n" ^ danger_will_robinson)
6107 match deprecation_notice flags with
6109 | Some txt -> "\n\n" ^ txt in
6111 let describe_alias =
6112 if name <> alias then
6113 sprintf "\n\nYou can use '%s' as an alias for this command." alias
6117 pr "strcasecmp (cmd, \"%s\") == 0" name;
6118 if name <> name2 then
6119 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6120 if name <> alias then
6121 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6123 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
6125 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6128 pr " display_builtin_command (cmd);\n";
6132 let emit_print_list_function typ =
6133 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6136 pr " unsigned int i;\n";
6138 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6139 pr " printf (\"[%%d] = {\\n\", i);\n";
6140 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
6141 pr " printf (\"}\\n\");\n";
6147 (* print_* functions *)
6151 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6153 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6156 pr " unsigned int i;\n";
6162 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6164 pr " printf (\"%s: \");\n" name;
6165 pr " for (i = 0; i < 32; ++i)\n";
6166 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6167 pr " printf (\"\\n\");\n"
6169 pr " printf (\"%%s%s: \", indent);\n" name;
6170 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6171 pr " if (isprint (%s->%s[i]))\n" typ name;
6172 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6174 pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6175 pr " printf (\"\\n\");\n"
6176 | name, (FUInt64|FBytes) ->
6177 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6180 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6183 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6186 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6189 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6191 | name, FOptPercent ->
6192 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6193 typ name name typ name;
6194 pr " else printf (\"%%s%s: \\n\", indent);\n" name
6200 (* Emit a print_TYPE_list function definition only if that function is used. *)
6203 | typ, (RStructListOnly | RStructAndList) ->
6204 (* generate the function for typ *)
6205 emit_print_list_function typ
6206 | typ, _ -> () (* empty *)
6209 (* Emit a print_TYPE function definition only if that function is used. *)
6212 | typ, RStructOnly ->
6213 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6215 pr " print_%s_indent (%s, \"\");\n" typ typ;
6218 | typ, _ -> () (* empty *)
6221 (* run_<action> actions *)
6223 fun (name, style, _, flags, _, _, _) ->
6224 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6226 (match fst style with
6229 | RBool _ -> pr " int r;\n"
6230 | RInt64 _ -> pr " int64_t r;\n"
6231 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
6232 | RString _ -> pr " char *r;\n"
6233 | RStringList _ | RHashtable _ -> pr " char **r;\n"
6234 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
6235 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
6238 pr " size_t size;\n";
6243 | Device n | Dev_or_Path n
6247 | FileOut n -> pr " const char *%s;\n" n
6248 | StringList n | DeviceList n -> pr " char **%s;\n" n
6249 | Bool n -> pr " int %s;\n" n
6250 | Int n -> pr " int %s;\n" n
6253 (* Check and convert parameters. *)
6254 let argc_expected = List.length (snd style) in
6255 pr " if (argc != %d) {\n" argc_expected;
6256 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6258 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6265 | Device name | Dev_or_Path name | String name -> pr " %s = argv[%d];\n" name i
6267 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6270 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6273 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6275 | StringList name | DeviceList name ->
6276 pr " %s = parse_string_list (argv[%d]);\n" name i;
6277 pr " if (%s == NULL) return -1;\n" name;
6279 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6281 pr " %s = atoi (argv[%d]);\n" name i
6284 (* Call C API function. *)
6286 try find_map (function FishAction n -> Some n | _ -> None) flags
6287 with Not_found -> sprintf "guestfs_%s" name in
6289 generate_c_call_args ~handle:"g" style;
6294 | Pathname name | Device name | Dev_or_Path name | String name
6295 | OptString name | FileIn name | FileOut name | Bool name
6297 | StringList name | DeviceList name ->
6298 pr " free_strings (%s);\n" name
6301 (* Check return value for errors and display command results. *)
6302 (match fst style with
6303 | RErr -> pr " return r;\n"
6305 pr " if (r == -1) return -1;\n";
6306 pr " printf (\"%%d\\n\", r);\n";
6309 pr " if (r == -1) return -1;\n";
6310 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6313 pr " if (r == -1) return -1;\n";
6314 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6317 pr " if (r == NULL) return -1;\n";
6318 pr " printf (\"%%s\\n\", r);\n";
6320 | RConstOptString _ ->
6321 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6324 pr " if (r == NULL) return -1;\n";
6325 pr " printf (\"%%s\\n\", r);\n";
6329 pr " if (r == NULL) return -1;\n";
6330 pr " print_strings (r);\n";
6331 pr " free_strings (r);\n";
6333 | RStruct (_, typ) ->
6334 pr " if (r == NULL) return -1;\n";
6335 pr " print_%s (r);\n" typ;
6336 pr " guestfs_free_%s (r);\n" typ;
6338 | RStructList (_, typ) ->
6339 pr " if (r == NULL) return -1;\n";
6340 pr " print_%s_list (r);\n" typ;
6341 pr " guestfs_free_%s_list (r);\n" typ;
6344 pr " if (r == NULL) return -1;\n";
6345 pr " print_table (r);\n";
6346 pr " free_strings (r);\n";
6349 pr " if (r == NULL) return -1;\n";
6350 pr " fwrite (r, size, 1, stdout);\n";
6358 (* run_action function *)
6359 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6362 fun (name, _, _, flags, _, _, _) ->
6363 let name2 = replace_char name '_' '-' in
6365 try find_map (function FishAlias n -> Some n | _ -> None) flags
6366 with Not_found -> name in
6368 pr "strcasecmp (cmd, \"%s\") == 0" name;
6369 if name <> name2 then
6370 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6371 if name <> alias then
6372 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6374 pr " return run_%s (cmd, argc, argv);\n" name;
6378 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6385 (* Readline completion for guestfish. *)
6386 and generate_fish_completion () =
6387 generate_header CStyle GPLv2;
6391 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6401 #ifdef HAVE_LIBREADLINE
6402 #include <readline/readline.h>
6407 #ifdef HAVE_LIBREADLINE
6409 static const char *const commands[] = {
6410 BUILTIN_COMMANDS_FOR_COMPLETION,
6413 (* Get the commands, including the aliases. They don't need to be
6414 * sorted - the generator() function just does a dumb linear search.
6418 fun (name, _, _, flags, _, _, _) ->
6419 let name2 = replace_char name '_' '-' in
6421 try find_map (function FishAlias n -> Some n | _ -> None) flags
6422 with Not_found -> name in
6424 if name <> alias then [name2; alias] else [name2]
6426 let commands = List.flatten commands in
6428 List.iter (pr " \"%s\",\n") commands;
6434 generator (const char *text, int state)
6436 static int index, len;
6441 len = strlen (text);
6444 rl_attempted_completion_over = 1;
6446 while ((name = commands[index]) != NULL) {
6448 if (strncasecmp (name, text, len) == 0)
6449 return strdup (name);
6455 #endif /* HAVE_LIBREADLINE */
6457 char **do_completion (const char *text, int start, int end)
6459 char **matches = NULL;
6461 #ifdef HAVE_LIBREADLINE
6462 rl_completion_append_character = ' ';
6465 matches = rl_completion_matches (text, generator);
6466 else if (complete_dest_paths)
6467 matches = rl_completion_matches (text, complete_dest_paths_generator);
6474 (* Generate the POD documentation for guestfish. *)
6475 and generate_fish_actions_pod () =
6476 let all_functions_sorted =
6478 fun (_, _, _, flags, _, _, _) ->
6479 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6480 ) all_functions_sorted in
6482 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6485 fun (name, style, _, flags, _, _, longdesc) ->
6487 Str.global_substitute rex (
6490 try Str.matched_group 1 s
6492 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6493 "C<" ^ replace_char sub '_' '-' ^ ">"
6495 let name = replace_char name '_' '-' in
6497 try find_map (function FishAlias n -> Some n | _ -> None) flags
6498 with Not_found -> name in
6500 pr "=head2 %s" name;
6501 if name <> alias then
6508 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6509 | OptString n -> pr " %s" n
6510 | StringList n | DeviceList n -> pr " '%s ...'" n
6511 | Bool _ -> pr " true|false"
6512 | Int n -> pr " %s" n
6513 | FileIn n | FileOut n -> pr " (%s|-)" n
6517 pr "%s\n\n" longdesc;
6519 if List.exists (function FileIn _ | FileOut _ -> true
6520 | _ -> false) (snd style) then
6521 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6523 if List.mem ProtocolLimitWarning flags then
6524 pr "%s\n\n" protocol_limit_warning;
6526 if List.mem DangerWillRobinson flags then
6527 pr "%s\n\n" danger_will_robinson;
6529 match deprecation_notice flags with
6531 | Some txt -> pr "%s\n\n" txt
6532 ) all_functions_sorted
6534 (* Generate a C function prototype. *)
6535 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6536 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6538 ?handle name style =
6539 if extern then pr "extern ";
6540 if static then pr "static ";
6541 (match fst style with
6543 | RInt _ -> pr "int "
6544 | RInt64 _ -> pr "int64_t "
6545 | RBool _ -> pr "int "
6546 | RConstString _ | RConstOptString _ -> pr "const char *"
6547 | RString _ | RBufferOut _ -> pr "char *"
6548 | RStringList _ | RHashtable _ -> pr "char **"
6549 | RStruct (_, typ) ->
6550 if not in_daemon then pr "struct guestfs_%s *" typ
6551 else pr "guestfs_int_%s *" typ
6552 | RStructList (_, typ) ->
6553 if not in_daemon then pr "struct guestfs_%s_list *" typ
6554 else pr "guestfs_int_%s_list *" typ
6556 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6557 pr "%s%s (" prefix name;
6558 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6561 let comma = ref false in
6564 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6568 if single_line then pr ", " else pr ",\n\t\t"
6575 | Device n | Dev_or_Path n
6579 pr "const char *%s" n
6580 | StringList n | DeviceList n ->
6582 pr "char *const *%s" n
6583 | Bool n -> next (); pr "int %s" n
6584 | Int n -> next (); pr "int %s" n
6587 if not in_daemon then (next (); pr "const char *%s" n)
6589 if is_RBufferOut then (next (); pr "size_t *size_r");
6592 if semicolon then pr ";";
6593 if newline then pr "\n"
6595 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6596 and generate_c_call_args ?handle ?(decl = false) style =
6598 let comma = ref false in
6600 if !comma then pr ", ";
6605 | Some handle -> pr "%s" handle; comma := true
6610 pr "%s" (name_of_argt arg)
6612 (* For RBufferOut calls, add implicit &size parameter. *)
6614 match fst style with
6622 (* Generate the OCaml bindings interface. *)
6623 and generate_ocaml_mli () =
6624 generate_header OCamlStyle LGPLv2;
6627 (** For API documentation you should refer to the C API
6628 in the guestfs(3) manual page. The OCaml API uses almost
6629 exactly the same calls. *)
6632 (** A [guestfs_h] handle. *)
6634 exception Error of string
6635 (** This exception is raised when there is an error. *)
6637 val create : unit -> t
6639 val close : t -> unit
6640 (** Handles are closed by the garbage collector when they become
6641 unreferenced, but callers can also call this in order to
6642 provide predictable cleanup. *)
6645 generate_ocaml_structure_decls ();
6649 fun (name, style, _, _, _, shortdesc, _) ->
6650 generate_ocaml_prototype name style;
6651 pr "(** %s *)\n" shortdesc;
6655 (* Generate the OCaml bindings implementation. *)
6656 and generate_ocaml_ml () =
6657 generate_header OCamlStyle LGPLv2;
6661 exception Error of string
6662 external create : unit -> t = \"ocaml_guestfs_create\"
6663 external close : t -> unit = \"ocaml_guestfs_close\"
6666 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6670 generate_ocaml_structure_decls ();
6674 fun (name, style, _, _, _, shortdesc, _) ->
6675 generate_ocaml_prototype ~is_external:true name style;
6678 (* Generate the OCaml bindings C implementation. *)
6679 and generate_ocaml_c () =
6680 generate_header CStyle LGPLv2;
6687 #include <caml/config.h>
6688 #include <caml/alloc.h>
6689 #include <caml/callback.h>
6690 #include <caml/fail.h>
6691 #include <caml/memory.h>
6692 #include <caml/mlvalues.h>
6693 #include <caml/signals.h>
6695 #include <guestfs.h>
6697 #include \"guestfs_c.h\"
6699 /* Copy a hashtable of string pairs into an assoc-list. We return
6700 * the list in reverse order, but hashtables aren't supposed to be
6703 static CAMLprim value
6704 copy_table (char * const * argv)
6707 CAMLlocal5 (rv, pairv, kv, vv, cons);
6711 for (i = 0; argv[i] != NULL; i += 2) {
6712 kv = caml_copy_string (argv[i]);
6713 vv = caml_copy_string (argv[i+1]);
6714 pairv = caml_alloc (2, 0);
6715 Store_field (pairv, 0, kv);
6716 Store_field (pairv, 1, vv);
6717 cons = caml_alloc (2, 0);
6718 Store_field (cons, 1, rv);
6720 Store_field (cons, 0, pairv);
6728 (* Struct copy functions. *)
6730 let emit_ocaml_copy_list_function typ =
6731 pr "static CAMLprim value\n";
6732 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6734 pr " CAMLparam0 ();\n";
6735 pr " CAMLlocal2 (rv, v);\n";
6736 pr " unsigned int i;\n";
6738 pr " if (%ss->len == 0)\n" typ;
6739 pr " CAMLreturn (Atom (0));\n";
6741 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
6742 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6743 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
6744 pr " caml_modify (&Field (rv, i), v);\n";
6746 pr " CAMLreturn (rv);\n";
6754 let has_optpercent_col =
6755 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6757 pr "static CAMLprim value\n";
6758 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6760 pr " CAMLparam0 ();\n";
6761 if has_optpercent_col then
6762 pr " CAMLlocal3 (rv, v, v2);\n"
6764 pr " CAMLlocal2 (rv, v);\n";
6766 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
6771 pr " v = caml_copy_string (%s->%s);\n" typ name
6773 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
6774 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6777 pr " v = caml_alloc_string (32);\n";
6778 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
6779 | name, (FBytes|FInt64|FUInt64) ->
6780 pr " v = caml_copy_int64 (%s->%s);\n" typ name
6781 | name, (FInt32|FUInt32) ->
6782 pr " v = caml_copy_int32 (%s->%s);\n" typ name
6783 | name, FOptPercent ->
6784 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6785 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
6786 pr " v = caml_alloc (1, 0);\n";
6787 pr " Store_field (v, 0, v2);\n";
6788 pr " } else /* None */\n";
6789 pr " v = Val_int (0);\n";
6791 pr " v = Val_int (%s->%s);\n" typ name
6793 pr " Store_field (rv, %d, v);\n" i
6795 pr " CAMLreturn (rv);\n";
6800 (* Emit a copy_TYPE_list function definition only if that function is used. *)
6803 | typ, (RStructListOnly | RStructAndList) ->
6804 (* generate the function for typ *)
6805 emit_ocaml_copy_list_function typ
6806 | typ, _ -> () (* empty *)
6811 fun (name, style, _, _, _, _, _) ->
6813 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6815 let needs_extra_vs =
6816 match fst style with RConstOptString _ -> true | _ -> false in
6818 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6819 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6820 List.iter (pr ", value %s") (List.tl params); pr ");\n";
6822 pr "CAMLprim value\n";
6823 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6824 List.iter (pr ", value %s") (List.tl params);
6829 | [p1; p2; p3; p4; p5] ->
6830 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
6831 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6832 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6833 pr " CAMLxparam%d (%s);\n"
6834 (List.length rest) (String.concat ", " rest)
6836 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6838 if not needs_extra_vs then
6839 pr " CAMLlocal1 (rv);\n"
6841 pr " CAMLlocal3 (rv, v, v2);\n";
6844 pr " guestfs_h *g = Guestfs_val (gv);\n";
6845 pr " if (g == NULL)\n";
6846 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
6852 | Device n | Dev_or_Path n
6856 pr " const char *%s = String_val (%sv);\n" n n
6858 pr " const char *%s =\n" n;
6859 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6861 | StringList n | DeviceList n ->
6862 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6864 pr " int %s = Bool_val (%sv);\n" n n
6866 pr " int %s = Int_val (%sv);\n" n n
6869 match fst style with
6870 | RErr -> pr " int r;\n"; "-1"
6871 | RInt _ -> pr " int r;\n"; "-1"
6872 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6873 | RBool _ -> pr " int r;\n"; "-1"
6874 | RConstString _ | RConstOptString _ ->
6875 pr " const char *r;\n"; "NULL"
6876 | RString _ -> pr " char *r;\n"; "NULL"
6881 | RStruct (_, typ) ->
6882 pr " struct guestfs_%s *r;\n" typ; "NULL"
6883 | RStructList (_, typ) ->
6884 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6891 pr " size_t size;\n";
6895 pr " caml_enter_blocking_section ();\n";
6896 pr " r = guestfs_%s " name;
6897 generate_c_call_args ~handle:"g" style;
6899 pr " caml_leave_blocking_section ();\n";
6903 | StringList n | DeviceList n ->
6904 pr " ocaml_guestfs_free_strings (%s);\n" n;
6905 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6906 | FileIn _ | FileOut _ -> ()
6909 pr " if (r == %s)\n" error_code;
6910 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6913 (match fst style with
6914 | RErr -> pr " rv = Val_unit;\n"
6915 | RInt _ -> pr " rv = Val_int (r);\n"
6917 pr " rv = caml_copy_int64 (r);\n"
6918 | RBool _ -> pr " rv = Val_bool (r);\n"
6920 pr " rv = caml_copy_string (r);\n"
6921 | RConstOptString _ ->
6922 pr " if (r) { /* Some string */\n";
6923 pr " v = caml_alloc (1, 0);\n";
6924 pr " v2 = caml_copy_string (r);\n";
6925 pr " Store_field (v, 0, v2);\n";
6926 pr " } else /* None */\n";
6927 pr " v = Val_int (0);\n";
6929 pr " rv = caml_copy_string (r);\n";
6932 pr " rv = caml_copy_string_array ((const char **) r);\n";
6933 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6935 | RStruct (_, typ) ->
6936 pr " rv = copy_%s (r);\n" typ;
6937 pr " guestfs_free_%s (r);\n" typ;
6938 | RStructList (_, typ) ->
6939 pr " rv = copy_%s_list (r);\n" typ;
6940 pr " guestfs_free_%s_list (r);\n" typ;
6942 pr " rv = copy_table (r);\n";
6943 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6946 pr " rv = caml_alloc_string (size);\n";
6947 pr " memcpy (String_val (rv), r, size);\n";
6950 pr " CAMLreturn (rv);\n";
6954 if List.length params > 5 then (
6955 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6956 pr "CAMLprim value ";
6957 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
6958 pr "CAMLprim value\n";
6959 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6961 pr " return ocaml_guestfs_%s (argv[0]" name;
6962 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6969 and generate_ocaml_structure_decls () =
6972 pr "type %s = {\n" typ;
6975 | name, FString -> pr " %s : string;\n" name
6976 | name, FBuffer -> pr " %s : string;\n" name
6977 | name, FUUID -> pr " %s : string;\n" name
6978 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
6979 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
6980 | name, FChar -> pr " %s : char;\n" name
6981 | name, FOptPercent -> pr " %s : float option;\n" name
6987 and generate_ocaml_prototype ?(is_external = false) name style =
6988 if is_external then pr "external " else pr "val ";
6989 pr "%s : t -> " name;
6992 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6993 | OptString _ -> pr "string option -> "
6994 | StringList _ | DeviceList _ -> pr "string array -> "
6995 | Bool _ -> pr "bool -> "
6996 | Int _ -> pr "int -> "
6998 (match fst style with
6999 | RErr -> pr "unit" (* all errors are turned into exceptions *)
7000 | RInt _ -> pr "int"
7001 | RInt64 _ -> pr "int64"
7002 | RBool _ -> pr "bool"
7003 | RConstString _ -> pr "string"
7004 | RConstOptString _ -> pr "string option"
7005 | RString _ | RBufferOut _ -> pr "string"
7006 | RStringList _ -> pr "string array"
7007 | RStruct (_, typ) -> pr "%s" typ
7008 | RStructList (_, typ) -> pr "%s array" typ
7009 | RHashtable _ -> pr "(string * string) list"
7011 if is_external then (
7013 if List.length (snd style) + 1 > 5 then
7014 pr "\"ocaml_guestfs_%s_byte\" " name;
7015 pr "\"ocaml_guestfs_%s\"" name
7019 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7020 and generate_perl_xs () =
7021 generate_header CStyle LGPLv2;
7024 #include \"EXTERN.h\"
7028 #include <guestfs.h>
7031 #define PRId64 \"lld\"
7035 my_newSVll(long long val) {
7036 #ifdef USE_64_BIT_ALL
7037 return newSViv(val);
7041 len = snprintf(buf, 100, \"%%\" PRId64, val);
7042 return newSVpv(buf, len);
7047 #define PRIu64 \"llu\"
7051 my_newSVull(unsigned long long val) {
7052 #ifdef USE_64_BIT_ALL
7053 return newSVuv(val);
7057 len = snprintf(buf, 100, \"%%\" PRIu64, val);
7058 return newSVpv(buf, len);
7062 /* http://www.perlmonks.org/?node_id=680842 */
7064 XS_unpack_charPtrPtr (SV *arg) {
7069 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7070 croak (\"array reference expected\");
7072 av = (AV *)SvRV (arg);
7073 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7075 croak (\"malloc failed\");
7077 for (i = 0; i <= av_len (av); i++) {
7078 SV **elem = av_fetch (av, i, 0);
7080 if (!elem || !*elem)
7081 croak (\"missing element in list\");
7083 ret[i] = SvPV_nolen (*elem);
7091 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
7098 RETVAL = guestfs_create ();
7100 croak (\"could not create guestfs handle\");
7101 guestfs_set_error_handler (RETVAL, NULL, NULL);
7114 fun (name, style, _, _, _, _, _) ->
7115 (match fst style with
7116 | RErr -> pr "void\n"
7117 | RInt _ -> pr "SV *\n"
7118 | RInt64 _ -> pr "SV *\n"
7119 | RBool _ -> pr "SV *\n"
7120 | RConstString _ -> pr "SV *\n"
7121 | RConstOptString _ -> pr "SV *\n"
7122 | RString _ -> pr "SV *\n"
7123 | RBufferOut _ -> pr "SV *\n"
7125 | RStruct _ | RStructList _
7127 pr "void\n" (* all lists returned implictly on the stack *)
7129 (* Call and arguments. *)
7131 generate_c_call_args ~handle:"g" ~decl:true style;
7133 pr " guestfs_h *g;\n";
7137 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7140 (* http://www.perlmonks.org/?node_id=554277
7141 * Note that the implicit handle argument means we have
7142 * to add 1 to the ST(x) operator.
7144 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7145 | StringList n | DeviceList n -> pr " char **%s;\n" n
7146 | Bool n -> pr " int %s;\n" n
7147 | Int n -> pr " int %s;\n" n
7150 let do_cleanups () =
7153 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7154 | FileIn _ | FileOut _ -> ()
7155 | StringList n | DeviceList n -> pr " free (%s);\n" n
7160 (match fst style with
7165 pr " r = guestfs_%s " name;
7166 generate_c_call_args ~handle:"g" style;
7169 pr " if (r == -1)\n";
7170 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7176 pr " %s = guestfs_%s " n name;
7177 generate_c_call_args ~handle:"g" style;
7180 pr " if (%s == -1)\n" n;
7181 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7182 pr " RETVAL = newSViv (%s);\n" n;
7187 pr " int64_t %s;\n" n;
7189 pr " %s = guestfs_%s " n name;
7190 generate_c_call_args ~handle:"g" style;
7193 pr " if (%s == -1)\n" n;
7194 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7195 pr " RETVAL = my_newSVll (%s);\n" n;
7200 pr " const char *%s;\n" n;
7202 pr " %s = guestfs_%s " n name;
7203 generate_c_call_args ~handle:"g" style;
7206 pr " if (%s == NULL)\n" n;
7207 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7208 pr " RETVAL = newSVpv (%s, 0);\n" n;
7211 | RConstOptString n ->
7213 pr " const char *%s;\n" n;
7215 pr " %s = guestfs_%s " n name;
7216 generate_c_call_args ~handle:"g" style;
7219 pr " if (%s == NULL)\n" n;
7220 pr " RETVAL = &PL_sv_undef;\n";
7222 pr " RETVAL = newSVpv (%s, 0);\n" n;
7227 pr " char *%s;\n" n;
7229 pr " %s = guestfs_%s " n name;
7230 generate_c_call_args ~handle:"g" style;
7233 pr " if (%s == NULL)\n" n;
7234 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7235 pr " RETVAL = newSVpv (%s, 0);\n" n;
7236 pr " free (%s);\n" n;
7239 | RStringList n | RHashtable n ->
7241 pr " char **%s;\n" n;
7244 pr " %s = guestfs_%s " n name;
7245 generate_c_call_args ~handle:"g" style;
7248 pr " if (%s == NULL)\n" n;
7249 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7250 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7251 pr " EXTEND (SP, n);\n";
7252 pr " for (i = 0; i < n; ++i) {\n";
7253 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7254 pr " free (%s[i]);\n" n;
7256 pr " free (%s);\n" n;
7257 | RStruct (n, typ) ->
7258 let cols = cols_of_struct typ in
7259 generate_perl_struct_code typ cols name style n do_cleanups
7260 | RStructList (n, typ) ->
7261 let cols = cols_of_struct typ in
7262 generate_perl_struct_list_code typ cols name style n do_cleanups
7265 pr " char *%s;\n" n;
7266 pr " size_t size;\n";
7268 pr " %s = guestfs_%s " n name;
7269 generate_c_call_args ~handle:"g" style;
7272 pr " if (%s == NULL)\n" n;
7273 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7274 pr " RETVAL = newSVpv (%s, size);\n" n;
7275 pr " free (%s);\n" n;
7283 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7285 pr " struct guestfs_%s_list *%s;\n" typ n;
7289 pr " %s = guestfs_%s " n name;
7290 generate_c_call_args ~handle:"g" style;
7293 pr " if (%s == NULL)\n" n;
7294 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7295 pr " EXTEND (SP, %s->len);\n" n;
7296 pr " for (i = 0; i < %s->len; ++i) {\n" n;
7297 pr " hv = newHV ();\n";
7301 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7302 name (String.length name) n name
7304 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7305 name (String.length name) n name
7307 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7308 name (String.length name) n name n name
7309 | name, (FBytes|FUInt64) ->
7310 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7311 name (String.length name) n name
7313 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7314 name (String.length name) n name
7315 | name, (FInt32|FUInt32) ->
7316 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7317 name (String.length name) n name
7319 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7320 name (String.length name) n name
7321 | name, FOptPercent ->
7322 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7323 name (String.length name) n name
7325 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7327 pr " guestfs_free_%s_list (%s);\n" typ n
7329 and generate_perl_struct_code typ cols name style n do_cleanups =
7331 pr " struct guestfs_%s *%s;\n" typ n;
7333 pr " %s = guestfs_%s " n name;
7334 generate_c_call_args ~handle:"g" style;
7337 pr " if (%s == NULL)\n" n;
7338 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7339 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7341 fun ((name, _) as col) ->
7342 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7346 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7349 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7352 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7354 | name, (FBytes|FUInt64) ->
7355 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7358 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7360 | name, (FInt32|FUInt32) ->
7361 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7364 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7366 | name, FOptPercent ->
7367 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7370 pr " free (%s);\n" n
7372 (* Generate Sys/Guestfs.pm. *)
7373 and generate_perl_pm () =
7374 generate_header HashStyle LGPLv2;
7381 Sys::Guestfs - Perl bindings for libguestfs
7387 my $h = Sys::Guestfs->new ();
7388 $h->add_drive ('guest.img');
7390 $h->mount ('/dev/sda1', '/');
7391 $h->touch ('/hello');
7396 The C<Sys::Guestfs> module provides a Perl XS binding to the
7397 libguestfs API for examining and modifying virtual machine
7400 Amongst the things this is good for: making batch configuration
7401 changes to guests, getting disk used/free statistics (see also:
7402 virt-df), migrating between virtualization systems (see also:
7403 virt-p2v), performing partial backups, performing partial guest
7404 clones, cloning guests and changing registry/UUID/hostname info, and
7407 Libguestfs uses Linux kernel and qemu code, and can access any type of
7408 guest filesystem that Linux and qemu can, including but not limited
7409 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7410 schemes, qcow, qcow2, vmdk.
7412 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7413 LVs, what filesystem is in each LV, etc.). It can also run commands
7414 in the context of the guest. Also you can access filesystems over FTP.
7416 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7417 functions for using libguestfs from Perl, including integration
7422 All errors turn into calls to C<croak> (see L<Carp(3)>).
7430 package Sys::Guestfs;
7436 XSLoader::load ('Sys::Guestfs');
7438 =item $h = Sys::Guestfs->new ();
7440 Create a new guestfs handle.
7446 my $class = ref ($proto) || $proto;
7448 my $self = Sys::Guestfs::_create ();
7449 bless $self, $class;
7455 (* Actions. We only need to print documentation for these as
7456 * they are pulled in from the XS code automatically.
7459 fun (name, style, _, flags, _, _, longdesc) ->
7460 if not (List.mem NotInDocs flags) then (
7461 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7463 generate_perl_prototype name style;
7465 pr "%s\n\n" longdesc;
7466 if List.mem ProtocolLimitWarning flags then
7467 pr "%s\n\n" protocol_limit_warning;
7468 if List.mem DangerWillRobinson flags then
7469 pr "%s\n\n" danger_will_robinson;
7470 match deprecation_notice flags with
7472 | Some txt -> pr "%s\n\n" txt
7474 ) all_functions_sorted;
7486 Copyright (C) 2009 Red Hat Inc.
7490 Please see the file COPYING.LIB for the full license.
7496 L<http://libguestfs.org>,
7497 L<Sys::Guestfs::Lib(3)>.
7502 and generate_perl_prototype name style =
7503 (match fst style with
7511 | RBufferOut n -> pr "$%s = " n
7513 | RHashtable n -> pr "%%%s = " n
7515 | RStructList (n,_) -> pr "@%s = " n
7518 let comma = ref false in
7521 if !comma then pr ", ";
7524 | Pathname n | Device n | Dev_or_Path n | String n
7525 | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7527 | StringList n | DeviceList n ->
7532 (* Generate Python C module. *)
7533 and generate_python_c () =
7534 generate_header CStyle LGPLv2;
7543 #include \"guestfs.h\"
7551 get_handle (PyObject *obj)
7554 assert (obj != Py_None);
7555 return ((Pyguestfs_Object *) obj)->g;
7559 put_handle (guestfs_h *g)
7563 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7566 /* This list should be freed (but not the strings) after use. */
7568 get_string_list (PyObject *obj)
7575 if (!PyList_Check (obj)) {
7576 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7580 len = PyList_Size (obj);
7581 r = malloc (sizeof (char *) * (len+1));
7583 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7587 for (i = 0; i < len; ++i)
7588 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7595 put_string_list (char * const * const argv)
7600 for (argc = 0; argv[argc] != NULL; ++argc)
7603 list = PyList_New (argc);
7604 for (i = 0; i < argc; ++i)
7605 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7611 put_table (char * const * const argv)
7613 PyObject *list, *item;
7616 for (argc = 0; argv[argc] != NULL; ++argc)
7619 list = PyList_New (argc >> 1);
7620 for (i = 0; i < argc; i += 2) {
7621 item = PyTuple_New (2);
7622 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7623 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7624 PyList_SetItem (list, i >> 1, item);
7631 free_strings (char **argv)
7635 for (argc = 0; argv[argc] != NULL; ++argc)
7641 py_guestfs_create (PyObject *self, PyObject *args)
7645 g = guestfs_create ();
7647 PyErr_SetString (PyExc_RuntimeError,
7648 \"guestfs.create: failed to allocate handle\");
7651 guestfs_set_error_handler (g, NULL, NULL);
7652 return put_handle (g);
7656 py_guestfs_close (PyObject *self, PyObject *args)
7661 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7663 g = get_handle (py_g);
7667 Py_INCREF (Py_None);
7673 let emit_put_list_function typ =
7674 pr "static PyObject *\n";
7675 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7677 pr " PyObject *list;\n";
7680 pr " list = PyList_New (%ss->len);\n" typ;
7681 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7682 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7683 pr " return list;\n";
7688 (* Structures, turned into Python dictionaries. *)
7691 pr "static PyObject *\n";
7692 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7694 pr " PyObject *dict;\n";
7696 pr " dict = PyDict_New ();\n";
7700 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7701 pr " PyString_FromString (%s->%s));\n"
7704 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7705 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7708 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7709 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
7711 | name, (FBytes|FUInt64) ->
7712 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7713 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
7716 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7717 pr " PyLong_FromLongLong (%s->%s));\n"
7720 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7721 pr " PyLong_FromUnsignedLong (%s->%s));\n"
7724 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7725 pr " PyLong_FromLong (%s->%s));\n"
7727 | name, FOptPercent ->
7728 pr " if (%s->%s >= 0)\n" typ name;
7729 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7730 pr " PyFloat_FromDouble ((double) %s->%s));\n"
7733 pr " Py_INCREF (Py_None);\n";
7734 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7737 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7738 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7740 pr " return dict;\n";
7746 (* Emit a put_TYPE_list function definition only if that function is used. *)
7749 | typ, (RStructListOnly | RStructAndList) ->
7750 (* generate the function for typ *)
7751 emit_put_list_function typ
7752 | typ, _ -> () (* empty *)
7755 (* Python wrapper functions. *)
7757 fun (name, style, _, _, _, _, _) ->
7758 pr "static PyObject *\n";
7759 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7762 pr " PyObject *py_g;\n";
7763 pr " guestfs_h *g;\n";
7764 pr " PyObject *py_r;\n";
7767 match fst style with
7768 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7769 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7770 | RConstString _ | RConstOptString _ ->
7771 pr " const char *r;\n"; "NULL"
7772 | RString _ -> pr " char *r;\n"; "NULL"
7773 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7774 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7775 | RStructList (_, typ) ->
7776 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7779 pr " size_t size;\n";
7784 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7785 pr " const char *%s;\n" n
7786 | OptString n -> pr " const char *%s;\n" n
7787 | StringList n | DeviceList n ->
7788 pr " PyObject *py_%s;\n" n;
7789 pr " char **%s;\n" n
7790 | Bool n -> pr " int %s;\n" n
7791 | Int n -> pr " int %s;\n" n
7796 (* Convert the parameters. *)
7797 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
7800 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7801 | OptString _ -> pr "z"
7802 | StringList _ | DeviceList _ -> pr "O"
7803 | Bool _ -> pr "i" (* XXX Python has booleans? *)
7806 pr ":guestfs_%s\",\n" name;
7810 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7811 | OptString n -> pr ", &%s" n
7812 | StringList n | DeviceList n -> pr ", &py_%s" n
7813 | Bool n -> pr ", &%s" n
7814 | Int n -> pr ", &%s" n
7818 pr " return NULL;\n";
7820 pr " g = get_handle (py_g);\n";
7823 | Pathname _ | Device _ | Dev_or_Path _ | String _
7824 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7825 | StringList n | DeviceList n ->
7826 pr " %s = get_string_list (py_%s);\n" n n;
7827 pr " if (!%s) return NULL;\n" n
7832 pr " r = guestfs_%s " name;
7833 generate_c_call_args ~handle:"g" style;
7838 | Pathname _ | Device _ | Dev_or_Path _ | String _
7839 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7840 | StringList n | DeviceList n ->
7841 pr " free (%s);\n" n
7844 pr " if (r == %s) {\n" error_code;
7845 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7846 pr " return NULL;\n";
7850 (match fst style with
7852 pr " Py_INCREF (Py_None);\n";
7853 pr " py_r = Py_None;\n"
7855 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
7856 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
7857 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
7858 | RConstOptString _ ->
7860 pr " py_r = PyString_FromString (r);\n";
7862 pr " Py_INCREF (Py_None);\n";
7863 pr " py_r = Py_None;\n";
7866 pr " py_r = PyString_FromString (r);\n";
7869 pr " py_r = put_string_list (r);\n";
7870 pr " free_strings (r);\n"
7871 | RStruct (_, typ) ->
7872 pr " py_r = put_%s (r);\n" typ;
7873 pr " guestfs_free_%s (r);\n" typ
7874 | RStructList (_, typ) ->
7875 pr " py_r = put_%s_list (r);\n" typ;
7876 pr " guestfs_free_%s_list (r);\n" typ
7878 pr " py_r = put_table (r);\n";
7879 pr " free_strings (r);\n"
7881 pr " py_r = PyString_FromStringAndSize (r, size);\n";
7885 pr " return py_r;\n";
7890 (* Table of functions. *)
7891 pr "static PyMethodDef methods[] = {\n";
7892 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7893 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7895 fun (name, _, _, _, _, _, _) ->
7896 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7899 pr " { NULL, NULL, 0, NULL }\n";
7903 (* Init function. *)
7906 initlibguestfsmod (void)
7908 static int initialized = 0;
7910 if (initialized) return;
7911 Py_InitModule ((char *) \"libguestfsmod\", methods);
7916 (* Generate Python module. *)
7917 and generate_python_py () =
7918 generate_header HashStyle LGPLv2;
7921 u\"\"\"Python bindings for libguestfs
7924 g = guestfs.GuestFS ()
7925 g.add_drive (\"guest.img\")
7927 parts = g.list_partitions ()
7929 The guestfs module provides a Python binding to the libguestfs API
7930 for examining and modifying virtual machine disk images.
7932 Amongst the things this is good for: making batch configuration
7933 changes to guests, getting disk used/free statistics (see also:
7934 virt-df), migrating between virtualization systems (see also:
7935 virt-p2v), performing partial backups, performing partial guest
7936 clones, cloning guests and changing registry/UUID/hostname info, and
7939 Libguestfs uses Linux kernel and qemu code, and can access any type of
7940 guest filesystem that Linux and qemu can, including but not limited
7941 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7942 schemes, qcow, qcow2, vmdk.
7944 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7945 LVs, what filesystem is in each LV, etc.). It can also run commands
7946 in the context of the guest. Also you can access filesystems over FTP.
7948 Errors which happen while using the API are turned into Python
7949 RuntimeError exceptions.
7951 To create a guestfs handle you usually have to perform the following
7954 # Create the handle, call add_drive at least once, and possibly
7955 # several times if the guest has multiple block devices:
7956 g = guestfs.GuestFS ()
7957 g.add_drive (\"guest.img\")
7959 # Launch the qemu subprocess and wait for it to become ready:
7962 # Now you can issue commands, for example:
7967 import libguestfsmod
7970 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7972 def __init__ (self):
7973 \"\"\"Create a new libguestfs handle.\"\"\"
7974 self._o = libguestfsmod.create ()
7977 libguestfsmod.close (self._o)
7982 fun (name, style, _, flags, _, _, longdesc) ->
7984 generate_py_call_args ~handle:"self" (snd style);
7987 if not (List.mem NotInDocs flags) then (
7988 let doc = replace_str longdesc "C<guestfs_" "C<g." in
7990 match fst style with
7991 | RErr | RInt _ | RInt64 _ | RBool _
7992 | RConstOptString _ | RConstString _
7993 | RString _ | RBufferOut _ -> doc
7995 doc ^ "\n\nThis function returns a list of strings."
7996 | RStruct (_, typ) ->
7997 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7998 | RStructList (_, typ) ->
7999 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
8001 doc ^ "\n\nThis function returns a dictionary." in
8003 if List.mem ProtocolLimitWarning flags then
8004 doc ^ "\n\n" ^ protocol_limit_warning
8007 if List.mem DangerWillRobinson flags then
8008 doc ^ "\n\n" ^ danger_will_robinson
8011 match deprecation_notice flags with
8013 | Some txt -> doc ^ "\n\n" ^ txt in
8014 let doc = pod2text ~width:60 name doc in
8015 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8016 let doc = String.concat "\n " doc in
8017 pr " u\"\"\"%s\"\"\"\n" doc;
8019 pr " return libguestfsmod.%s " name;
8020 generate_py_call_args ~handle:"self._o" (snd style);
8025 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8026 and generate_py_call_args ~handle args =
8028 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8031 (* Useful if you need the longdesc POD text as plain text. Returns a
8034 * Because this is very slow (the slowest part of autogeneration),
8035 * we memoize the results.
8037 and pod2text ~width name longdesc =
8038 let key = width, name, longdesc in
8039 try Hashtbl.find pod2text_memo key
8041 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8042 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8044 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8045 let chan = Unix.open_process_in cmd in
8046 let lines = ref [] in
8048 let line = input_line chan in
8049 if i = 1 then (* discard the first line of output *)
8052 let line = triml line in
8053 lines := line :: !lines;
8056 let lines = try loop 1 with End_of_file -> List.rev !lines in
8057 Unix.unlink filename;
8058 (match Unix.close_process_in chan with
8059 | Unix.WEXITED 0 -> ()
8061 failwithf "pod2text: process exited with non-zero status (%d)" i
8062 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8063 failwithf "pod2text: process signalled or stopped by signal %d" i
8065 Hashtbl.add pod2text_memo key lines;
8066 pod2text_memo_updated ();
8069 (* Generate ruby bindings. *)
8070 and generate_ruby_c () =
8071 generate_header CStyle LGPLv2;
8079 #include \"guestfs.h\"
8081 #include \"extconf.h\"
8083 /* For Ruby < 1.9 */
8085 #define RARRAY_LEN(r) (RARRAY((r))->len)
8088 static VALUE m_guestfs; /* guestfs module */
8089 static VALUE c_guestfs; /* guestfs_h handle */
8090 static VALUE e_Error; /* used for all errors */
8092 static void ruby_guestfs_free (void *p)
8095 guestfs_close ((guestfs_h *) p);
8098 static VALUE ruby_guestfs_create (VALUE m)
8102 g = guestfs_create ();
8104 rb_raise (e_Error, \"failed to create guestfs handle\");
8106 /* Don't print error messages to stderr by default. */
8107 guestfs_set_error_handler (g, NULL, NULL);
8109 /* Wrap it, and make sure the close function is called when the
8112 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8115 static VALUE ruby_guestfs_close (VALUE gv)
8118 Data_Get_Struct (gv, guestfs_h, g);
8120 ruby_guestfs_free (g);
8121 DATA_PTR (gv) = NULL;
8129 fun (name, style, _, _, _, _, _) ->
8130 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8131 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8134 pr " guestfs_h *g;\n";
8135 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
8137 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8143 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8144 pr " Check_Type (%sv, T_STRING);\n" n;
8145 pr " const char *%s = StringValueCStr (%sv);\n" n n;
8147 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8148 pr " \"%s\", \"%s\");\n" n name
8150 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8151 | StringList n | DeviceList n ->
8152 pr " char **%s;\n" n;
8153 pr " Check_Type (%sv, T_ARRAY);\n" n;
8155 pr " int i, len;\n";
8156 pr " len = RARRAY_LEN (%sv);\n" n;
8157 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8159 pr " for (i = 0; i < len; ++i) {\n";
8160 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
8161 pr " %s[i] = StringValueCStr (v);\n" n;
8163 pr " %s[len] = NULL;\n" n;
8166 pr " int %s = RTEST (%sv);\n" n n
8168 pr " int %s = NUM2INT (%sv);\n" n n
8173 match fst style with
8174 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8175 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8176 | RConstString _ | RConstOptString _ ->
8177 pr " const char *r;\n"; "NULL"
8178 | RString _ -> pr " char *r;\n"; "NULL"
8179 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8180 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8181 | RStructList (_, typ) ->
8182 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8185 pr " size_t size;\n";
8189 pr " r = guestfs_%s " name;
8190 generate_c_call_args ~handle:"g" style;
8195 | Pathname _ | Device _ | Dev_or_Path _ | String _
8196 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8197 | StringList n | DeviceList n ->
8198 pr " free (%s);\n" n
8201 pr " if (r == %s)\n" error_code;
8202 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8205 (match fst style with
8207 pr " return Qnil;\n"
8208 | RInt _ | RBool _ ->
8209 pr " return INT2NUM (r);\n"
8211 pr " return ULL2NUM (r);\n"
8213 pr " return rb_str_new2 (r);\n";
8214 | RConstOptString _ ->
8216 pr " return rb_str_new2 (r);\n";
8218 pr " return Qnil;\n";
8220 pr " VALUE rv = rb_str_new2 (r);\n";
8224 pr " int i, len = 0;\n";
8225 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
8226 pr " VALUE rv = rb_ary_new2 (len);\n";
8227 pr " for (i = 0; r[i] != NULL; ++i) {\n";
8228 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8229 pr " free (r[i]);\n";
8233 | RStruct (_, typ) ->
8234 let cols = cols_of_struct typ in
8235 generate_ruby_struct_code typ cols
8236 | RStructList (_, typ) ->
8237 let cols = cols_of_struct typ in
8238 generate_ruby_struct_list_code typ cols
8240 pr " VALUE rv = rb_hash_new ();\n";
8242 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
8243 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8244 pr " free (r[i]);\n";
8245 pr " free (r[i+1]);\n";
8250 pr " VALUE rv = rb_str_new (r, size);\n";
8260 /* Initialize the module. */
8261 void Init__guestfs ()
8263 m_guestfs = rb_define_module (\"Guestfs\");
8264 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8265 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8267 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8268 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8271 (* Define the rest of the methods. *)
8273 fun (name, style, _, _, _, _, _) ->
8274 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
8275 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8280 (* Ruby code to return a struct. *)
8281 and generate_ruby_struct_code typ cols =
8282 pr " VALUE rv = rb_hash_new ();\n";
8286 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8288 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8290 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8291 | name, (FBytes|FUInt64) ->
8292 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8294 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8296 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8298 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8299 | name, FOptPercent ->
8300 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8301 | name, FChar -> (* XXX wrong? *)
8302 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8304 pr " guestfs_free_%s (r);\n" typ;
8307 (* Ruby code to return a struct list. *)
8308 and generate_ruby_struct_list_code typ cols =
8309 pr " VALUE rv = rb_ary_new2 (r->len);\n";
8311 pr " for (i = 0; i < r->len; ++i) {\n";
8312 pr " VALUE hv = rb_hash_new ();\n";
8316 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8318 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
8320 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8321 | name, (FBytes|FUInt64) ->
8322 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8324 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8326 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8328 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8329 | name, FOptPercent ->
8330 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8331 | name, FChar -> (* XXX wrong? *)
8332 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8334 pr " rb_ary_push (rv, hv);\n";
8336 pr " guestfs_free_%s_list (r);\n" typ;
8339 (* Generate Java bindings GuestFS.java file. *)
8340 and generate_java_java () =
8341 generate_header CStyle LGPLv2;
8344 package com.redhat.et.libguestfs;
8346 import java.util.HashMap;
8347 import com.redhat.et.libguestfs.LibGuestFSException;
8348 import com.redhat.et.libguestfs.PV;
8349 import com.redhat.et.libguestfs.VG;
8350 import com.redhat.et.libguestfs.LV;
8351 import com.redhat.et.libguestfs.Stat;
8352 import com.redhat.et.libguestfs.StatVFS;
8353 import com.redhat.et.libguestfs.IntBool;
8354 import com.redhat.et.libguestfs.Dirent;
8357 * The GuestFS object is a libguestfs handle.
8361 public class GuestFS {
8362 // Load the native code.
8364 System.loadLibrary (\"guestfs_jni\");
8368 * The native guestfs_h pointer.
8373 * Create a libguestfs handle.
8375 * @throws LibGuestFSException
8377 public GuestFS () throws LibGuestFSException
8381 private native long _create () throws LibGuestFSException;
8384 * Close a libguestfs handle.
8386 * You can also leave handles to be collected by the garbage
8387 * collector, but this method ensures that the resources used
8388 * by the handle are freed up immediately. If you call any
8389 * other methods after closing the handle, you will get an
8392 * @throws LibGuestFSException
8394 public void close () throws LibGuestFSException
8400 private native void _close (long g) throws LibGuestFSException;
8402 public void finalize () throws LibGuestFSException
8410 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8411 if not (List.mem NotInDocs flags); then (
8412 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8414 if List.mem ProtocolLimitWarning flags then
8415 doc ^ "\n\n" ^ protocol_limit_warning
8418 if List.mem DangerWillRobinson flags then
8419 doc ^ "\n\n" ^ danger_will_robinson
8422 match deprecation_notice flags with
8424 | Some txt -> doc ^ "\n\n" ^ txt in
8425 let doc = pod2text ~width:60 name doc in
8426 let doc = List.map ( (* RHBZ#501883 *)
8429 | nonempty -> nonempty
8431 let doc = String.concat "\n * " doc in
8434 pr " * %s\n" shortdesc;
8437 pr " * @throws LibGuestFSException\n";
8441 generate_java_prototype ~public:true ~semicolon:false name style;
8444 pr " if (g == 0)\n";
8445 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8448 if fst style <> RErr then pr "return ";
8450 generate_java_call_args ~handle:"g" (snd style);
8454 generate_java_prototype ~privat:true ~native:true name style;
8461 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8462 and generate_java_call_args ~handle args =
8464 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8467 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8468 ?(semicolon=true) name style =
8469 if privat then pr "private ";
8470 if public then pr "public ";
8471 if native then pr "native ";
8474 (match fst style with
8475 | RErr -> pr "void ";
8476 | RInt _ -> pr "int ";
8477 | RInt64 _ -> pr "long ";
8478 | RBool _ -> pr "boolean ";
8479 | RConstString _ | RConstOptString _ | RString _
8480 | RBufferOut _ -> pr "String ";
8481 | RStringList _ -> pr "String[] ";
8482 | RStruct (_, typ) ->
8483 let name = java_name_of_struct typ in
8485 | RStructList (_, typ) ->
8486 let name = java_name_of_struct typ in
8488 | RHashtable _ -> pr "HashMap<String,String> ";
8491 if native then pr "_%s " name else pr "%s " name;
8493 let needs_comma = ref false in
8502 if !needs_comma then pr ", ";
8503 needs_comma := true;
8507 | Device n | Dev_or_Path n
8513 | StringList n | DeviceList n ->
8522 pr " throws LibGuestFSException";
8523 if semicolon then pr ";"
8525 and generate_java_struct jtyp cols =
8526 generate_header CStyle LGPLv2;
8529 package com.redhat.et.libguestfs;
8532 * Libguestfs %s structure.
8544 | name, FBuffer -> pr " public String %s;\n" name
8545 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8546 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8547 | name, FChar -> pr " public char %s;\n" name
8548 | name, FOptPercent ->
8549 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8550 pr " public float %s;\n" name
8555 and generate_java_c () =
8556 generate_header CStyle LGPLv2;
8563 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8564 #include \"guestfs.h\"
8566 /* Note that this function returns. The exception is not thrown
8567 * until after the wrapper function returns.
8570 throw_exception (JNIEnv *env, const char *msg)
8573 cl = (*env)->FindClass (env,
8574 \"com/redhat/et/libguestfs/LibGuestFSException\");
8575 (*env)->ThrowNew (env, cl, msg);
8578 JNIEXPORT jlong JNICALL
8579 Java_com_redhat_et_libguestfs_GuestFS__1create
8580 (JNIEnv *env, jobject obj)
8584 g = guestfs_create ();
8586 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8589 guestfs_set_error_handler (g, NULL, NULL);
8590 return (jlong) (long) g;
8593 JNIEXPORT void JNICALL
8594 Java_com_redhat_et_libguestfs_GuestFS__1close
8595 (JNIEnv *env, jobject obj, jlong jg)
8597 guestfs_h *g = (guestfs_h *) (long) jg;
8604 fun (name, style, _, _, _, _, _) ->
8606 (match fst style with
8607 | RErr -> pr "void ";
8608 | RInt _ -> pr "jint ";
8609 | RInt64 _ -> pr "jlong ";
8610 | RBool _ -> pr "jboolean ";
8611 | RConstString _ | RConstOptString _ | RString _
8612 | RBufferOut _ -> pr "jstring ";
8613 | RStruct _ | RHashtable _ ->
8615 | RStringList _ | RStructList _ ->
8619 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8620 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8622 pr " (JNIEnv *env, jobject obj, jlong jg";
8626 | Device n | Dev_or_Path n
8631 pr ", jstring j%s" n
8632 | StringList n | DeviceList n ->
8633 pr ", jobjectArray j%s" n
8635 pr ", jboolean j%s" n
8641 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8642 let error_code, no_ret =
8643 match fst style with
8644 | RErr -> pr " int r;\n"; "-1", ""
8646 | RInt _ -> pr " int r;\n"; "-1", "0"
8647 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8648 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8649 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8651 pr " jstring jr;\n";
8652 pr " char *r;\n"; "NULL", "NULL"
8654 pr " jobjectArray jr;\n";
8657 pr " jstring jstr;\n";
8658 pr " char **r;\n"; "NULL", "NULL"
8659 | RStruct (_, typ) ->
8660 pr " jobject jr;\n";
8662 pr " jfieldID fl;\n";
8663 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8664 | RStructList (_, typ) ->
8665 pr " jobjectArray jr;\n";
8667 pr " jfieldID fl;\n";
8668 pr " jobject jfl;\n";
8669 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8670 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8672 pr " jstring jr;\n";
8674 pr " size_t size;\n";
8679 | Device n | Dev_or_Path n
8684 pr " const char *%s;\n" n
8685 | StringList n | DeviceList n ->
8686 pr " int %s_len;\n" n;
8687 pr " const char **%s;\n" n
8694 (match fst style with
8695 | RStringList _ | RStructList _ -> true
8696 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8698 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8699 List.exists (function
8700 | StringList _ -> true
8701 | DeviceList _ -> true
8702 | _ -> false) (snd style) in
8708 (* Get the parameters. *)
8712 | Device n | Dev_or_Path n
8716 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8718 (* This is completely undocumented, but Java null becomes
8721 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8722 | StringList n | DeviceList n ->
8723 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8724 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8725 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8726 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8728 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8730 pr " %s[%s_len] = NULL;\n" n n;
8733 pr " %s = j%s;\n" n n
8736 (* Make the call. *)
8737 pr " r = guestfs_%s " name;
8738 generate_c_call_args ~handle:"g" style;
8741 (* Release the parameters. *)
8745 | Device n | Dev_or_Path n
8749 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8752 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8753 | StringList n | DeviceList n ->
8754 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8755 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8757 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8759 pr " free (%s);\n" n
8764 (* Check for errors. *)
8765 pr " if (r == %s) {\n" error_code;
8766 pr " throw_exception (env, guestfs_last_error (g));\n";
8767 pr " return %s;\n" no_ret;
8771 (match fst style with
8773 | RInt _ -> pr " return (jint) r;\n"
8774 | RBool _ -> pr " return (jboolean) r;\n"
8775 | RInt64 _ -> pr " return (jlong) r;\n"
8776 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
8777 | RConstOptString _ ->
8778 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8780 pr " jr = (*env)->NewStringUTF (env, r);\n";
8784 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8785 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8786 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
8787 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8788 pr " for (i = 0; i < r_len; ++i) {\n";
8789 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
8790 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8791 pr " free (r[i]);\n";
8795 | RStruct (_, typ) ->
8796 let jtyp = java_name_of_struct typ in
8797 let cols = cols_of_struct typ in
8798 generate_java_struct_return typ jtyp cols
8799 | RStructList (_, typ) ->
8800 let jtyp = java_name_of_struct typ in
8801 let cols = cols_of_struct typ in
8802 generate_java_struct_list_return typ jtyp cols
8805 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8806 pr " return NULL;\n"
8808 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8817 and generate_java_struct_return typ jtyp cols =
8818 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8819 pr " jr = (*env)->AllocObject (env, cl);\n";
8823 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8824 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8827 pr " char s[33];\n";
8828 pr " memcpy (s, r->%s, 32);\n" name;
8830 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8831 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8835 pr " int len = r->%s_len;\n" name;
8836 pr " char s[len+1];\n";
8837 pr " memcpy (s, r->%s, len);\n" name;
8838 pr " s[len] = 0;\n";
8839 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8840 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8842 | name, (FBytes|FUInt64|FInt64) ->
8843 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8844 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8845 | name, (FUInt32|FInt32) ->
8846 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8847 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8848 | name, FOptPercent ->
8849 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8850 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8852 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8853 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8858 and generate_java_struct_list_return typ jtyp cols =
8859 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8860 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8861 pr " for (i = 0; i < r->len; ++i) {\n";
8862 pr " jfl = (*env)->AllocObject (env, cl);\n";
8866 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8867 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8870 pr " char s[33];\n";
8871 pr " memcpy (s, r->val[i].%s, 32);\n" name;
8873 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8874 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8878 pr " int len = r->val[i].%s_len;\n" name;
8879 pr " char s[len+1];\n";
8880 pr " memcpy (s, r->val[i].%s, len);\n" name;
8881 pr " s[len] = 0;\n";
8882 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8883 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8885 | name, (FBytes|FUInt64|FInt64) ->
8886 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8887 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8888 | name, (FUInt32|FInt32) ->
8889 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8890 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8891 | name, FOptPercent ->
8892 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8893 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8895 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8896 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8898 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8900 pr " guestfs_free_%s_list (r);\n" typ;
8903 and generate_java_makefile_inc () =
8904 generate_header HashStyle GPLv2;
8906 pr "java_built_sources = \\\n";
8909 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8911 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8913 and generate_haskell_hs () =
8914 generate_header HaskellStyle LGPLv2;
8916 (* XXX We only know how to generate partial FFI for Haskell
8917 * at the moment. Please help out!
8919 let can_generate style =
8923 | RInt64 _, _ -> true
8926 | RConstOptString _, _
8932 | RBufferOut _, _ -> false in
8935 {-# INCLUDE <guestfs.h> #-}
8936 {-# LANGUAGE ForeignFunctionInterface #-}
8941 (* List out the names of the actions we want to export. *)
8943 fun (name, style, _, _, _, _, _) ->
8944 if can_generate style then pr ",\n %s" name
8951 import Foreign.C.Types
8953 import Control.Exception
8954 import Data.Typeable
8956 data GuestfsS = GuestfsS -- represents the opaque C struct
8957 type GuestfsP = Ptr GuestfsS -- guestfs_h *
8958 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8960 -- XXX define properly later XXX
8964 data IntBool = IntBool
8966 data StatVFS = StatVFS
8967 data Hashtable = Hashtable
8969 foreign import ccall unsafe \"guestfs_create\" c_create
8971 foreign import ccall unsafe \"&guestfs_close\" c_close
8972 :: FunPtr (GuestfsP -> IO ())
8973 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8974 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8976 create :: IO GuestfsH
8979 c_set_error_handler p nullPtr nullPtr
8980 h <- newForeignPtr c_close p
8983 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8984 :: GuestfsP -> IO CString
8986 -- last_error :: GuestfsH -> IO (Maybe String)
8987 -- last_error h = do
8988 -- str <- withForeignPtr h (\\p -> c_last_error p)
8989 -- maybePeek peekCString str
8991 last_error :: GuestfsH -> IO (String)
8993 str <- withForeignPtr h (\\p -> c_last_error p)
8995 then return \"no error\"
8996 else peekCString str
9000 (* Generate wrappers for each foreign function. *)
9002 fun (name, style, _, _, _, _, _) ->
9003 if can_generate style then (
9004 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9006 generate_haskell_prototype ~handle:"GuestfsP" style;
9010 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9012 pr "%s %s = do\n" name
9013 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9015 (* Convert pointer arguments using with* functions. *)
9020 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9021 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9022 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9023 | Bool _ | Int _ -> ()
9025 (* Convert integer arguments. *)
9029 | Bool n -> sprintf "(fromBool %s)" n
9030 | Int n -> sprintf "(fromIntegral %s)" n
9031 | FileIn n | FileOut n
9032 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9034 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9035 (String.concat " " ("p" :: args));
9036 (match fst style with
9037 | RErr | RInt _ | RInt64 _ | RBool _ ->
9038 pr " if (r == -1)\n";
9040 pr " err <- last_error h\n";
9042 | RConstString _ | RConstOptString _ | RString _
9043 | RStringList _ | RStruct _
9044 | RStructList _ | RHashtable _ | RBufferOut _ ->
9045 pr " if (r == nullPtr)\n";
9047 pr " err <- last_error h\n";
9050 (match fst style with
9052 pr " else return ()\n"
9054 pr " else return (fromIntegral r)\n"
9056 pr " else return (fromIntegral r)\n"
9058 pr " else return (toBool r)\n"
9067 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9073 and generate_haskell_prototype ~handle ?(hs = false) style =
9075 let string = if hs then "String" else "CString" in
9076 let int = if hs then "Int" else "CInt" in
9077 let bool = if hs then "Bool" else "CInt" in
9078 let int64 = if hs then "Integer" else "Int64" in
9082 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9083 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9084 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9085 | Bool _ -> pr "%s" bool
9086 | Int _ -> pr "%s" int
9087 | FileIn _ -> pr "%s" string
9088 | FileOut _ -> pr "%s" string
9093 (match fst style with
9094 | RErr -> if not hs then pr "CInt"
9095 | RInt _ -> pr "%s" int
9096 | RInt64 _ -> pr "%s" int64
9097 | RBool _ -> pr "%s" bool
9098 | RConstString _ -> pr "%s" string
9099 | RConstOptString _ -> pr "Maybe %s" string
9100 | RString _ -> pr "%s" string
9101 | RStringList _ -> pr "[%s]" string
9102 | RStruct (_, typ) ->
9103 let name = java_name_of_struct typ in
9105 | RStructList (_, typ) ->
9106 let name = java_name_of_struct typ in
9108 | RHashtable _ -> pr "Hashtable"
9109 | RBufferOut _ -> pr "%s" string
9113 and generate_bindtests () =
9114 generate_header CStyle LGPLv2;
9119 #include <inttypes.h>
9122 #include \"guestfs.h\"
9123 #include \"guestfs-internal-actions.h\"
9124 #include \"guestfs_protocol.h\"
9126 #define error guestfs_error
9127 #define safe_calloc guestfs_safe_calloc
9128 #define safe_malloc guestfs_safe_malloc
9131 print_strings (char *const *argv)
9136 for (argc = 0; argv[argc] != NULL; ++argc) {
9137 if (argc > 0) printf (\", \");
9138 printf (\"\\\"%%s\\\"\", argv[argc]);
9143 /* The test0 function prints its parameters to stdout. */
9147 match test_functions with
9148 | [] -> assert false
9149 | test0 :: tests -> test0, tests in
9152 let (name, style, _, _, _, _, _) = test0 in
9153 generate_prototype ~extern:false ~semicolon:false ~newline:true
9154 ~handle:"g" ~prefix:"guestfs__" name style;
9159 | Device n | Dev_or_Path n
9162 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
9163 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9164 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
9165 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9166 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
9168 pr " /* Java changes stdout line buffering so we need this: */\n";
9169 pr " fflush (stdout);\n";
9175 fun (name, style, _, _, _, _, _) ->
9176 if String.sub name (String.length name - 3) 3 <> "err" then (
9177 pr "/* Test normal return. */\n";
9178 generate_prototype ~extern:false ~semicolon:false ~newline:true
9179 ~handle:"g" ~prefix:"guestfs__" name style;
9181 (match fst style with
9186 pr " sscanf (val, \"%%d\", &r);\n";
9190 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
9193 pr " return strcmp (val, \"true\") == 0;\n"
9195 | RConstOptString _ ->
9196 (* Can't return the input string here. Return a static
9197 * string so we ensure we get a segfault if the caller
9200 pr " return \"static string\";\n"
9202 pr " return strdup (val);\n"
9204 pr " char **strs;\n";
9206 pr " sscanf (val, \"%%d\", &n);\n";
9207 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9208 pr " for (i = 0; i < n; ++i) {\n";
9209 pr " strs[i] = safe_malloc (g, 16);\n";
9210 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
9212 pr " strs[n] = NULL;\n";
9213 pr " return strs;\n"
9214 | RStruct (_, typ) ->
9215 pr " struct guestfs_%s *r;\n" typ;
9216 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9218 | RStructList (_, typ) ->
9219 pr " struct guestfs_%s_list *r;\n" typ;
9220 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9221 pr " sscanf (val, \"%%d\", &r->len);\n";
9222 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9225 pr " char **strs;\n";
9227 pr " sscanf (val, \"%%d\", &n);\n";
9228 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9229 pr " for (i = 0; i < n; ++i) {\n";
9230 pr " strs[i*2] = safe_malloc (g, 16);\n";
9231 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
9232 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
9233 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9235 pr " strs[n*2] = NULL;\n";
9236 pr " return strs;\n"
9238 pr " return strdup (val);\n"
9243 pr "/* Test error return. */\n";
9244 generate_prototype ~extern:false ~semicolon:false ~newline:true
9245 ~handle:"g" ~prefix:"guestfs__" name style;
9247 pr " error (g, \"error\");\n";
9248 (match fst style with
9249 | RErr | RInt _ | RInt64 _ | RBool _ ->
9251 | RConstString _ | RConstOptString _
9252 | RString _ | RStringList _ | RStruct _
9256 pr " return NULL;\n"
9263 and generate_ocaml_bindtests () =
9264 generate_header OCamlStyle GPLv2;
9268 let g = Guestfs.create () in
9275 | CallString s -> "\"" ^ s ^ "\""
9276 | CallOptString None -> "None"
9277 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9278 | CallStringList xs ->
9279 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9280 | CallInt i when i >= 0 -> string_of_int i
9281 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9282 | CallBool b -> string_of_bool b
9287 generate_lang_bindtests (
9288 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
9291 pr "print_endline \"EOF\"\n"
9293 and generate_perl_bindtests () =
9294 pr "#!/usr/bin/perl -w\n";
9295 generate_header HashStyle GPLv2;
9302 my $g = Sys::Guestfs->new ();
9306 String.concat ", " (
9309 | CallString s -> "\"" ^ s ^ "\""
9310 | CallOptString None -> "undef"
9311 | CallOptString (Some s) -> sprintf "\"%s\"" s
9312 | CallStringList xs ->
9313 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9314 | CallInt i -> string_of_int i
9315 | CallBool b -> if b then "1" else "0"
9320 generate_lang_bindtests (
9321 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9324 pr "print \"EOF\\n\"\n"
9326 and generate_python_bindtests () =
9327 generate_header HashStyle GPLv2;
9332 g = guestfs.GuestFS ()
9336 String.concat ", " (
9339 | CallString s -> "\"" ^ s ^ "\""
9340 | CallOptString None -> "None"
9341 | CallOptString (Some s) -> sprintf "\"%s\"" s
9342 | CallStringList xs ->
9343 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9344 | CallInt i -> string_of_int i
9345 | CallBool b -> if b then "1" else "0"
9350 generate_lang_bindtests (
9351 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9354 pr "print \"EOF\"\n"
9356 and generate_ruby_bindtests () =
9357 generate_header HashStyle GPLv2;
9362 g = Guestfs::create()
9366 String.concat ", " (
9369 | CallString s -> "\"" ^ s ^ "\""
9370 | CallOptString None -> "nil"
9371 | CallOptString (Some s) -> sprintf "\"%s\"" s
9372 | CallStringList xs ->
9373 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9374 | CallInt i -> string_of_int i
9375 | CallBool b -> string_of_bool b
9380 generate_lang_bindtests (
9381 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9384 pr "print \"EOF\\n\"\n"
9386 and generate_java_bindtests () =
9387 generate_header CStyle GPLv2;
9390 import com.redhat.et.libguestfs.*;
9392 public class Bindtests {
9393 public static void main (String[] argv)
9396 GuestFS g = new GuestFS ();
9400 String.concat ", " (
9403 | CallString s -> "\"" ^ s ^ "\""
9404 | CallOptString None -> "null"
9405 | CallOptString (Some s) -> sprintf "\"%s\"" s
9406 | CallStringList xs ->
9408 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9409 | CallInt i -> string_of_int i
9410 | CallBool b -> string_of_bool b
9415 generate_lang_bindtests (
9416 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9420 System.out.println (\"EOF\");
9422 catch (Exception exn) {
9423 System.err.println (exn);
9430 and generate_haskell_bindtests () =
9431 generate_header HaskellStyle GPLv2;
9434 module Bindtests where
9435 import qualified Guestfs
9445 | CallString s -> "\"" ^ s ^ "\""
9446 | CallOptString None -> "Nothing"
9447 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9448 | CallStringList xs ->
9449 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9450 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9451 | CallInt i -> string_of_int i
9452 | CallBool true -> "True"
9453 | CallBool false -> "False"
9458 generate_lang_bindtests (
9459 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9462 pr " putStrLn \"EOF\"\n"
9464 (* Language-independent bindings tests - we do it this way to
9465 * ensure there is parity in testing bindings across all languages.
9467 and generate_lang_bindtests call =
9468 call "test0" [CallString "abc"; CallOptString (Some "def");
9469 CallStringList []; CallBool false;
9470 CallInt 0; CallString "123"; CallString "456"];
9471 call "test0" [CallString "abc"; CallOptString None;
9472 CallStringList []; CallBool false;
9473 CallInt 0; CallString "123"; CallString "456"];
9474 call "test0" [CallString ""; CallOptString (Some "def");
9475 CallStringList []; CallBool false;
9476 CallInt 0; CallString "123"; CallString "456"];
9477 call "test0" [CallString ""; CallOptString (Some "");
9478 CallStringList []; CallBool false;
9479 CallInt 0; CallString "123"; CallString "456"];
9480 call "test0" [CallString "abc"; CallOptString (Some "def");
9481 CallStringList ["1"]; CallBool false;
9482 CallInt 0; CallString "123"; CallString "456"];
9483 call "test0" [CallString "abc"; CallOptString (Some "def");
9484 CallStringList ["1"; "2"]; CallBool false;
9485 CallInt 0; CallString "123"; CallString "456"];
9486 call "test0" [CallString "abc"; CallOptString (Some "def");
9487 CallStringList ["1"]; CallBool true;
9488 CallInt 0; CallString "123"; CallString "456"];
9489 call "test0" [CallString "abc"; CallOptString (Some "def");
9490 CallStringList ["1"]; CallBool false;
9491 CallInt (-1); CallString "123"; CallString "456"];
9492 call "test0" [CallString "abc"; CallOptString (Some "def");
9493 CallStringList ["1"]; CallBool false;
9494 CallInt (-2); CallString "123"; CallString "456"];
9495 call "test0" [CallString "abc"; CallOptString (Some "def");
9496 CallStringList ["1"]; CallBool false;
9497 CallInt 1; CallString "123"; CallString "456"];
9498 call "test0" [CallString "abc"; CallOptString (Some "def");
9499 CallStringList ["1"]; CallBool false;
9500 CallInt 2; CallString "123"; CallString "456"];
9501 call "test0" [CallString "abc"; CallOptString (Some "def");
9502 CallStringList ["1"]; CallBool false;
9503 CallInt 4095; CallString "123"; CallString "456"];
9504 call "test0" [CallString "abc"; CallOptString (Some "def");
9505 CallStringList ["1"]; CallBool false;
9506 CallInt 0; CallString ""; CallString ""]
9508 (* XXX Add here tests of the return and error functions. *)
9510 (* This is used to generate the src/MAX_PROC_NR file which
9511 * contains the maximum procedure number, a surrogate for the
9512 * ABI version number. See src/Makefile.am for the details.
9514 and generate_max_proc_nr () =
9515 let proc_nrs = List.map (
9516 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9517 ) daemon_functions in
9519 let max_proc_nr = List.fold_left max 0 proc_nrs in
9521 pr "%d\n" max_proc_nr
9523 let output_to filename =
9524 let filename_new = filename ^ ".new" in
9525 chan := open_out filename_new;
9530 (* Is the new file different from the current file? *)
9531 if Sys.file_exists filename && files_equal filename filename_new then
9532 Unix.unlink filename_new (* same, so skip it *)
9534 (* different, overwrite old one *)
9535 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9536 Unix.rename filename_new filename;
9537 Unix.chmod filename 0o444;
9538 printf "written %s\n%!" filename;
9547 if not (Sys.file_exists "HACKING") then (
9549 You are probably running this from the wrong directory.
9550 Run it from the top source directory using the command
9556 let close = output_to "src/guestfs_protocol.x" in
9560 let close = output_to "src/guestfs-structs.h" in
9561 generate_structs_h ();
9564 let close = output_to "src/guestfs-actions.h" in
9565 generate_actions_h ();
9568 let close = output_to "src/guestfs-internal-actions.h" in
9569 generate_internal_actions_h ();
9572 let close = output_to "src/guestfs-actions.c" in
9573 generate_client_actions ();
9576 let close = output_to "daemon/actions.h" in
9577 generate_daemon_actions_h ();
9580 let close = output_to "daemon/stubs.c" in
9581 generate_daemon_actions ();
9584 let close = output_to "daemon/names.c" in
9585 generate_daemon_names ();
9588 let close = output_to "capitests/tests.c" in
9592 let close = output_to "src/guestfs-bindtests.c" in
9593 generate_bindtests ();
9596 let close = output_to "fish/cmds.c" in
9597 generate_fish_cmds ();
9600 let close = output_to "fish/completion.c" in
9601 generate_fish_completion ();
9604 let close = output_to "guestfs-structs.pod" in
9605 generate_structs_pod ();
9608 let close = output_to "guestfs-actions.pod" in
9609 generate_actions_pod ();
9612 let close = output_to "guestfish-actions.pod" in
9613 generate_fish_actions_pod ();
9616 let close = output_to "ocaml/guestfs.mli" in
9617 generate_ocaml_mli ();
9620 let close = output_to "ocaml/guestfs.ml" in
9621 generate_ocaml_ml ();
9624 let close = output_to "ocaml/guestfs_c_actions.c" in
9625 generate_ocaml_c ();
9628 let close = output_to "ocaml/bindtests.ml" in
9629 generate_ocaml_bindtests ();
9632 let close = output_to "perl/Guestfs.xs" in
9633 generate_perl_xs ();
9636 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9637 generate_perl_pm ();
9640 let close = output_to "perl/bindtests.pl" in
9641 generate_perl_bindtests ();
9644 let close = output_to "python/guestfs-py.c" in
9645 generate_python_c ();
9648 let close = output_to "python/guestfs.py" in
9649 generate_python_py ();
9652 let close = output_to "python/bindtests.py" in
9653 generate_python_bindtests ();
9656 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9660 let close = output_to "ruby/bindtests.rb" in
9661 generate_ruby_bindtests ();
9664 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9665 generate_java_java ();
9670 let cols = cols_of_struct typ in
9671 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9672 let close = output_to filename in
9673 generate_java_struct jtyp cols;
9677 let close = output_to "java/Makefile.inc" in
9678 generate_java_makefile_inc ();
9681 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9685 let close = output_to "java/Bindtests.java" in
9686 generate_java_bindtests ();
9689 let close = output_to "haskell/Guestfs.hs" in
9690 generate_haskell_hs ();
9693 let close = output_to "haskell/Bindtests.hs" in
9694 generate_haskell_bindtests ();
9697 let close = output_to "src/MAX_PROC_NR" in
9698 generate_max_proc_nr ();
9701 (* Always generate this file last, and unconditionally. It's used
9702 * by the Makefile to know when we must re-run the generator.
9704 let chan = open_out "src/stamp-generator" in