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.");
811 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
812 [InitNone, Always, TestOutputFalse (
813 [["set_direct"; "false"];
815 "enable or disable direct appliance mode",
817 If the direct appliance mode flag is enabled, then stdin and
818 stdout are passed directly through to the appliance once it
821 One consequence of this is that log messages aren't caught
822 by the library and handled by C<guestfs_set_log_message_callback>,
823 but go straight to stdout.
825 You probably don't want to use this unless you know what you
828 The default is disabled.");
830 ("get_direct", (RBool "direct", []), -1, [],
832 "get direct appliance mode flag",
834 Return the direct appliance mode flag.");
838 (* daemon_functions are any functions which cause some action
839 * to take place in the daemon.
842 let daemon_functions = [
843 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
844 [InitEmpty, Always, TestOutput (
845 [["sfdiskM"; "/dev/sda"; ","];
846 ["mkfs"; "ext2"; "/dev/sda1"];
847 ["mount"; "/dev/sda1"; "/"];
848 ["write_file"; "/new"; "new file contents"; "0"];
849 ["cat"; "/new"]], "new file contents")],
850 "mount a guest disk at a position in the filesystem",
852 Mount a guest disk at a position in the filesystem. Block devices
853 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
854 the guest. If those block devices contain partitions, they will have
855 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
858 The rules are the same as for L<mount(2)>: A filesystem must
859 first be mounted on C</> before others can be mounted. Other
860 filesystems can only be mounted on directories which already
863 The mounted filesystem is writable, if we have sufficient permissions
864 on the underlying device.
866 The filesystem options C<sync> and C<noatime> are set with this
867 call, in order to improve reliability.");
869 ("sync", (RErr, []), 2, [],
870 [ InitEmpty, Always, TestRun [["sync"]]],
871 "sync disks, writes are flushed through to the disk image",
873 This syncs the disk, so that any writes are flushed through to the
874 underlying disk image.
876 You should always call this if you have modified a disk image, before
877 closing the handle.");
879 ("touch", (RErr, [Pathname "path"]), 3, [],
880 [InitBasicFS, Always, TestOutputTrue (
882 ["exists"; "/new"]])],
883 "update file timestamps or create a new file",
885 Touch acts like the L<touch(1)> command. It can be used to
886 update the timestamps on a file, or, if the file does not exist,
887 to create a new zero-length file.");
889 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
890 [InitISOFS, Always, TestOutput (
891 [["cat"; "/known-2"]], "abcdef\n")],
892 "list the contents of a file",
894 Return the contents of the file named C<path>.
896 Note that this function cannot correctly handle binary files
897 (specifically, files containing C<\\0> character which is treated
898 as end of string). For those you need to use the C<guestfs_read_file>
899 or C<guestfs_download> functions which have a more complex interface.");
901 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
902 [], (* XXX Tricky to test because it depends on the exact format
903 * of the 'ls -l' command, which changes between F10 and F11.
905 "list the files in a directory (long format)",
907 List the files in C<directory> (relative to the root directory,
908 there is no cwd) in the format of 'ls -la'.
910 This command is mostly useful for interactive sessions. It
911 is I<not> intended that you try to parse the output string.");
913 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
914 [InitBasicFS, Always, TestOutputList (
917 ["touch"; "/newest"];
918 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
919 "list the files in a directory",
921 List the files in C<directory> (relative to the root directory,
922 there is no cwd). The '.' and '..' entries are not returned, but
923 hidden files are shown.
925 This command is mostly useful for interactive sessions. Programs
926 should probably use C<guestfs_readdir> instead.");
928 ("list_devices", (RStringList "devices", []), 7, [],
929 [InitEmpty, Always, TestOutputListOfDevices (
930 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
931 "list the block devices",
933 List all the block devices.
935 The full block device names are returned, eg. C</dev/sda>");
937 ("list_partitions", (RStringList "partitions", []), 8, [],
938 [InitBasicFS, Always, TestOutputListOfDevices (
939 [["list_partitions"]], ["/dev/sda1"]);
940 InitEmpty, Always, TestOutputListOfDevices (
941 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
942 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
943 "list the partitions",
945 List all the partitions detected on all block devices.
947 The full partition device names are returned, eg. C</dev/sda1>
949 This does not return logical volumes. For that you will need to
950 call C<guestfs_lvs>.");
952 ("pvs", (RStringList "physvols", []), 9, [],
953 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
954 [["pvs"]], ["/dev/sda1"]);
955 InitEmpty, Always, TestOutputListOfDevices (
956 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
957 ["pvcreate"; "/dev/sda1"];
958 ["pvcreate"; "/dev/sda2"];
959 ["pvcreate"; "/dev/sda3"];
960 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
961 "list the LVM physical volumes (PVs)",
963 List all the physical volumes detected. This is the equivalent
964 of the L<pvs(8)> command.
966 This returns a list of just the device names that contain
967 PVs (eg. C</dev/sda2>).
969 See also C<guestfs_pvs_full>.");
971 ("vgs", (RStringList "volgroups", []), 10, [],
972 [InitBasicFSonLVM, Always, TestOutputList (
974 InitEmpty, Always, TestOutputList (
975 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
976 ["pvcreate"; "/dev/sda1"];
977 ["pvcreate"; "/dev/sda2"];
978 ["pvcreate"; "/dev/sda3"];
979 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
980 ["vgcreate"; "VG2"; "/dev/sda3"];
981 ["vgs"]], ["VG1"; "VG2"])],
982 "list the LVM volume groups (VGs)",
984 List all the volumes groups detected. This is the equivalent
985 of the L<vgs(8)> command.
987 This returns a list of just the volume group names that were
988 detected (eg. C<VolGroup00>).
990 See also C<guestfs_vgs_full>.");
992 ("lvs", (RStringList "logvols", []), 11, [],
993 [InitBasicFSonLVM, Always, TestOutputList (
994 [["lvs"]], ["/dev/VG/LV"]);
995 InitEmpty, Always, TestOutputList (
996 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
997 ["pvcreate"; "/dev/sda1"];
998 ["pvcreate"; "/dev/sda2"];
999 ["pvcreate"; "/dev/sda3"];
1000 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1001 ["vgcreate"; "VG2"; "/dev/sda3"];
1002 ["lvcreate"; "LV1"; "VG1"; "50"];
1003 ["lvcreate"; "LV2"; "VG1"; "50"];
1004 ["lvcreate"; "LV3"; "VG2"; "50"];
1005 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1006 "list the LVM logical volumes (LVs)",
1008 List all the logical volumes detected. This is the equivalent
1009 of the L<lvs(8)> command.
1011 This returns a list of the logical volume device names
1012 (eg. C</dev/VolGroup00/LogVol00>).
1014 See also C<guestfs_lvs_full>.");
1016 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1017 [], (* XXX how to test? *)
1018 "list the LVM physical volumes (PVs)",
1020 List all the physical volumes detected. This is the equivalent
1021 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1023 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1024 [], (* XXX how to test? *)
1025 "list the LVM volume groups (VGs)",
1027 List all the volumes groups detected. This is the equivalent
1028 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1030 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1031 [], (* XXX how to test? *)
1032 "list the LVM logical volumes (LVs)",
1034 List all the logical volumes detected. This is the equivalent
1035 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1037 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1038 [InitISOFS, Always, TestOutputList (
1039 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1040 InitISOFS, Always, TestOutputList (
1041 [["read_lines"; "/empty"]], [])],
1042 "read file as lines",
1044 Return the contents of the file named C<path>.
1046 The file contents are returned as a list of lines. Trailing
1047 C<LF> and C<CRLF> character sequences are I<not> returned.
1049 Note that this function cannot correctly handle binary files
1050 (specifically, files containing C<\\0> character which is treated
1051 as end of line). For those you need to use the C<guestfs_read_file>
1052 function which has a more complex interface.");
1054 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1055 [], (* XXX Augeas code needs tests. *)
1056 "create a new Augeas handle",
1058 Create a new Augeas handle for editing configuration files.
1059 If there was any previous Augeas handle associated with this
1060 guestfs session, then it is closed.
1062 You must call this before using any other C<guestfs_aug_*>
1065 C<root> is the filesystem root. C<root> must not be NULL,
1068 The flags are the same as the flags defined in
1069 E<lt>augeas.hE<gt>, the logical I<or> of the following
1074 =item C<AUG_SAVE_BACKUP> = 1
1076 Keep the original file with a C<.augsave> extension.
1078 =item C<AUG_SAVE_NEWFILE> = 2
1080 Save changes into a file with extension C<.augnew>, and
1081 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1083 =item C<AUG_TYPE_CHECK> = 4
1085 Typecheck lenses (can be expensive).
1087 =item C<AUG_NO_STDINC> = 8
1089 Do not use standard load path for modules.
1091 =item C<AUG_SAVE_NOOP> = 16
1093 Make save a no-op, just record what would have been changed.
1095 =item C<AUG_NO_LOAD> = 32
1097 Do not load the tree in C<guestfs_aug_init>.
1101 To close the handle, you can call C<guestfs_aug_close>.
1103 To find out more about Augeas, see L<http://augeas.net/>.");
1105 ("aug_close", (RErr, []), 26, [],
1106 [], (* XXX Augeas code needs tests. *)
1107 "close the current Augeas handle",
1109 Close the current Augeas handle and free up any resources
1110 used by it. After calling this, you have to call
1111 C<guestfs_aug_init> again before you can use any other
1112 Augeas functions.");
1114 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1115 [], (* XXX Augeas code needs tests. *)
1116 "define an Augeas variable",
1118 Defines an Augeas variable C<name> whose value is the result
1119 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1122 On success this returns the number of nodes in C<expr>, or
1123 C<0> if C<expr> evaluates to something which is not a nodeset.");
1125 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1126 [], (* XXX Augeas code needs tests. *)
1127 "define an Augeas node",
1129 Defines a variable C<name> whose value is the result of
1132 If C<expr> evaluates to an empty nodeset, a node is created,
1133 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1134 C<name> will be the nodeset containing that single node.
1136 On success this returns a pair containing the
1137 number of nodes in the nodeset, and a boolean flag
1138 if a node was created.");
1140 ("aug_get", (RString "val", [String "augpath"]), 19, [],
1141 [], (* XXX Augeas code needs tests. *)
1142 "look up the value of an Augeas path",
1144 Look up the value associated with C<path>. If C<path>
1145 matches exactly one node, the C<value> is returned.");
1147 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1148 [], (* XXX Augeas code needs tests. *)
1149 "set Augeas path to value",
1151 Set the value associated with C<path> to C<value>.");
1153 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1154 [], (* XXX Augeas code needs tests. *)
1155 "insert a sibling Augeas node",
1157 Create a new sibling C<label> for C<path>, inserting it into
1158 the tree before or after C<path> (depending on the boolean
1161 C<path> must match exactly one existing node in the tree, and
1162 C<label> must be a label, ie. not contain C</>, C<*> or end
1163 with a bracketed index C<[N]>.");
1165 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1166 [], (* XXX Augeas code needs tests. *)
1167 "remove an Augeas path",
1169 Remove C<path> and all of its children.
1171 On success this returns the number of entries which were removed.");
1173 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1174 [], (* XXX Augeas code needs tests. *)
1177 Move the node C<src> to C<dest>. C<src> must match exactly
1178 one node. C<dest> is overwritten if it exists.");
1180 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1181 [], (* XXX Augeas code needs tests. *)
1182 "return Augeas nodes which match augpath",
1184 Returns a list of paths which match the path expression C<path>.
1185 The returned paths are sufficiently qualified so that they match
1186 exactly one node in the current tree.");
1188 ("aug_save", (RErr, []), 25, [],
1189 [], (* XXX Augeas code needs tests. *)
1190 "write all pending Augeas changes to disk",
1192 This writes all pending changes to disk.
1194 The flags which were passed to C<guestfs_aug_init> affect exactly
1195 how files are saved.");
1197 ("aug_load", (RErr, []), 27, [],
1198 [], (* XXX Augeas code needs tests. *)
1199 "load files into the tree",
1201 Load files into the tree.
1203 See C<aug_load> in the Augeas documentation for the full gory
1206 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1207 [], (* XXX Augeas code needs tests. *)
1208 "list Augeas nodes under augpath",
1210 This is just a shortcut for listing C<guestfs_aug_match>
1211 C<path/*> and sorting the resulting nodes into alphabetical order.");
1213 ("rm", (RErr, [Pathname "path"]), 29, [],
1214 [InitBasicFS, Always, TestRun
1217 InitBasicFS, Always, TestLastFail
1219 InitBasicFS, Always, TestLastFail
1224 Remove the single file C<path>.");
1226 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1227 [InitBasicFS, Always, TestRun
1230 InitBasicFS, Always, TestLastFail
1231 [["rmdir"; "/new"]];
1232 InitBasicFS, Always, TestLastFail
1234 ["rmdir"; "/new"]]],
1235 "remove a directory",
1237 Remove the single directory C<path>.");
1239 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1240 [InitBasicFS, Always, TestOutputFalse
1242 ["mkdir"; "/new/foo"];
1243 ["touch"; "/new/foo/bar"];
1245 ["exists"; "/new"]]],
1246 "remove a file or directory recursively",
1248 Remove the file or directory C<path>, recursively removing the
1249 contents if its a directory. This is like the C<rm -rf> shell
1252 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1253 [InitBasicFS, Always, TestOutputTrue
1255 ["is_dir"; "/new"]];
1256 InitBasicFS, Always, TestLastFail
1257 [["mkdir"; "/new/foo/bar"]]],
1258 "create a directory",
1260 Create a directory named C<path>.");
1262 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1263 [InitBasicFS, Always, TestOutputTrue
1264 [["mkdir_p"; "/new/foo/bar"];
1265 ["is_dir"; "/new/foo/bar"]];
1266 InitBasicFS, Always, TestOutputTrue
1267 [["mkdir_p"; "/new/foo/bar"];
1268 ["is_dir"; "/new/foo"]];
1269 InitBasicFS, Always, TestOutputTrue
1270 [["mkdir_p"; "/new/foo/bar"];
1271 ["is_dir"; "/new"]];
1272 (* Regression tests for RHBZ#503133: *)
1273 InitBasicFS, Always, TestRun
1275 ["mkdir_p"; "/new"]];
1276 InitBasicFS, Always, TestLastFail
1278 ["mkdir_p"; "/new"]]],
1279 "create a directory and parents",
1281 Create a directory named C<path>, creating any parent directories
1282 as necessary. This is like the C<mkdir -p> shell command.");
1284 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1285 [], (* XXX Need stat command to test *)
1288 Change the mode (permissions) of C<path> to C<mode>. Only
1289 numeric modes are supported.");
1291 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1292 [], (* XXX Need stat command to test *)
1293 "change file owner and group",
1295 Change the file owner to C<owner> and group to C<group>.
1297 Only numeric uid and gid are supported. If you want to use
1298 names, you will need to locate and parse the password file
1299 yourself (Augeas support makes this relatively easy).");
1301 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1302 [InitISOFS, Always, TestOutputTrue (
1303 [["exists"; "/empty"]]);
1304 InitISOFS, Always, TestOutputTrue (
1305 [["exists"; "/directory"]])],
1306 "test if file or directory exists",
1308 This returns C<true> if and only if there is a file, directory
1309 (or anything) with the given C<path> name.
1311 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1313 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1314 [InitISOFS, Always, TestOutputTrue (
1315 [["is_file"; "/known-1"]]);
1316 InitISOFS, Always, TestOutputFalse (
1317 [["is_file"; "/directory"]])],
1318 "test if file exists",
1320 This returns C<true> if and only if there is a file
1321 with the given C<path> name. Note that it returns false for
1322 other objects like directories.
1324 See also C<guestfs_stat>.");
1326 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1327 [InitISOFS, Always, TestOutputFalse (
1328 [["is_dir"; "/known-3"]]);
1329 InitISOFS, Always, TestOutputTrue (
1330 [["is_dir"; "/directory"]])],
1331 "test if file exists",
1333 This returns C<true> if and only if there is a directory
1334 with the given C<path> name. Note that it returns false for
1335 other objects like files.
1337 See also C<guestfs_stat>.");
1339 ("pvcreate", (RErr, [Device "device"]), 39, [],
1340 [InitEmpty, Always, TestOutputListOfDevices (
1341 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1342 ["pvcreate"; "/dev/sda1"];
1343 ["pvcreate"; "/dev/sda2"];
1344 ["pvcreate"; "/dev/sda3"];
1345 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1346 "create an LVM physical volume",
1348 This creates an LVM physical volume on the named C<device>,
1349 where C<device> should usually be a partition name such
1352 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1353 [InitEmpty, Always, TestOutputList (
1354 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1355 ["pvcreate"; "/dev/sda1"];
1356 ["pvcreate"; "/dev/sda2"];
1357 ["pvcreate"; "/dev/sda3"];
1358 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1359 ["vgcreate"; "VG2"; "/dev/sda3"];
1360 ["vgs"]], ["VG1"; "VG2"])],
1361 "create an LVM volume group",
1363 This creates an LVM volume group called C<volgroup>
1364 from the non-empty list of physical volumes C<physvols>.");
1366 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1367 [InitEmpty, Always, TestOutputList (
1368 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1369 ["pvcreate"; "/dev/sda1"];
1370 ["pvcreate"; "/dev/sda2"];
1371 ["pvcreate"; "/dev/sda3"];
1372 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1373 ["vgcreate"; "VG2"; "/dev/sda3"];
1374 ["lvcreate"; "LV1"; "VG1"; "50"];
1375 ["lvcreate"; "LV2"; "VG1"; "50"];
1376 ["lvcreate"; "LV3"; "VG2"; "50"];
1377 ["lvcreate"; "LV4"; "VG2"; "50"];
1378 ["lvcreate"; "LV5"; "VG2"; "50"];
1380 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1381 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1382 "create an LVM volume group",
1384 This creates an LVM volume group called C<logvol>
1385 on the volume group C<volgroup>, with C<size> megabytes.");
1387 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1388 [InitEmpty, Always, TestOutput (
1389 [["sfdiskM"; "/dev/sda"; ","];
1390 ["mkfs"; "ext2"; "/dev/sda1"];
1391 ["mount"; "/dev/sda1"; "/"];
1392 ["write_file"; "/new"; "new file contents"; "0"];
1393 ["cat"; "/new"]], "new file contents")],
1394 "make a filesystem",
1396 This creates a filesystem on C<device> (usually a partition
1397 or LVM logical volume). The filesystem type is C<fstype>, for
1400 ("sfdisk", (RErr, [Device "device";
1401 Int "cyls"; Int "heads"; Int "sectors";
1402 StringList "lines"]), 43, [DangerWillRobinson],
1404 "create partitions on a block device",
1406 This is a direct interface to the L<sfdisk(8)> program for creating
1407 partitions on block devices.
1409 C<device> should be a block device, for example C</dev/sda>.
1411 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1412 and sectors on the device, which are passed directly to sfdisk as
1413 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1414 of these, then the corresponding parameter is omitted. Usually for
1415 'large' disks, you can just pass C<0> for these, but for small
1416 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1417 out the right geometry and you will need to tell it.
1419 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1420 information refer to the L<sfdisk(8)> manpage.
1422 To create a single partition occupying the whole disk, you would
1423 pass C<lines> as a single element list, when the single element being
1424 the string C<,> (comma).
1426 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1428 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1429 [InitBasicFS, Always, TestOutput (
1430 [["write_file"; "/new"; "new file contents"; "0"];
1431 ["cat"; "/new"]], "new file contents");
1432 InitBasicFS, Always, TestOutput (
1433 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1434 ["cat"; "/new"]], "\nnew file contents\n");
1435 InitBasicFS, Always, TestOutput (
1436 [["write_file"; "/new"; "\n\n"; "0"];
1437 ["cat"; "/new"]], "\n\n");
1438 InitBasicFS, Always, TestOutput (
1439 [["write_file"; "/new"; ""; "0"];
1440 ["cat"; "/new"]], "");
1441 InitBasicFS, Always, TestOutput (
1442 [["write_file"; "/new"; "\n\n\n"; "0"];
1443 ["cat"; "/new"]], "\n\n\n");
1444 InitBasicFS, Always, TestOutput (
1445 [["write_file"; "/new"; "\n"; "0"];
1446 ["cat"; "/new"]], "\n")],
1449 This call creates a file called C<path>. The contents of the
1450 file is the string C<content> (which can contain any 8 bit data),
1451 with length C<size>.
1453 As a special case, if C<size> is C<0>
1454 then the length is calculated using C<strlen> (so in this case
1455 the content cannot contain embedded ASCII NULs).
1457 I<NB.> Owing to a bug, writing content containing ASCII NUL
1458 characters does I<not> work, even if the length is specified.
1459 We hope to resolve this bug in a future version. In the meantime
1460 use C<guestfs_upload>.");
1462 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1463 [InitEmpty, Always, TestOutputListOfDevices (
1464 [["sfdiskM"; "/dev/sda"; ","];
1465 ["mkfs"; "ext2"; "/dev/sda1"];
1466 ["mount"; "/dev/sda1"; "/"];
1467 ["mounts"]], ["/dev/sda1"]);
1468 InitEmpty, Always, TestOutputList (
1469 [["sfdiskM"; "/dev/sda"; ","];
1470 ["mkfs"; "ext2"; "/dev/sda1"];
1471 ["mount"; "/dev/sda1"; "/"];
1474 "unmount a filesystem",
1476 This unmounts the given filesystem. The filesystem may be
1477 specified either by its mountpoint (path) or the device which
1478 contains the filesystem.");
1480 ("mounts", (RStringList "devices", []), 46, [],
1481 [InitBasicFS, Always, TestOutputListOfDevices (
1482 [["mounts"]], ["/dev/sda1"])],
1483 "show mounted filesystems",
1485 This returns the list of currently mounted filesystems. It returns
1486 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1488 Some internal mounts are not shown.
1490 See also: C<guestfs_mountpoints>");
1492 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1493 [InitBasicFS, Always, TestOutputList (
1496 (* check that umount_all can unmount nested mounts correctly: *)
1497 InitEmpty, Always, TestOutputList (
1498 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1499 ["mkfs"; "ext2"; "/dev/sda1"];
1500 ["mkfs"; "ext2"; "/dev/sda2"];
1501 ["mkfs"; "ext2"; "/dev/sda3"];
1502 ["mount"; "/dev/sda1"; "/"];
1504 ["mount"; "/dev/sda2"; "/mp1"];
1505 ["mkdir"; "/mp1/mp2"];
1506 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1507 ["mkdir"; "/mp1/mp2/mp3"];
1510 "unmount all filesystems",
1512 This unmounts all mounted filesystems.
1514 Some internal mounts are not unmounted by this call.");
1516 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1518 "remove all LVM LVs, VGs and PVs",
1520 This command removes all LVM logical volumes, volume groups
1521 and physical volumes.");
1523 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1524 [InitISOFS, Always, TestOutput (
1525 [["file"; "/empty"]], "empty");
1526 InitISOFS, Always, TestOutput (
1527 [["file"; "/known-1"]], "ASCII text");
1528 InitISOFS, Always, TestLastFail (
1529 [["file"; "/notexists"]])],
1530 "determine file type",
1532 This call uses the standard L<file(1)> command to determine
1533 the type or contents of the file. This also works on devices,
1534 for example to find out whether a partition contains a filesystem.
1536 This call will also transparently look inside various types
1539 The exact command which runs is C<file -zbsL path>. Note in
1540 particular that the filename is not prepended to the output
1541 (the C<-b> option).");
1543 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1544 [InitBasicFS, Always, TestOutput (
1545 [["upload"; "test-command"; "/test-command"];
1546 ["chmod"; "0o755"; "/test-command"];
1547 ["command"; "/test-command 1"]], "Result1");
1548 InitBasicFS, Always, TestOutput (
1549 [["upload"; "test-command"; "/test-command"];
1550 ["chmod"; "0o755"; "/test-command"];
1551 ["command"; "/test-command 2"]], "Result2\n");
1552 InitBasicFS, Always, TestOutput (
1553 [["upload"; "test-command"; "/test-command"];
1554 ["chmod"; "0o755"; "/test-command"];
1555 ["command"; "/test-command 3"]], "\nResult3");
1556 InitBasicFS, Always, TestOutput (
1557 [["upload"; "test-command"; "/test-command"];
1558 ["chmod"; "0o755"; "/test-command"];
1559 ["command"; "/test-command 4"]], "\nResult4\n");
1560 InitBasicFS, Always, TestOutput (
1561 [["upload"; "test-command"; "/test-command"];
1562 ["chmod"; "0o755"; "/test-command"];
1563 ["command"; "/test-command 5"]], "\nResult5\n\n");
1564 InitBasicFS, Always, TestOutput (
1565 [["upload"; "test-command"; "/test-command"];
1566 ["chmod"; "0o755"; "/test-command"];
1567 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1568 InitBasicFS, Always, TestOutput (
1569 [["upload"; "test-command"; "/test-command"];
1570 ["chmod"; "0o755"; "/test-command"];
1571 ["command"; "/test-command 7"]], "");
1572 InitBasicFS, Always, TestOutput (
1573 [["upload"; "test-command"; "/test-command"];
1574 ["chmod"; "0o755"; "/test-command"];
1575 ["command"; "/test-command 8"]], "\n");
1576 InitBasicFS, Always, TestOutput (
1577 [["upload"; "test-command"; "/test-command"];
1578 ["chmod"; "0o755"; "/test-command"];
1579 ["command"; "/test-command 9"]], "\n\n");
1580 InitBasicFS, Always, TestOutput (
1581 [["upload"; "test-command"; "/test-command"];
1582 ["chmod"; "0o755"; "/test-command"];
1583 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1584 InitBasicFS, Always, TestOutput (
1585 [["upload"; "test-command"; "/test-command"];
1586 ["chmod"; "0o755"; "/test-command"];
1587 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1588 InitBasicFS, Always, TestLastFail (
1589 [["upload"; "test-command"; "/test-command"];
1590 ["chmod"; "0o755"; "/test-command"];
1591 ["command"; "/test-command"]])],
1592 "run a command from the guest filesystem",
1594 This call runs a command from the guest filesystem. The
1595 filesystem must be mounted, and must contain a compatible
1596 operating system (ie. something Linux, with the same
1597 or compatible processor architecture).
1599 The single parameter is an argv-style list of arguments.
1600 The first element is the name of the program to run.
1601 Subsequent elements are parameters. The list must be
1602 non-empty (ie. must contain a program name). Note that
1603 the command runs directly, and is I<not> invoked via
1604 the shell (see C<guestfs_sh>).
1606 The return value is anything printed to I<stdout> by
1609 If the command returns a non-zero exit status, then
1610 this function returns an error message. The error message
1611 string is the content of I<stderr> from the command.
1613 The C<$PATH> environment variable will contain at least
1614 C</usr/bin> and C</bin>. If you require a program from
1615 another location, you should provide the full path in the
1618 Shared libraries and data files required by the program
1619 must be available on filesystems which are mounted in the
1620 correct places. It is the caller's responsibility to ensure
1621 all filesystems that are needed are mounted at the right
1624 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1625 [InitBasicFS, Always, TestOutputList (
1626 [["upload"; "test-command"; "/test-command"];
1627 ["chmod"; "0o755"; "/test-command"];
1628 ["command_lines"; "/test-command 1"]], ["Result1"]);
1629 InitBasicFS, Always, TestOutputList (
1630 [["upload"; "test-command"; "/test-command"];
1631 ["chmod"; "0o755"; "/test-command"];
1632 ["command_lines"; "/test-command 2"]], ["Result2"]);
1633 InitBasicFS, Always, TestOutputList (
1634 [["upload"; "test-command"; "/test-command"];
1635 ["chmod"; "0o755"; "/test-command"];
1636 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1637 InitBasicFS, Always, TestOutputList (
1638 [["upload"; "test-command"; "/test-command"];
1639 ["chmod"; "0o755"; "/test-command"];
1640 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1641 InitBasicFS, Always, TestOutputList (
1642 [["upload"; "test-command"; "/test-command"];
1643 ["chmod"; "0o755"; "/test-command"];
1644 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1645 InitBasicFS, Always, TestOutputList (
1646 [["upload"; "test-command"; "/test-command"];
1647 ["chmod"; "0o755"; "/test-command"];
1648 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1649 InitBasicFS, Always, TestOutputList (
1650 [["upload"; "test-command"; "/test-command"];
1651 ["chmod"; "0o755"; "/test-command"];
1652 ["command_lines"; "/test-command 7"]], []);
1653 InitBasicFS, Always, TestOutputList (
1654 [["upload"; "test-command"; "/test-command"];
1655 ["chmod"; "0o755"; "/test-command"];
1656 ["command_lines"; "/test-command 8"]], [""]);
1657 InitBasicFS, Always, TestOutputList (
1658 [["upload"; "test-command"; "/test-command"];
1659 ["chmod"; "0o755"; "/test-command"];
1660 ["command_lines"; "/test-command 9"]], ["";""]);
1661 InitBasicFS, Always, TestOutputList (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1665 InitBasicFS, Always, TestOutputList (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1669 "run a command, returning lines",
1671 This is the same as C<guestfs_command>, but splits the
1672 result into a list of lines.
1674 See also: C<guestfs_sh_lines>");
1676 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1677 [InitISOFS, Always, TestOutputStruct (
1678 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1679 "get file information",
1681 Returns file information for the given C<path>.
1683 This is the same as the C<stat(2)> system call.");
1685 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1686 [InitISOFS, Always, TestOutputStruct (
1687 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1688 "get file information for a symbolic link",
1690 Returns file information for the given C<path>.
1692 This is the same as C<guestfs_stat> except that if C<path>
1693 is a symbolic link, then the link is stat-ed, not the file it
1696 This is the same as the C<lstat(2)> system call.");
1698 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1699 [InitISOFS, Always, TestOutputStruct (
1700 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1701 "get file system statistics",
1703 Returns file system statistics for any mounted file system.
1704 C<path> should be a file or directory in the mounted file system
1705 (typically it is the mount point itself, but it doesn't need to be).
1707 This is the same as the C<statvfs(2)> system call.");
1709 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1711 "get ext2/ext3/ext4 superblock details",
1713 This returns the contents of the ext2, ext3 or ext4 filesystem
1714 superblock on C<device>.
1716 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1717 manpage for more details. The list of fields returned isn't
1718 clearly defined, and depends on both the version of C<tune2fs>
1719 that libguestfs was built against, and the filesystem itself.");
1721 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1722 [InitEmpty, Always, TestOutputTrue (
1723 [["blockdev_setro"; "/dev/sda"];
1724 ["blockdev_getro"; "/dev/sda"]])],
1725 "set block device to read-only",
1727 Sets the block device named C<device> to read-only.
1729 This uses the L<blockdev(8)> command.");
1731 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1732 [InitEmpty, Always, TestOutputFalse (
1733 [["blockdev_setrw"; "/dev/sda"];
1734 ["blockdev_getro"; "/dev/sda"]])],
1735 "set block device to read-write",
1737 Sets the block device named C<device> to read-write.
1739 This uses the L<blockdev(8)> command.");
1741 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1742 [InitEmpty, Always, TestOutputTrue (
1743 [["blockdev_setro"; "/dev/sda"];
1744 ["blockdev_getro"; "/dev/sda"]])],
1745 "is block device set to read-only",
1747 Returns a boolean indicating if the block device is read-only
1748 (true if read-only, false if not).
1750 This uses the L<blockdev(8)> command.");
1752 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1753 [InitEmpty, Always, TestOutputInt (
1754 [["blockdev_getss"; "/dev/sda"]], 512)],
1755 "get sectorsize of block device",
1757 This returns the size of sectors on a block device.
1758 Usually 512, but can be larger for modern devices.
1760 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1763 This uses the L<blockdev(8)> command.");
1765 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1766 [InitEmpty, Always, TestOutputInt (
1767 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1768 "get blocksize of block device",
1770 This returns the block size of a device.
1772 (Note this is different from both I<size in blocks> and
1773 I<filesystem block size>).
1775 This uses the L<blockdev(8)> command.");
1777 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1779 "set blocksize of block device",
1781 This sets the block size of a device.
1783 (Note this is different from both I<size in blocks> and
1784 I<filesystem block size>).
1786 This uses the L<blockdev(8)> command.");
1788 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1789 [InitEmpty, Always, TestOutputInt (
1790 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1791 "get total size of device in 512-byte sectors",
1793 This returns the size of the device in units of 512-byte sectors
1794 (even if the sectorsize isn't 512 bytes ... weird).
1796 See also C<guestfs_blockdev_getss> for the real sector size of
1797 the device, and C<guestfs_blockdev_getsize64> for the more
1798 useful I<size in bytes>.
1800 This uses the L<blockdev(8)> command.");
1802 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1803 [InitEmpty, Always, TestOutputInt (
1804 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1805 "get total size of device in bytes",
1807 This returns the size of the device in bytes.
1809 See also C<guestfs_blockdev_getsz>.
1811 This uses the L<blockdev(8)> command.");
1813 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1814 [InitEmpty, Always, TestRun
1815 [["blockdev_flushbufs"; "/dev/sda"]]],
1816 "flush device buffers",
1818 This tells the kernel to flush internal buffers associated
1821 This uses the L<blockdev(8)> command.");
1823 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1824 [InitEmpty, Always, TestRun
1825 [["blockdev_rereadpt"; "/dev/sda"]]],
1826 "reread partition table",
1828 Reread the partition table on C<device>.
1830 This uses the L<blockdev(8)> command.");
1832 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1833 [InitBasicFS, Always, TestOutput (
1834 (* Pick a file from cwd which isn't likely to change. *)
1835 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1836 ["checksum"; "md5"; "/COPYING.LIB"]],
1837 Digest.to_hex (Digest.file "COPYING.LIB"))],
1838 "upload a file from the local machine",
1840 Upload local file C<filename> to C<remotefilename> on the
1843 C<filename> can also be a named pipe.
1845 See also C<guestfs_download>.");
1847 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1848 [InitBasicFS, Always, TestOutput (
1849 (* Pick a file from cwd which isn't likely to change. *)
1850 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1851 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1852 ["upload"; "testdownload.tmp"; "/upload"];
1853 ["checksum"; "md5"; "/upload"]],
1854 Digest.to_hex (Digest.file "COPYING.LIB"))],
1855 "download a file to the local machine",
1857 Download file C<remotefilename> and save it as C<filename>
1858 on the local machine.
1860 C<filename> can also be a named pipe.
1862 See also C<guestfs_upload>, C<guestfs_cat>.");
1864 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1865 [InitISOFS, Always, TestOutput (
1866 [["checksum"; "crc"; "/known-3"]], "2891671662");
1867 InitISOFS, Always, TestLastFail (
1868 [["checksum"; "crc"; "/notexists"]]);
1869 InitISOFS, Always, TestOutput (
1870 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1871 InitISOFS, Always, TestOutput (
1872 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1873 InitISOFS, Always, TestOutput (
1874 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1875 InitISOFS, Always, TestOutput (
1876 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1877 InitISOFS, Always, TestOutput (
1878 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1879 InitISOFS, Always, TestOutput (
1880 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1881 "compute MD5, SHAx or CRC checksum of file",
1883 This call computes the MD5, SHAx or CRC checksum of the
1886 The type of checksum to compute is given by the C<csumtype>
1887 parameter which must have one of the following values:
1893 Compute the cyclic redundancy check (CRC) specified by POSIX
1894 for the C<cksum> command.
1898 Compute the MD5 hash (using the C<md5sum> program).
1902 Compute the SHA1 hash (using the C<sha1sum> program).
1906 Compute the SHA224 hash (using the C<sha224sum> program).
1910 Compute the SHA256 hash (using the C<sha256sum> program).
1914 Compute the SHA384 hash (using the C<sha384sum> program).
1918 Compute the SHA512 hash (using the C<sha512sum> program).
1922 The checksum is returned as a printable string.");
1924 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1925 [InitBasicFS, Always, TestOutput (
1926 [["tar_in"; "../images/helloworld.tar"; "/"];
1927 ["cat"; "/hello"]], "hello\n")],
1928 "unpack tarfile to directory",
1930 This command uploads and unpacks local file C<tarfile> (an
1931 I<uncompressed> tar file) into C<directory>.
1933 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1935 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1937 "pack directory into tarfile",
1939 This command packs the contents of C<directory> and downloads
1940 it to local file C<tarfile>.
1942 To download a compressed tarball, use C<guestfs_tgz_out>.");
1944 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1945 [InitBasicFS, Always, TestOutput (
1946 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1947 ["cat"; "/hello"]], "hello\n")],
1948 "unpack compressed tarball to directory",
1950 This command uploads and unpacks local file C<tarball> (a
1951 I<gzip compressed> tar file) into C<directory>.
1953 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1955 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1957 "pack directory into compressed tarball",
1959 This command packs the contents of C<directory> and downloads
1960 it to local file C<tarball>.
1962 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1964 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1965 [InitBasicFS, Always, TestLastFail (
1967 ["mount_ro"; "/dev/sda1"; "/"];
1968 ["touch"; "/new"]]);
1969 InitBasicFS, Always, TestOutput (
1970 [["write_file"; "/new"; "data"; "0"];
1972 ["mount_ro"; "/dev/sda1"; "/"];
1973 ["cat"; "/new"]], "data")],
1974 "mount a guest disk, read-only",
1976 This is the same as the C<guestfs_mount> command, but it
1977 mounts the filesystem with the read-only (I<-o ro>) flag.");
1979 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1981 "mount a guest disk with mount options",
1983 This is the same as the C<guestfs_mount> command, but it
1984 allows you to set the mount options as for the
1985 L<mount(8)> I<-o> flag.");
1987 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1989 "mount a guest disk with mount options and vfstype",
1991 This is the same as the C<guestfs_mount> command, but it
1992 allows you to set both the mount options and the vfstype
1993 as for the L<mount(8)> I<-o> and I<-t> flags.");
1995 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1997 "debugging and internals",
1999 The C<guestfs_debug> command exposes some internals of
2000 C<guestfsd> (the guestfs daemon) that runs inside the
2003 There is no comprehensive help for this command. You have
2004 to look at the file C<daemon/debug.c> in the libguestfs source
2005 to find out what you can do.");
2007 ("lvremove", (RErr, [Device "device"]), 77, [],
2008 [InitEmpty, Always, TestOutputList (
2009 [["sfdiskM"; "/dev/sda"; ","];
2010 ["pvcreate"; "/dev/sda1"];
2011 ["vgcreate"; "VG"; "/dev/sda1"];
2012 ["lvcreate"; "LV1"; "VG"; "50"];
2013 ["lvcreate"; "LV2"; "VG"; "50"];
2014 ["lvremove"; "/dev/VG/LV1"];
2015 ["lvs"]], ["/dev/VG/LV2"]);
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"];
2022 ["lvremove"; "/dev/VG"];
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"];
2030 ["lvremove"; "/dev/VG"];
2032 "remove an LVM logical volume",
2034 Remove an LVM logical volume C<device>, where C<device> is
2035 the path to the LV, such as C</dev/VG/LV>.
2037 You can also remove all LVs in a volume group by specifying
2038 the VG name, C</dev/VG>.");
2040 ("vgremove", (RErr, [String "vgname"]), 78, [],
2041 [InitEmpty, Always, TestOutputList (
2042 [["sfdiskM"; "/dev/sda"; ","];
2043 ["pvcreate"; "/dev/sda1"];
2044 ["vgcreate"; "VG"; "/dev/sda1"];
2045 ["lvcreate"; "LV1"; "VG"; "50"];
2046 ["lvcreate"; "LV2"; "VG"; "50"];
2049 InitEmpty, Always, TestOutputList (
2050 [["sfdiskM"; "/dev/sda"; ","];
2051 ["pvcreate"; "/dev/sda1"];
2052 ["vgcreate"; "VG"; "/dev/sda1"];
2053 ["lvcreate"; "LV1"; "VG"; "50"];
2054 ["lvcreate"; "LV2"; "VG"; "50"];
2057 "remove an LVM volume group",
2059 Remove an LVM volume group C<vgname>, (for example C<VG>).
2061 This also forcibly removes all logical volumes in the volume
2064 ("pvremove", (RErr, [Device "device"]), 79, [],
2065 [InitEmpty, Always, TestOutputListOfDevices (
2066 [["sfdiskM"; "/dev/sda"; ","];
2067 ["pvcreate"; "/dev/sda1"];
2068 ["vgcreate"; "VG"; "/dev/sda1"];
2069 ["lvcreate"; "LV1"; "VG"; "50"];
2070 ["lvcreate"; "LV2"; "VG"; "50"];
2072 ["pvremove"; "/dev/sda1"];
2074 InitEmpty, Always, TestOutputListOfDevices (
2075 [["sfdiskM"; "/dev/sda"; ","];
2076 ["pvcreate"; "/dev/sda1"];
2077 ["vgcreate"; "VG"; "/dev/sda1"];
2078 ["lvcreate"; "LV1"; "VG"; "50"];
2079 ["lvcreate"; "LV2"; "VG"; "50"];
2081 ["pvremove"; "/dev/sda1"];
2083 InitEmpty, Always, TestOutputListOfDevices (
2084 [["sfdiskM"; "/dev/sda"; ","];
2085 ["pvcreate"; "/dev/sda1"];
2086 ["vgcreate"; "VG"; "/dev/sda1"];
2087 ["lvcreate"; "LV1"; "VG"; "50"];
2088 ["lvcreate"; "LV2"; "VG"; "50"];
2090 ["pvremove"; "/dev/sda1"];
2092 "remove an LVM physical volume",
2094 This wipes a physical volume C<device> so that LVM will no longer
2097 The implementation uses the C<pvremove> command which refuses to
2098 wipe physical volumes that contain any volume groups, so you have
2099 to remove those first.");
2101 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2102 [InitBasicFS, Always, TestOutput (
2103 [["set_e2label"; "/dev/sda1"; "testlabel"];
2104 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2105 "set the ext2/3/4 filesystem label",
2107 This sets the ext2/3/4 filesystem label of the filesystem on
2108 C<device> to C<label>. Filesystem labels are limited to
2111 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2112 to return the existing label on a filesystem.");
2114 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2116 "get the ext2/3/4 filesystem label",
2118 This returns the ext2/3/4 filesystem label of the filesystem on
2121 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2122 (let uuid = uuidgen () in
2123 [InitBasicFS, Always, TestOutput (
2124 [["set_e2uuid"; "/dev/sda1"; uuid];
2125 ["get_e2uuid"; "/dev/sda1"]], uuid);
2126 InitBasicFS, Always, TestOutput (
2127 [["set_e2uuid"; "/dev/sda1"; "clear"];
2128 ["get_e2uuid"; "/dev/sda1"]], "");
2129 (* We can't predict what UUIDs will be, so just check the commands run. *)
2130 InitBasicFS, Always, TestRun (
2131 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2132 InitBasicFS, Always, TestRun (
2133 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2134 "set the ext2/3/4 filesystem UUID",
2136 This sets the ext2/3/4 filesystem UUID of the filesystem on
2137 C<device> to C<uuid>. The format of the UUID and alternatives
2138 such as C<clear>, C<random> and C<time> are described in the
2139 L<tune2fs(8)> manpage.
2141 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2142 to return the existing UUID of a filesystem.");
2144 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2146 "get the ext2/3/4 filesystem UUID",
2148 This returns the ext2/3/4 filesystem UUID of the filesystem on
2151 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2152 [InitBasicFS, Always, TestOutputInt (
2153 [["umount"; "/dev/sda1"];
2154 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2155 InitBasicFS, Always, TestOutputInt (
2156 [["umount"; "/dev/sda1"];
2157 ["zero"; "/dev/sda1"];
2158 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2159 "run the filesystem checker",
2161 This runs the filesystem checker (fsck) on C<device> which
2162 should have filesystem type C<fstype>.
2164 The returned integer is the status. See L<fsck(8)> for the
2165 list of status codes from C<fsck>.
2173 Multiple status codes can be summed together.
2177 A non-zero return code can mean \"success\", for example if
2178 errors have been corrected on the filesystem.
2182 Checking or repairing NTFS volumes is not supported
2187 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2189 ("zero", (RErr, [Device "device"]), 85, [],
2190 [InitBasicFS, Always, TestOutput (
2191 [["umount"; "/dev/sda1"];
2192 ["zero"; "/dev/sda1"];
2193 ["file"; "/dev/sda1"]], "data")],
2194 "write zeroes to the device",
2196 This command writes zeroes over the first few blocks of C<device>.
2198 How many blocks are zeroed isn't specified (but it's I<not> enough
2199 to securely wipe the device). It should be sufficient to remove
2200 any partition tables, filesystem superblocks and so on.
2202 See also: C<guestfs_scrub_device>.");
2204 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2205 (* Test disabled because grub-install incompatible with virtio-blk driver.
2206 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2208 [InitBasicFS, Disabled, TestOutputTrue (
2209 [["grub_install"; "/"; "/dev/sda1"];
2210 ["is_dir"; "/boot"]])],
2213 This command installs GRUB (the Grand Unified Bootloader) on
2214 C<device>, with the root directory being C<root>.");
2216 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2217 [InitBasicFS, Always, TestOutput (
2218 [["write_file"; "/old"; "file content"; "0"];
2219 ["cp"; "/old"; "/new"];
2220 ["cat"; "/new"]], "file content");
2221 InitBasicFS, Always, TestOutputTrue (
2222 [["write_file"; "/old"; "file content"; "0"];
2223 ["cp"; "/old"; "/new"];
2224 ["is_file"; "/old"]]);
2225 InitBasicFS, Always, TestOutput (
2226 [["write_file"; "/old"; "file content"; "0"];
2228 ["cp"; "/old"; "/dir/new"];
2229 ["cat"; "/dir/new"]], "file content")],
2232 This copies a file from C<src> to C<dest> where C<dest> is
2233 either a destination filename or destination directory.");
2235 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2236 [InitBasicFS, Always, TestOutput (
2237 [["mkdir"; "/olddir"];
2238 ["mkdir"; "/newdir"];
2239 ["write_file"; "/olddir/file"; "file content"; "0"];
2240 ["cp_a"; "/olddir"; "/newdir"];
2241 ["cat"; "/newdir/olddir/file"]], "file content")],
2242 "copy a file or directory recursively",
2244 This copies a file or directory from C<src> to C<dest>
2245 recursively using the C<cp -a> command.");
2247 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2248 [InitBasicFS, Always, TestOutput (
2249 [["write_file"; "/old"; "file content"; "0"];
2250 ["mv"; "/old"; "/new"];
2251 ["cat"; "/new"]], "file content");
2252 InitBasicFS, Always, TestOutputFalse (
2253 [["write_file"; "/old"; "file content"; "0"];
2254 ["mv"; "/old"; "/new"];
2255 ["is_file"; "/old"]])],
2258 This moves a file from C<src> to C<dest> where C<dest> is
2259 either a destination filename or destination directory.");
2261 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2262 [InitEmpty, Always, TestRun (
2263 [["drop_caches"; "3"]])],
2264 "drop kernel page cache, dentries and inodes",
2266 This instructs the guest kernel to drop its page cache,
2267 and/or dentries and inode caches. The parameter C<whattodrop>
2268 tells the kernel what precisely to drop, see
2269 L<http://linux-mm.org/Drop_Caches>
2271 Setting C<whattodrop> to 3 should drop everything.
2273 This automatically calls L<sync(2)> before the operation,
2274 so that the maximum guest memory is freed.");
2276 ("dmesg", (RString "kmsgs", []), 91, [],
2277 [InitEmpty, Always, TestRun (
2279 "return kernel messages",
2281 This returns the kernel messages (C<dmesg> output) from
2282 the guest kernel. This is sometimes useful for extended
2283 debugging of problems.
2285 Another way to get the same information is to enable
2286 verbose messages with C<guestfs_set_verbose> or by setting
2287 the environment variable C<LIBGUESTFS_DEBUG=1> before
2288 running the program.");
2290 ("ping_daemon", (RErr, []), 92, [],
2291 [InitEmpty, Always, TestRun (
2292 [["ping_daemon"]])],
2293 "ping the guest daemon",
2295 This is a test probe into the guestfs daemon running inside
2296 the qemu subprocess. Calling this function checks that the
2297 daemon responds to the ping message, without affecting the daemon
2298 or attached block device(s) in any other way.");
2300 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2301 [InitBasicFS, Always, TestOutputTrue (
2302 [["write_file"; "/file1"; "contents of a file"; "0"];
2303 ["cp"; "/file1"; "/file2"];
2304 ["equal"; "/file1"; "/file2"]]);
2305 InitBasicFS, Always, TestOutputFalse (
2306 [["write_file"; "/file1"; "contents of a file"; "0"];
2307 ["write_file"; "/file2"; "contents of another file"; "0"];
2308 ["equal"; "/file1"; "/file2"]]);
2309 InitBasicFS, Always, TestLastFail (
2310 [["equal"; "/file1"; "/file2"]])],
2311 "test if two files have equal contents",
2313 This compares the two files C<file1> and C<file2> and returns
2314 true if their content is exactly equal, or false otherwise.
2316 The external L<cmp(1)> program is used for the comparison.");
2318 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2319 [InitISOFS, Always, TestOutputList (
2320 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2321 InitISOFS, Always, TestOutputList (
2322 [["strings"; "/empty"]], [])],
2323 "print the printable strings in a file",
2325 This runs the L<strings(1)> command on a file and returns
2326 the list of printable strings found.");
2328 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2329 [InitISOFS, Always, TestOutputList (
2330 [["strings_e"; "b"; "/known-5"]], []);
2331 InitBasicFS, Disabled, TestOutputList (
2332 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2333 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2334 "print the printable strings in a file",
2336 This is like the C<guestfs_strings> command, but allows you to
2337 specify the encoding.
2339 See the L<strings(1)> manpage for the full list of encodings.
2341 Commonly useful encodings are C<l> (lower case L) which will
2342 show strings inside Windows/x86 files.
2344 The returned strings are transcoded to UTF-8.");
2346 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2347 [InitISOFS, Always, TestOutput (
2348 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2349 (* Test for RHBZ#501888c2 regression which caused large hexdump
2350 * commands to segfault.
2352 InitISOFS, Always, TestRun (
2353 [["hexdump"; "/100krandom"]])],
2354 "dump a file in hexadecimal",
2356 This runs C<hexdump -C> on the given C<path>. The result is
2357 the human-readable, canonical hex dump of the file.");
2359 ("zerofree", (RErr, [Device "device"]), 97, [],
2360 [InitNone, Always, TestOutput (
2361 [["sfdiskM"; "/dev/sda"; ","];
2362 ["mkfs"; "ext3"; "/dev/sda1"];
2363 ["mount"; "/dev/sda1"; "/"];
2364 ["write_file"; "/new"; "test file"; "0"];
2365 ["umount"; "/dev/sda1"];
2366 ["zerofree"; "/dev/sda1"];
2367 ["mount"; "/dev/sda1"; "/"];
2368 ["cat"; "/new"]], "test file")],
2369 "zero unused inodes and disk blocks on ext2/3 filesystem",
2371 This runs the I<zerofree> program on C<device>. This program
2372 claims to zero unused inodes and disk blocks on an ext2/3
2373 filesystem, thus making it possible to compress the filesystem
2376 You should B<not> run this program if the filesystem is
2379 It is possible that using this program can damage the filesystem
2380 or data on the filesystem.");
2382 ("pvresize", (RErr, [Device "device"]), 98, [],
2384 "resize an LVM physical volume",
2386 This resizes (expands or shrinks) an existing LVM physical
2387 volume to match the new size of the underlying device.");
2389 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2390 Int "cyls"; Int "heads"; Int "sectors";
2391 String "line"]), 99, [DangerWillRobinson],
2393 "modify a single partition on a block device",
2395 This runs L<sfdisk(8)> option to modify just the single
2396 partition C<n> (note: C<n> counts from 1).
2398 For other parameters, see C<guestfs_sfdisk>. You should usually
2399 pass C<0> for the cyls/heads/sectors parameters.");
2401 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2403 "display the partition table",
2405 This displays the partition table on C<device>, in the
2406 human-readable output of the L<sfdisk(8)> command. It is
2407 not intended to be parsed.");
2409 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2411 "display the kernel geometry",
2413 This displays the kernel's idea of the geometry of C<device>.
2415 The result is in human-readable format, and not designed to
2418 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2420 "display the disk geometry from the partition table",
2422 This displays the disk geometry of C<device> read from the
2423 partition table. Especially in the case where the underlying
2424 block device has been resized, this can be different from the
2425 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2427 The result is in human-readable format, and not designed to
2430 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2432 "activate or deactivate all volume groups",
2434 This command activates or (if C<activate> is false) deactivates
2435 all logical volumes in all volume groups.
2436 If activated, then they are made known to the
2437 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2438 then those devices disappear.
2440 This command is the same as running C<vgchange -a y|n>");
2442 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2444 "activate or deactivate some volume groups",
2446 This command activates or (if C<activate> is false) deactivates
2447 all logical volumes in the listed volume groups C<volgroups>.
2448 If activated, then they are made known to the
2449 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2450 then those devices disappear.
2452 This command is the same as running C<vgchange -a y|n volgroups...>
2454 Note that if C<volgroups> is an empty list then B<all> volume groups
2455 are activated or deactivated.");
2457 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2458 [InitNone, Always, TestOutput (
2459 [["sfdiskM"; "/dev/sda"; ","];
2460 ["pvcreate"; "/dev/sda1"];
2461 ["vgcreate"; "VG"; "/dev/sda1"];
2462 ["lvcreate"; "LV"; "VG"; "10"];
2463 ["mkfs"; "ext2"; "/dev/VG/LV"];
2464 ["mount"; "/dev/VG/LV"; "/"];
2465 ["write_file"; "/new"; "test content"; "0"];
2467 ["lvresize"; "/dev/VG/LV"; "20"];
2468 ["e2fsck_f"; "/dev/VG/LV"];
2469 ["resize2fs"; "/dev/VG/LV"];
2470 ["mount"; "/dev/VG/LV"; "/"];
2471 ["cat"; "/new"]], "test content")],
2472 "resize an LVM logical volume",
2474 This resizes (expands or shrinks) an existing LVM logical
2475 volume to C<mbytes>. When reducing, data in the reduced part
2478 ("resize2fs", (RErr, [Device "device"]), 106, [],
2479 [], (* lvresize tests this *)
2480 "resize an ext2/ext3 filesystem",
2482 This resizes an ext2 or ext3 filesystem to match the size of
2483 the underlying device.
2485 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2486 on the C<device> before calling this command. For unknown reasons
2487 C<resize2fs> sometimes gives an error about this and sometimes not.
2488 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2489 calling this function.");
2491 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2492 [InitBasicFS, Always, TestOutputList (
2493 [["find"; "/"]], ["lost+found"]);
2494 InitBasicFS, Always, TestOutputList (
2498 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2499 InitBasicFS, Always, TestOutputList (
2500 [["mkdir_p"; "/a/b/c"];
2501 ["touch"; "/a/b/c/d"];
2502 ["find"; "/a/b/"]], ["c"; "c/d"])],
2503 "find all files and directories",
2505 This command lists out all files and directories, recursively,
2506 starting at C<directory>. It is essentially equivalent to
2507 running the shell command C<find directory -print> but some
2508 post-processing happens on the output, described below.
2510 This returns a list of strings I<without any prefix>. Thus
2511 if the directory structure was:
2517 then the returned list from C<guestfs_find> C</tmp> would be
2525 If C<directory> is not a directory, then this command returns
2528 The returned list is sorted.
2530 See also C<guestfs_find0>.");
2532 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2533 [], (* lvresize tests this *)
2534 "check an ext2/ext3 filesystem",
2536 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2537 filesystem checker on C<device>, noninteractively (C<-p>),
2538 even if the filesystem appears to be clean (C<-f>).
2540 This command is only needed because of C<guestfs_resize2fs>
2541 (q.v.). Normally you should use C<guestfs_fsck>.");
2543 ("sleep", (RErr, [Int "secs"]), 109, [],
2544 [InitNone, Always, TestRun (
2546 "sleep for some seconds",
2548 Sleep for C<secs> seconds.");
2550 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2551 [InitNone, Always, TestOutputInt (
2552 [["sfdiskM"; "/dev/sda"; ","];
2553 ["mkfs"; "ntfs"; "/dev/sda1"];
2554 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2555 InitNone, Always, TestOutputInt (
2556 [["sfdiskM"; "/dev/sda"; ","];
2557 ["mkfs"; "ext2"; "/dev/sda1"];
2558 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2559 "probe NTFS volume",
2561 This command runs the L<ntfs-3g.probe(8)> command which probes
2562 an NTFS C<device> for mountability. (Not all NTFS volumes can
2563 be mounted read-write, and some cannot be mounted at all).
2565 C<rw> is a boolean flag. Set it to true if you want to test
2566 if the volume can be mounted read-write. Set it to false if
2567 you want to test if the volume can be mounted read-only.
2569 The return value is an integer which C<0> if the operation
2570 would succeed, or some non-zero value documented in the
2571 L<ntfs-3g.probe(8)> manual page.");
2573 ("sh", (RString "output", [String "command"]), 111, [],
2574 [], (* XXX needs tests *)
2575 "run a command via the shell",
2577 This call runs a command from the guest filesystem via the
2580 This is like C<guestfs_command>, but passes the command to:
2582 /bin/sh -c \"command\"
2584 Depending on the guest's shell, this usually results in
2585 wildcards being expanded, shell expressions being interpolated
2588 All the provisos about C<guestfs_command> apply to this call.");
2590 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2591 [], (* XXX needs tests *)
2592 "run a command via the shell returning lines",
2594 This is the same as C<guestfs_sh>, but splits the result
2595 into a list of lines.
2597 See also: C<guestfs_command_lines>");
2599 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2600 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2601 * code in stubs.c, since all valid glob patterns must start with "/".
2602 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2604 [InitBasicFS, Always, TestOutputList (
2605 [["mkdir_p"; "/a/b/c"];
2606 ["touch"; "/a/b/c/d"];
2607 ["touch"; "/a/b/c/e"];
2608 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2609 InitBasicFS, Always, TestOutputList (
2610 [["mkdir_p"; "/a/b/c"];
2611 ["touch"; "/a/b/c/d"];
2612 ["touch"; "/a/b/c/e"];
2613 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2614 InitBasicFS, Always, TestOutputList (
2615 [["mkdir_p"; "/a/b/c"];
2616 ["touch"; "/a/b/c/d"];
2617 ["touch"; "/a/b/c/e"];
2618 ["glob_expand"; "/a/*/x/*"]], [])],
2619 "expand a wildcard path",
2621 This command searches for all the pathnames matching
2622 C<pattern> according to the wildcard expansion rules
2625 If no paths match, then this returns an empty list
2626 (note: not an error).
2628 It is just a wrapper around the C L<glob(3)> function
2629 with flags C<GLOB_MARK|GLOB_BRACE>.
2630 See that manual page for more details.");
2632 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2633 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2634 [["scrub_device"; "/dev/sdc"]])],
2635 "scrub (securely wipe) a device",
2637 This command writes patterns over C<device> to make data retrieval
2640 It is an interface to the L<scrub(1)> program. See that
2641 manual page for more details.");
2643 ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2644 [InitBasicFS, Always, TestRun (
2645 [["write_file"; "/file"; "content"; "0"];
2646 ["scrub_file"; "/file"]])],
2647 "scrub (securely wipe) a file",
2649 This command writes patterns over a file to make data retrieval
2652 The file is I<removed> after scrubbing.
2654 It is an interface to the L<scrub(1)> program. See that
2655 manual page for more details.");
2657 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2658 [], (* XXX needs testing *)
2659 "scrub (securely wipe) free space",
2661 This command creates the directory C<dir> and then fills it
2662 with files until the filesystem is full, and scrubs the files
2663 as for C<guestfs_scrub_file>, and deletes them.
2664 The intention is to scrub any free space on the partition
2667 It is an interface to the L<scrub(1)> program. See that
2668 manual page for more details.");
2670 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2671 [InitBasicFS, Always, TestRun (
2673 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2674 "create a temporary directory",
2676 This command creates a temporary directory. The
2677 C<template> parameter should be a full pathname for the
2678 temporary directory name with the final six characters being
2681 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2682 the second one being suitable for Windows filesystems.
2684 The name of the temporary directory that was created
2687 The temporary directory is created with mode 0700
2688 and is owned by root.
2690 The caller is responsible for deleting the temporary
2691 directory and its contents after use.
2693 See also: L<mkdtemp(3)>");
2695 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2696 [InitISOFS, Always, TestOutputInt (
2697 [["wc_l"; "/10klines"]], 10000)],
2698 "count lines in a file",
2700 This command counts the lines in a file, using the
2701 C<wc -l> external command.");
2703 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2704 [InitISOFS, Always, TestOutputInt (
2705 [["wc_w"; "/10klines"]], 10000)],
2706 "count words in a file",
2708 This command counts the words in a file, using the
2709 C<wc -w> external command.");
2711 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2712 [InitISOFS, Always, TestOutputInt (
2713 [["wc_c"; "/100kallspaces"]], 102400)],
2714 "count characters in a file",
2716 This command counts the characters in a file, using the
2717 C<wc -c> external command.");
2719 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2720 [InitISOFS, Always, TestOutputList (
2721 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2722 "return first 10 lines of a file",
2724 This command returns up to the first 10 lines of a file as
2725 a list of strings.");
2727 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2728 [InitISOFS, Always, TestOutputList (
2729 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2730 InitISOFS, Always, TestOutputList (
2731 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732 InitISOFS, Always, TestOutputList (
2733 [["head_n"; "0"; "/10klines"]], [])],
2734 "return first N lines of a file",
2736 If the parameter C<nrlines> is a positive number, this returns the first
2737 C<nrlines> lines of the file C<path>.
2739 If the parameter C<nrlines> is a negative number, this returns lines
2740 from the file C<path>, excluding the last C<nrlines> lines.
2742 If the parameter C<nrlines> is zero, this returns an empty list.");
2744 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2745 [InitISOFS, Always, TestOutputList (
2746 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2747 "return last 10 lines of a file",
2749 This command returns up to the last 10 lines of a file as
2750 a list of strings.");
2752 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2753 [InitISOFS, Always, TestOutputList (
2754 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2755 InitISOFS, Always, TestOutputList (
2756 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757 InitISOFS, Always, TestOutputList (
2758 [["tail_n"; "0"; "/10klines"]], [])],
2759 "return last N lines of a file",
2761 If the parameter C<nrlines> is a positive number, this returns the last
2762 C<nrlines> lines of the file C<path>.
2764 If the parameter C<nrlines> is a negative number, this returns lines
2765 from the file C<path>, starting with the C<-nrlines>th line.
2767 If the parameter C<nrlines> is zero, this returns an empty list.");
2769 ("df", (RString "output", []), 125, [],
2770 [], (* XXX Tricky to test because it depends on the exact format
2771 * of the 'df' command and other imponderables.
2773 "report file system disk space usage",
2775 This command runs the C<df> command to report disk space used.
2777 This command is mostly useful for interactive sessions. It
2778 is I<not> intended that you try to parse the output string.
2779 Use C<statvfs> from programs.");
2781 ("df_h", (RString "output", []), 126, [],
2782 [], (* XXX Tricky to test because it depends on the exact format
2783 * of the 'df' command and other imponderables.
2785 "report file system disk space usage (human readable)",
2787 This command runs the C<df -h> command to report disk space used
2788 in human-readable format.
2790 This command is mostly useful for interactive sessions. It
2791 is I<not> intended that you try to parse the output string.
2792 Use C<statvfs> from programs.");
2794 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2795 [InitISOFS, Always, TestOutputInt (
2796 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2797 "estimate file space usage",
2799 This command runs the C<du -s> command to estimate file space
2802 C<path> can be a file or a directory. If C<path> is a directory
2803 then the estimate includes the contents of the directory and all
2804 subdirectories (recursively).
2806 The result is the estimated size in I<kilobytes>
2807 (ie. units of 1024 bytes).");
2809 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2810 [InitISOFS, Always, TestOutputList (
2811 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2812 "list files in an initrd",
2814 This command lists out files contained in an initrd.
2816 The files are listed without any initial C</> character. The
2817 files are listed in the order they appear (not necessarily
2818 alphabetical). Directory names are listed as separate items.
2820 Old Linux kernels (2.4 and earlier) used a compressed ext2
2821 filesystem as initrd. We I<only> support the newer initramfs
2822 format (compressed cpio files).");
2824 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2826 "mount a file using the loop device",
2828 This command lets you mount C<file> (a filesystem image
2829 in a file) on a mount point. It is entirely equivalent to
2830 the command C<mount -o loop file mountpoint>.");
2832 ("mkswap", (RErr, [Device "device"]), 130, [],
2833 [InitEmpty, Always, TestRun (
2834 [["sfdiskM"; "/dev/sda"; ","];
2835 ["mkswap"; "/dev/sda1"]])],
2836 "create a swap partition",
2838 Create a swap partition on C<device>.");
2840 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2841 [InitEmpty, Always, TestRun (
2842 [["sfdiskM"; "/dev/sda"; ","];
2843 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2844 "create a swap partition with a label",
2846 Create a swap partition on C<device> with label C<label>.
2848 Note that you cannot attach a swap label to a block device
2849 (eg. C</dev/sda>), just to a partition. This appears to be
2850 a limitation of the kernel or swap tools.");
2852 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2853 (let uuid = uuidgen () in
2854 [InitEmpty, Always, TestRun (
2855 [["sfdiskM"; "/dev/sda"; ","];
2856 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2857 "create a swap partition with an explicit UUID",
2859 Create a swap partition on C<device> with UUID C<uuid>.");
2861 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2862 [InitBasicFS, Always, TestOutputStruct (
2863 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2864 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2865 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2866 InitBasicFS, Always, TestOutputStruct (
2867 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2868 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2869 "make block, character or FIFO devices",
2871 This call creates block or character special devices, or
2872 named pipes (FIFOs).
2874 The C<mode> parameter should be the mode, using the standard
2875 constants. C<devmajor> and C<devminor> are the
2876 device major and minor numbers, only used when creating block
2877 and character special devices.");
2879 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2880 [InitBasicFS, Always, TestOutputStruct (
2881 [["mkfifo"; "0o777"; "/node"];
2882 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2883 "make FIFO (named pipe)",
2885 This call creates a FIFO (named pipe) called C<path> with
2886 mode C<mode>. It is just a convenient wrapper around
2887 C<guestfs_mknod>.");
2889 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2890 [InitBasicFS, Always, TestOutputStruct (
2891 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2892 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2893 "make block device node",
2895 This call creates a block device node called C<path> with
2896 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2897 It is just a convenient wrapper around C<guestfs_mknod>.");
2899 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2900 [InitBasicFS, Always, TestOutputStruct (
2901 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2902 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2903 "make char device node",
2905 This call creates a char device node called C<path> with
2906 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2907 It is just a convenient wrapper around C<guestfs_mknod>.");
2909 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2910 [], (* XXX umask is one of those stateful things that we should
2911 * reset between each test.
2913 "set file mode creation mask (umask)",
2915 This function sets the mask used for creating new files and
2916 device nodes to C<mask & 0777>.
2918 Typical umask values would be C<022> which creates new files
2919 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2920 C<002> which creates new files with permissions like
2921 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2923 The default umask is C<022>. This is important because it
2924 means that directories and device nodes will be created with
2925 C<0644> or C<0755> mode even if you specify C<0777>.
2927 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2929 This call returns the previous umask.");
2931 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2933 "read directories entries",
2935 This returns the list of directory entries in directory C<dir>.
2937 All entries in the directory are returned, including C<.> and
2938 C<..>. The entries are I<not> sorted, but returned in the same
2939 order as the underlying filesystem.
2941 Also this call returns basic file type information about each
2942 file. The C<ftyp> field will contain one of the following characters:
2980 The L<readdir(3)> returned a C<d_type> field with an
2985 This function is primarily intended for use by programs. To
2986 get a simple list of names, use C<guestfs_ls>. To get a printable
2987 directory for human consumption, use C<guestfs_ll>.");
2989 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2991 "create partitions on a block device",
2993 This is a simplified interface to the C<guestfs_sfdisk>
2994 command, where partition sizes are specified in megabytes
2995 only (rounded to the nearest cylinder) and you don't need
2996 to specify the cyls, heads and sectors parameters which
2997 were rarely if ever used anyway.
2999 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3001 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3003 "determine file type inside a compressed file",
3005 This command runs C<file> after first decompressing C<path>
3008 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3010 Since 1.0.63, use C<guestfs_file> instead which can now
3011 process compressed files.");
3013 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3015 "list extended attributes of a file or directory",
3017 This call lists the extended attributes of the file or directory
3020 At the system call level, this is a combination of the
3021 L<listxattr(2)> and L<getxattr(2)> calls.
3023 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3025 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3027 "list extended attributes of a file or directory",
3029 This is the same as C<guestfs_getxattrs>, but if C<path>
3030 is a symbolic link, then it returns the extended attributes
3031 of the link itself.");
3033 ("setxattr", (RErr, [String "xattr";
3034 String "val"; Int "vallen"; (* will be BufferIn *)
3035 Pathname "path"]), 143, [],
3037 "set extended attribute of a file or directory",
3039 This call sets the extended attribute named C<xattr>
3040 of the file C<path> to the value C<val> (of length C<vallen>).
3041 The value is arbitrary 8 bit data.
3043 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3045 ("lsetxattr", (RErr, [String "xattr";
3046 String "val"; Int "vallen"; (* will be BufferIn *)
3047 Pathname "path"]), 144, [],
3049 "set extended attribute of a file or directory",
3051 This is the same as C<guestfs_setxattr>, but if C<path>
3052 is a symbolic link, then it sets an extended attribute
3053 of the link itself.");
3055 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3057 "remove extended attribute of a file or directory",
3059 This call removes the extended attribute named C<xattr>
3060 of the file C<path>.
3062 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3064 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3066 "remove extended attribute of a file or directory",
3068 This is the same as C<guestfs_removexattr>, but if C<path>
3069 is a symbolic link, then it removes an extended attribute
3070 of the link itself.");
3072 ("mountpoints", (RHashtable "mps", []), 147, [],
3076 This call is similar to C<guestfs_mounts>. That call returns
3077 a list of devices. This one returns a hash table (map) of
3078 device name to directory where the device is mounted.");
3080 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3081 (* This is a special case: while you would expect a parameter
3082 * of type "Pathname", that doesn't work, because it implies
3083 * NEED_ROOT in the generated calling code in stubs.c, and
3084 * this function cannot use NEED_ROOT.
3087 "create a mountpoint",
3089 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3090 specialized calls that can be used to create extra mountpoints
3091 before mounting the first filesystem.
3093 These calls are I<only> necessary in some very limited circumstances,
3094 mainly the case where you want to mount a mix of unrelated and/or
3095 read-only filesystems together.
3097 For example, live CDs often contain a \"Russian doll\" nest of
3098 filesystems, an ISO outer layer, with a squashfs image inside, with
3099 an ext2/3 image inside that. You can unpack this as follows
3102 add-ro Fedora-11-i686-Live.iso
3105 mkmountpoint /squash
3108 mount-loop /cd/LiveOS/squashfs.img /squash
3109 mount-loop /squash/LiveOS/ext3fs.img /ext3
3111 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3113 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3115 "remove a mountpoint",
3117 This calls removes a mountpoint that was previously created
3118 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3119 for full details.");
3121 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3122 [InitISOFS, Always, TestOutputBuffer (
3123 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3126 This calls returns the contents of the file C<path> as a
3129 Unlike C<guestfs_cat>, this function can correctly
3130 handle files that contain embedded ASCII NUL characters.
3131 However unlike C<guestfs_download>, this function is limited
3132 in the total size of file that can be handled.");
3134 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3135 [InitISOFS, Always, TestOutputList (
3136 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3137 InitISOFS, Always, TestOutputList (
3138 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3139 "return lines matching a pattern",
3141 This calls the external C<grep> program and returns the
3144 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3145 [InitISOFS, Always, TestOutputList (
3146 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3147 "return lines matching a pattern",
3149 This calls the external C<egrep> program and returns the
3152 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3153 [InitISOFS, Always, TestOutputList (
3154 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3155 "return lines matching a pattern",
3157 This calls the external C<fgrep> program and returns the
3160 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3161 [InitISOFS, Always, TestOutputList (
3162 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3163 "return lines matching a pattern",
3165 This calls the external C<grep -i> program and returns the
3168 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3169 [InitISOFS, Always, TestOutputList (
3170 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3171 "return lines matching a pattern",
3173 This calls the external C<egrep -i> program and returns the
3176 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3177 [InitISOFS, Always, TestOutputList (
3178 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3179 "return lines matching a pattern",
3181 This calls the external C<fgrep -i> program and returns the
3184 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3185 [InitISOFS, Always, TestOutputList (
3186 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3187 "return lines matching a pattern",
3189 This calls the external C<zgrep> program and returns the
3192 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3193 [InitISOFS, Always, TestOutputList (
3194 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3195 "return lines matching a pattern",
3197 This calls the external C<zegrep> program and returns the
3200 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3201 [InitISOFS, Always, TestOutputList (
3202 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3203 "return lines matching a pattern",
3205 This calls the external C<zfgrep> program and returns the
3208 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3209 [InitISOFS, Always, TestOutputList (
3210 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3211 "return lines matching a pattern",
3213 This calls the external C<zgrep -i> program and returns the
3216 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3217 [InitISOFS, Always, TestOutputList (
3218 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3219 "return lines matching a pattern",
3221 This calls the external C<zegrep -i> program and returns the
3224 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3225 [InitISOFS, Always, TestOutputList (
3226 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3227 "return lines matching a pattern",
3229 This calls the external C<zfgrep -i> program and returns the
3232 ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3233 [InitISOFS, Always, TestOutput (
3234 [["realpath"; "/../directory"]], "/directory")],
3235 "canonicalized absolute pathname",
3237 Return the canonicalized absolute pathname of C<path>. The
3238 returned path has no C<.>, C<..> or symbolic link path elements.");
3240 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3241 [InitBasicFS, Always, TestOutputStruct (
3244 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3245 "create a hard link",
3247 This command creates a hard link using the C<ln> command.");
3249 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3250 [InitBasicFS, Always, TestOutputStruct (
3253 ["ln_f"; "/a"; "/b"];
3254 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3255 "create a hard link",
3257 This command creates a hard link using the C<ln -f> command.
3258 The C<-f> option removes the link (C<linkname>) if it exists already.");
3260 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3261 [InitBasicFS, Always, TestOutputStruct (
3263 ["ln_s"; "a"; "/b"];
3264 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3265 "create a symbolic link",
3267 This command creates a symbolic link using the C<ln -s> command.");
3269 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3270 [InitBasicFS, Always, TestOutput (
3271 [["mkdir_p"; "/a/b"];
3272 ["touch"; "/a/b/c"];
3273 ["ln_sf"; "../d"; "/a/b/c"];
3274 ["readlink"; "/a/b/c"]], "../d")],
3275 "create a symbolic link",
3277 This command creates a symbolic link using the C<ln -sf> command,
3278 The C<-f> option removes the link (C<linkname>) if it exists already.");
3280 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3281 [] (* XXX tested above *),
3282 "read the target of a symbolic link",
3284 This command reads the target of a symbolic link.");
3286 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3287 [InitBasicFS, Always, TestOutputStruct (
3288 [["fallocate"; "/a"; "1000000"];
3289 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3290 "preallocate a file in the guest filesystem",
3292 This command preallocates a file (containing zero bytes) named
3293 C<path> of size C<len> bytes. If the file exists already, it
3296 Do not confuse this with the guestfish-specific
3297 C<alloc> command which allocates a file in the host and
3298 attaches it as a device.");
3300 ("swapon_device", (RErr, [Device "device"]), 170, [],
3301 [InitPartition, Always, TestRun (
3302 [["mkswap"; "/dev/sda1"];
3303 ["swapon_device"; "/dev/sda1"];
3304 ["swapoff_device"; "/dev/sda1"]])],
3305 "enable swap on device",
3307 This command enables the libguestfs appliance to use the
3308 swap device or partition named C<device>. The increased
3309 memory is made available for all commands, for example
3310 those run using C<guestfs_command> or C<guestfs_sh>.
3312 Note that you should not swap to existing guest swap
3313 partitions unless you know what you are doing. They may
3314 contain hibernation information, or other information that
3315 the guest doesn't want you to trash. You also risk leaking
3316 information about the host to the guest this way. Instead,
3317 attach a new host device to the guest and swap on that.");
3319 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3320 [], (* XXX tested by swapon_device *)
3321 "disable swap on device",
3323 This command disables the libguestfs appliance swap
3324 device or partition named C<device>.
3325 See C<guestfs_swapon_device>.");
3327 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3328 [InitBasicFS, Always, TestRun (
3329 [["fallocate"; "/swap"; "8388608"];
3330 ["mkswap_file"; "/swap"];
3331 ["swapon_file"; "/swap"];
3332 ["swapoff_file"; "/swap"]])],
3333 "enable swap on file",
3335 This command enables swap to a file.
3336 See C<guestfs_swapon_device> for other notes.");
3338 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3339 [], (* XXX tested by swapon_file *)
3340 "disable swap on file",
3342 This command disables the libguestfs appliance swap on file.");
3344 ("swapon_label", (RErr, [String "label"]), 174, [],
3345 [InitEmpty, Always, TestRun (
3346 [["sfdiskM"; "/dev/sdb"; ","];
3347 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3348 ["swapon_label"; "swapit"];
3349 ["swapoff_label"; "swapit"];
3350 ["zero"; "/dev/sdb"];
3351 ["blockdev_rereadpt"; "/dev/sdb"]])],
3352 "enable swap on labeled swap partition",
3354 This command enables swap to a labeled swap partition.
3355 See C<guestfs_swapon_device> for other notes.");
3357 ("swapoff_label", (RErr, [String "label"]), 175, [],
3358 [], (* XXX tested by swapon_label *)
3359 "disable swap on labeled swap partition",
3361 This command disables the libguestfs appliance swap on
3362 labeled swap partition.");
3364 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3365 (let uuid = uuidgen () in
3366 [InitEmpty, Always, TestRun (
3367 [["mkswap_U"; uuid; "/dev/sdb"];
3368 ["swapon_uuid"; uuid];
3369 ["swapoff_uuid"; uuid]])]),
3370 "enable swap on swap partition by UUID",
3372 This command enables swap to a swap partition with the given UUID.
3373 See C<guestfs_swapon_device> for other notes.");
3375 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3376 [], (* XXX tested by swapon_uuid *)
3377 "disable swap on swap partition by UUID",
3379 This command disables the libguestfs appliance swap partition
3380 with the given UUID.");
3382 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3383 [InitBasicFS, Always, TestRun (
3384 [["fallocate"; "/swap"; "8388608"];
3385 ["mkswap_file"; "/swap"]])],
3386 "create a swap file",
3390 This command just writes a swap file signature to an existing
3391 file. To create the file itself, use something like C<guestfs_fallocate>.");
3393 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3394 [InitISOFS, Always, TestRun (
3395 [["inotify_init"; "0"]])],
3396 "create an inotify handle",
3398 This command creates a new inotify handle.
3399 The inotify subsystem can be used to notify events which happen to
3400 objects in the guest filesystem.
3402 C<maxevents> is the maximum number of events which will be
3403 queued up between calls to C<guestfs_inotify_read> or
3404 C<guestfs_inotify_files>.
3405 If this is passed as C<0>, then the kernel (or previously set)
3406 default is used. For Linux 2.6.29 the default was 16384 events.
3407 Beyond this limit, the kernel throws away events, but records
3408 the fact that it threw them away by setting a flag
3409 C<IN_Q_OVERFLOW> in the returned structure list (see
3410 C<guestfs_inotify_read>).
3412 Before any events are generated, you have to add some
3413 watches to the internal watch list. See:
3414 C<guestfs_inotify_add_watch>,
3415 C<guestfs_inotify_rm_watch> and
3416 C<guestfs_inotify_watch_all>.
3418 Queued up events should be read periodically by calling
3419 C<guestfs_inotify_read>
3420 (or C<guestfs_inotify_files> which is just a helpful
3421 wrapper around C<guestfs_inotify_read>). If you don't
3422 read the events out often enough then you risk the internal
3425 The handle should be closed after use by calling
3426 C<guestfs_inotify_close>. This also removes any
3427 watches automatically.
3429 See also L<inotify(7)> for an overview of the inotify interface
3430 as exposed by the Linux kernel, which is roughly what we expose
3431 via libguestfs. Note that there is one global inotify handle
3432 per libguestfs instance.");
3434 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3435 [InitBasicFS, Always, TestOutputList (
3436 [["inotify_init"; "0"];
3437 ["inotify_add_watch"; "/"; "1073741823"];
3440 ["inotify_files"]], ["a"; "b"])],
3441 "add an inotify watch",
3443 Watch C<path> for the events listed in C<mask>.
3445 Note that if C<path> is a directory then events within that
3446 directory are watched, but this does I<not> happen recursively
3447 (in subdirectories).
3449 Note for non-C or non-Linux callers: the inotify events are
3450 defined by the Linux kernel ABI and are listed in
3451 C</usr/include/sys/inotify.h>.");
3453 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3455 "remove an inotify watch",
3457 Remove a previously defined inotify watch.
3458 See C<guestfs_inotify_add_watch>.");
3460 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3462 "return list of inotify events",
3464 Return the complete queue of events that have happened
3465 since the previous read call.
3467 If no events have happened, this returns an empty list.
3469 I<Note>: In order to make sure that all events have been
3470 read, you must call this function repeatedly until it
3471 returns an empty list. The reason is that the call will
3472 read events up to the maximum appliance-to-host message
3473 size and leave remaining events in the queue.");
3475 ("inotify_files", (RStringList "paths", []), 183, [],
3477 "return list of watched files that had events",
3479 This function is a helpful wrapper around C<guestfs_inotify_read>
3480 which just returns a list of pathnames of objects that were
3481 touched. The returned pathnames are sorted and deduplicated.");
3483 ("inotify_close", (RErr, []), 184, [],
3485 "close the inotify handle",
3487 This closes the inotify handle which was previously
3488 opened by inotify_init. It removes all watches, throws
3489 away any pending events, and deallocates all resources.");
3491 ("setcon", (RErr, [String "context"]), 185, [],
3493 "set SELinux security context",
3495 This sets the SELinux security context of the daemon
3496 to the string C<context>.
3498 See the documentation about SELINUX in L<guestfs(3)>.");
3500 ("getcon", (RString "context", []), 186, [],
3502 "get SELinux security context",
3504 This gets the SELinux security context of the daemon.
3506 See the documentation about SELINUX in L<guestfs(3)>,
3507 and C<guestfs_setcon>");
3509 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3510 [InitEmpty, Always, TestOutput (
3511 [["sfdiskM"; "/dev/sda"; ","];
3512 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3513 ["mount"; "/dev/sda1"; "/"];
3514 ["write_file"; "/new"; "new file contents"; "0"];
3515 ["cat"; "/new"]], "new file contents")],
3516 "make a filesystem with block size",
3518 This call is similar to C<guestfs_mkfs>, but it allows you to
3519 control the block size of the resulting filesystem. Supported
3520 block sizes depend on the filesystem type, but typically they
3521 are C<1024>, C<2048> or C<4096> only.");
3523 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3524 [InitEmpty, Always, TestOutput (
3525 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3526 ["mke2journal"; "4096"; "/dev/sda1"];
3527 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3528 ["mount"; "/dev/sda2"; "/"];
3529 ["write_file"; "/new"; "new file contents"; "0"];
3530 ["cat"; "/new"]], "new file contents")],
3531 "make ext2/3/4 external journal",
3533 This creates an ext2 external journal on C<device>. It is equivalent
3536 mke2fs -O journal_dev -b blocksize device");
3538 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3539 [InitEmpty, Always, TestOutput (
3540 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3541 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3542 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3543 ["mount"; "/dev/sda2"; "/"];
3544 ["write_file"; "/new"; "new file contents"; "0"];
3545 ["cat"; "/new"]], "new file contents")],
3546 "make ext2/3/4 external journal with label",
3548 This creates an ext2 external journal on C<device> with label C<label>.");
3550 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3551 (let uuid = uuidgen () in
3552 [InitEmpty, Always, TestOutput (
3553 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3554 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3555 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3556 ["mount"; "/dev/sda2"; "/"];
3557 ["write_file"; "/new"; "new file contents"; "0"];
3558 ["cat"; "/new"]], "new file contents")]),
3559 "make ext2/3/4 external journal with UUID",
3561 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3563 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3565 "make ext2/3/4 filesystem with external journal",
3567 This creates an ext2/3/4 filesystem on C<device> with
3568 an external journal on C<journal>. It is equivalent
3571 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3573 See also C<guestfs_mke2journal>.");
3575 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3577 "make ext2/3/4 filesystem with external journal",
3579 This creates an ext2/3/4 filesystem on C<device> with
3580 an external journal on the journal labeled C<label>.
3582 See also C<guestfs_mke2journal_L>.");
3584 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3586 "make ext2/3/4 filesystem with external journal",
3588 This creates an ext2/3/4 filesystem on C<device> with
3589 an external journal on the journal with UUID C<uuid>.
3591 See also C<guestfs_mke2journal_U>.");
3593 ("modprobe", (RErr, [String "modulename"]), 194, [],
3594 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3595 "load a kernel module",
3597 This loads a kernel module in the appliance.
3599 The kernel module must have been whitelisted when libguestfs
3600 was built (see C<appliance/kmod.whitelist.in> in the source).");
3602 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3603 [InitNone, Always, TestOutput (
3604 [["echo_daemon"; "This is a test"]], "This is a test"
3606 "echo arguments back to the client",
3608 This command concatenate the list of C<words> passed with single spaces between
3609 them and returns the resulting string.
3611 You can use this command to test the connection through to the daemon.
3613 See also C<guestfs_ping_daemon>.");
3615 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3616 [], (* There is a regression test for this. *)
3617 "find all files and directories, returning NUL-separated list",
3619 This command lists out all files and directories, recursively,
3620 starting at C<directory>, placing the resulting list in the
3621 external file called C<files>.
3623 This command works the same way as C<guestfs_find> with the
3624 following exceptions:
3630 The resulting list is written to an external file.
3634 Items (filenames) in the result are separated
3635 by C<\\0> characters. See L<find(1)> option I<-print0>.
3639 This command is not limited in the number of names that it
3644 The result list is not sorted.
3650 let all_functions = non_daemon_functions @ daemon_functions
3652 (* In some places we want the functions to be displayed sorted
3653 * alphabetically, so this is useful:
3655 let all_functions_sorted =
3656 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3657 compare n1 n2) all_functions
3659 (* Field types for structures. *)
3661 | FChar (* C 'char' (really, a 7 bit byte). *)
3662 | FString (* nul-terminated ASCII string, NOT NULL. *)
3663 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3668 | FBytes (* Any int measure that counts bytes. *)
3669 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3670 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3672 (* Because we generate extra parsing code for LVM command line tools,
3673 * we have to pull out the LVM columns separately here.
3683 "pv_attr", FString (* XXX *);
3684 "pv_pe_count", FInt64;
3685 "pv_pe_alloc_count", FInt64;
3688 "pv_mda_count", FInt64;
3689 "pv_mda_free", FBytes;
3690 (* Not in Fedora 10:
3691 "pv_mda_size", FBytes;
3698 "vg_attr", FString (* XXX *);
3701 "vg_sysid", FString;
3702 "vg_extent_size", FBytes;
3703 "vg_extent_count", FInt64;
3704 "vg_free_count", FInt64;
3709 "snap_count", FInt64;
3712 "vg_mda_count", FInt64;
3713 "vg_mda_free", FBytes;
3714 (* Not in Fedora 10:
3715 "vg_mda_size", FBytes;
3721 "lv_attr", FString (* XXX *);
3724 "lv_kernel_major", FInt64;
3725 "lv_kernel_minor", FInt64;
3727 "seg_count", FInt64;
3729 "snap_percent", FOptPercent;
3730 "copy_percent", FOptPercent;
3733 "mirror_log", FString;
3737 (* Names and fields in all structures (in RStruct and RStructList)
3741 (* The old RIntBool return type, only ever used for aug_defnode. Do
3742 * not use this struct in any new code.
3745 "i", FInt32; (* for historical compatibility *)
3746 "b", FInt32; (* for historical compatibility *)
3749 (* LVM PVs, VGs, LVs. *)
3750 "lvm_pv", lvm_pv_cols;
3751 "lvm_vg", lvm_vg_cols;
3752 "lvm_lv", lvm_lv_cols;
3754 (* Column names and types from stat structures.
3755 * NB. Can't use things like 'st_atime' because glibc header files
3756 * define some of these as macros. Ugh.
3787 (* Column names in dirent structure. *)
3790 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3795 (* Version numbers. *)
3803 (* Extended attribute. *)
3805 "attrname", FString;
3809 (* Inotify events. *)
3813 "in_cookie", FUInt32;
3816 ] (* end of structs *)
3818 (* Ugh, Java has to be different ..
3819 * These names are also used by the Haskell bindings.
3821 let java_structs = [
3822 "int_bool", "IntBool";
3827 "statvfs", "StatVFS";
3829 "version", "Version";
3831 "inotify_event", "INotifyEvent";
3834 (* What structs are actually returned. *)
3835 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3837 (* Returns a list of RStruct/RStructList structs that are returned
3838 * by any function. Each element of returned list is a pair:
3840 * (structname, RStructOnly)
3841 * == there exists function which returns RStruct (_, structname)
3842 * (structname, RStructListOnly)
3843 * == there exists function which returns RStructList (_, structname)
3844 * (structname, RStructAndList)
3845 * == there are functions returning both RStruct (_, structname)
3846 * and RStructList (_, structname)
3849 (* ||| is a "logical OR" for rstructs_used_t *)
3853 | _, RStructAndList -> RStructAndList
3854 | RStructOnly, RStructListOnly
3855 | RStructListOnly, RStructOnly -> RStructAndList
3856 | RStructOnly, RStructOnly -> RStructOnly
3857 | RStructListOnly, RStructListOnly -> RStructListOnly
3860 let h = Hashtbl.create 13 in
3862 (* if elem->oldv exists, update entry using ||| operator,
3863 * else just add elem->newv to the hash
3865 let update elem newv =
3866 try let oldv = Hashtbl.find h elem in
3867 Hashtbl.replace h elem (newv ||| oldv)
3868 with Not_found -> Hashtbl.add h elem newv
3872 fun (_, style, _, _, _, _, _) ->
3873 match fst style with
3874 | RStruct (_, structname) -> update structname RStructOnly
3875 | RStructList (_, structname) -> update structname RStructListOnly
3879 (* return key->values as a list of (key,value) *)
3880 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3886 | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3887 | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3888 | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3892 (* Used for testing language bindings. *)
3894 | CallString of string
3895 | CallOptString of string option
3896 | CallStringList of string list
3900 (* Used to memoize the result of pod2text. *)
3901 let pod2text_memo_filename = "src/.pod2text.data"
3902 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3904 let chan = open_in pod2text_memo_filename in
3905 let v = input_value chan in
3909 _ -> Hashtbl.create 13
3910 let pod2text_memo_updated () =
3911 let chan = open_out pod2text_memo_filename in
3912 output_value chan pod2text_memo;
3915 (* Useful functions.
3916 * Note we don't want to use any external OCaml libraries which
3917 * makes this a bit harder than it should be.
3919 let failwithf fs = ksprintf failwith fs
3921 let replace_char s c1 c2 =
3922 let s2 = String.copy s in
3923 let r = ref false in
3924 for i = 0 to String.length s2 - 1 do
3925 if String.unsafe_get s2 i = c1 then (
3926 String.unsafe_set s2 i c2;
3930 if not !r then s else s2
3934 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3936 let triml ?(test = isspace) str =
3938 let n = ref (String.length str) in
3939 while !n > 0 && test str.[!i]; do
3944 else String.sub str !i !n
3946 let trimr ?(test = isspace) str =
3947 let n = ref (String.length str) in
3948 while !n > 0 && test str.[!n-1]; do
3951 if !n = String.length str then str
3952 else String.sub str 0 !n
3954 let trim ?(test = isspace) str =
3955 trimr ~test (triml ~test str)
3957 let rec find s sub =
3958 let len = String.length s in
3959 let sublen = String.length sub in
3961 if i <= len-sublen then (
3963 if j < sublen then (
3964 if s.[i+j] = sub.[j] then loop2 (j+1)
3970 if r = -1 then loop (i+1) else r
3976 let rec replace_str s s1 s2 =
3977 let len = String.length s in
3978 let sublen = String.length s1 in
3979 let i = find s s1 in
3982 let s' = String.sub s 0 i in
3983 let s'' = String.sub s (i+sublen) (len-i-sublen) in
3984 s' ^ s2 ^ replace_str s'' s1 s2
3987 let rec string_split sep str =
3988 let len = String.length str in
3989 let seplen = String.length sep in
3990 let i = find str sep in
3991 if i = -1 then [str]
3993 let s' = String.sub str 0 i in
3994 let s'' = String.sub str (i+seplen) (len-i-seplen) in
3995 s' :: string_split sep s''
3998 let files_equal n1 n2 =
3999 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4000 match Sys.command cmd with
4003 | i -> failwithf "%s: failed with error code %d" cmd i
4005 let rec filter_map f = function
4009 | Some y -> y :: filter_map f xs
4010 | None -> filter_map f xs
4012 let rec find_map f = function
4013 | [] -> raise Not_found
4017 | None -> find_map f xs
4020 let rec loop i = function
4022 | x :: xs -> f i x; loop (i+1) xs
4027 let rec loop i = function
4029 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4033 let name_of_argt = function
4034 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4035 | StringList n | DeviceList n | Bool n | Int n
4036 | FileIn n | FileOut n -> n
4038 let java_name_of_struct typ =
4039 try List.assoc typ java_structs
4042 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4044 let cols_of_struct typ =
4045 try List.assoc typ structs
4047 failwithf "cols_of_struct: unknown struct %s" typ
4049 let seq_of_test = function
4050 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4051 | TestOutputListOfDevices (s, _)
4052 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4053 | TestOutputTrue s | TestOutputFalse s
4054 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4055 | TestOutputStruct (s, _)
4056 | TestLastFail s -> s
4058 (* Handling for function flags. *)
4059 let protocol_limit_warning =
4060 "Because of the message protocol, there is a transfer limit
4061 of somewhere between 2MB and 4MB. To transfer large files you should use
4064 let danger_will_robinson =
4065 "B<This command is dangerous. Without careful use you
4066 can easily destroy all your data>."
4068 let deprecation_notice flags =
4071 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4073 sprintf "This function is deprecated.
4074 In new code, use the C<%s> call instead.
4076 Deprecated functions will not be removed from the API, but the
4077 fact that they are deprecated indicates that there are problems
4078 with correct use of these functions." alt in
4083 (* Check function names etc. for consistency. *)
4084 let check_functions () =
4085 let contains_uppercase str =
4086 let len = String.length str in
4088 if i >= len then false
4091 if c >= 'A' && c <= 'Z' then true
4098 (* Check function names. *)
4100 fun (name, _, _, _, _, _, _) ->
4101 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4102 failwithf "function name %s does not need 'guestfs' prefix" name;
4104 failwithf "function name is empty";
4105 if name.[0] < 'a' || name.[0] > 'z' then
4106 failwithf "function name %s must start with lowercase a-z" name;
4107 if String.contains name '-' then
4108 failwithf "function name %s should not contain '-', use '_' instead."
4112 (* Check function parameter/return names. *)
4114 fun (name, style, _, _, _, _, _) ->
4115 let check_arg_ret_name n =
4116 if contains_uppercase n then
4117 failwithf "%s param/ret %s should not contain uppercase chars"
4119 if String.contains n '-' || String.contains n '_' then
4120 failwithf "%s param/ret %s should not contain '-' or '_'"
4123 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;
4124 if n = "int" || n = "char" || n = "short" || n = "long" then
4125 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4126 if n = "i" || n = "n" then
4127 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4128 if n = "argv" || n = "args" then
4129 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4131 (* List Haskell, OCaml and C keywords here.
4132 * http://www.haskell.org/haskellwiki/Keywords
4133 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4134 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4135 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4136 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4137 * Omitting _-containing words, since they're handled above.
4138 * Omitting the OCaml reserved word, "val", is ok,
4139 * and saves us from renaming several parameters.
4142 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4143 "char"; "class"; "const"; "constraint"; "continue"; "data";
4144 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4145 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4146 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4147 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4148 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4149 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4150 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4151 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4152 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4153 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4154 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4155 "volatile"; "when"; "where"; "while";
4157 if List.mem n reserved then
4158 failwithf "%s has param/ret using reserved word %s" name n;
4161 (match fst style with
4163 | RInt n | RInt64 n | RBool n
4164 | RConstString n | RConstOptString n | RString n
4165 | RStringList n | RStruct (n, _) | RStructList (n, _)
4166 | RHashtable n | RBufferOut n ->
4167 check_arg_ret_name n
4169 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4172 (* Check short descriptions. *)
4174 fun (name, _, _, _, _, shortdesc, _) ->
4175 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4176 failwithf "short description of %s should begin with lowercase." name;
4177 let c = shortdesc.[String.length shortdesc-1] in
4178 if c = '\n' || c = '.' then
4179 failwithf "short description of %s should not end with . or \\n." name
4182 (* Check long dscriptions. *)
4184 fun (name, _, _, _, _, _, longdesc) ->
4185 if longdesc.[String.length longdesc-1] = '\n' then
4186 failwithf "long description of %s should not end with \\n." name
4189 (* Check proc_nrs. *)
4191 fun (name, _, proc_nr, _, _, _, _) ->
4192 if proc_nr <= 0 then
4193 failwithf "daemon function %s should have proc_nr > 0" name
4197 fun (name, _, proc_nr, _, _, _, _) ->
4198 if proc_nr <> -1 then
4199 failwithf "non-daemon function %s should have proc_nr -1" name
4200 ) non_daemon_functions;
4203 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4206 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4207 let rec loop = function
4210 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4212 | (name1,nr1) :: (name2,nr2) :: _ ->
4213 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4221 (* Ignore functions that have no tests. We generate a
4222 * warning when the user does 'make check' instead.
4224 | name, _, _, _, [], _, _ -> ()
4225 | name, _, _, _, tests, _, _ ->
4229 match seq_of_test test with
4231 failwithf "%s has a test containing an empty sequence" name
4232 | cmds -> List.map List.hd cmds
4234 let funcs = List.flatten funcs in
4236 let tested = List.mem name funcs in
4239 failwithf "function %s has tests but does not test itself" name
4242 (* 'pr' prints to the current output file. *)
4243 let chan = ref stdout
4244 let pr fs = ksprintf (output_string !chan) fs
4246 (* Generate a header block in a number of standard styles. *)
4247 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4248 type license = GPLv2 | LGPLv2
4250 let generate_header comment license =
4251 let c = match comment with
4252 | CStyle -> pr "/* "; " *"
4253 | HashStyle -> pr "# "; "#"
4254 | OCamlStyle -> pr "(* "; " *"
4255 | HaskellStyle -> pr "{- "; " " in
4256 pr "libguestfs generated file\n";
4257 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4258 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4260 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4264 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4265 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4266 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4267 pr "%s (at your option) any later version.\n" c;
4269 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4270 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4271 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4272 pr "%s GNU General Public License for more details.\n" c;
4274 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4275 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4276 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4279 pr "%s This library is free software; you can redistribute it and/or\n" c;
4280 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4281 pr "%s License as published by the Free Software Foundation; either\n" c;
4282 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4284 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4285 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4286 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4287 pr "%s Lesser General Public License for more details.\n" c;
4289 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4290 pr "%s License along with this library; if not, write to the Free Software\n" c;
4291 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4294 | CStyle -> pr " */\n"
4296 | OCamlStyle -> pr " *)\n"
4297 | HaskellStyle -> pr "-}\n"
4301 (* Start of main code generation functions below this line. *)
4303 (* Generate the pod documentation for the C API. *)
4304 let rec generate_actions_pod () =
4306 fun (shortname, style, _, flags, _, _, longdesc) ->
4307 if not (List.mem NotInDocs flags) then (
4308 let name = "guestfs_" ^ shortname in
4309 pr "=head2 %s\n\n" name;
4311 generate_prototype ~extern:false ~handle:"handle" name style;
4313 pr "%s\n\n" longdesc;
4314 (match fst style with
4316 pr "This function returns 0 on success or -1 on error.\n\n"
4318 pr "On error this function returns -1.\n\n"
4320 pr "On error this function returns -1.\n\n"
4322 pr "This function returns a C truth value on success or -1 on error.\n\n"
4324 pr "This function returns a string, or NULL on error.
4325 The string is owned by the guest handle and must I<not> be freed.\n\n"
4326 | RConstOptString _ ->
4327 pr "This function returns a string which may be NULL.
4328 There is way to return an error from this function.
4329 The string is owned by the guest handle and must I<not> be freed.\n\n"
4331 pr "This function returns a string, or NULL on error.
4332 I<The caller must free the returned string after use>.\n\n"
4334 pr "This function returns a NULL-terminated array of strings
4335 (like L<environ(3)>), or NULL if there was an error.
4336 I<The caller must free the strings and the array after use>.\n\n"
4337 | RStruct (_, typ) ->
4338 pr "This function returns a C<struct guestfs_%s *>,
4339 or NULL if there was an error.
4340 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4341 | RStructList (_, typ) ->
4342 pr "This function returns a C<struct guestfs_%s_list *>
4343 (see E<lt>guestfs-structs.hE<gt>),
4344 or NULL if there was an error.
4345 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4347 pr "This function returns a NULL-terminated array of
4348 strings, or NULL if there was an error.
4349 The array of strings will always have length C<2n+1>, where
4350 C<n> keys and values alternate, followed by the trailing NULL entry.
4351 I<The caller must free the strings and the array after use>.\n\n"
4353 pr "This function returns a buffer, or NULL on error.
4354 The size of the returned buffer is written to C<*size_r>.
4355 I<The caller must free the returned buffer after use>.\n\n"
4357 if List.mem ProtocolLimitWarning flags then
4358 pr "%s\n\n" protocol_limit_warning;
4359 if List.mem DangerWillRobinson flags then
4360 pr "%s\n\n" danger_will_robinson;
4361 match deprecation_notice flags with
4363 | Some txt -> pr "%s\n\n" txt
4365 ) all_functions_sorted
4367 and generate_structs_pod () =
4368 (* Structs documentation. *)
4371 pr "=head2 guestfs_%s\n" typ;
4373 pr " struct guestfs_%s {\n" typ;
4376 | name, FChar -> pr " char %s;\n" name
4377 | name, FUInt32 -> pr " uint32_t %s;\n" name
4378 | name, FInt32 -> pr " int32_t %s;\n" name
4379 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4380 | name, FInt64 -> pr " int64_t %s;\n" name
4381 | name, FString -> pr " char *%s;\n" name
4383 pr " /* The next two fields describe a byte array. */\n";
4384 pr " uint32_t %s_len;\n" name;
4385 pr " char *%s;\n" name
4387 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4388 pr " char %s[32];\n" name
4389 | name, FOptPercent ->
4390 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4391 pr " float %s;\n" name
4395 pr " struct guestfs_%s_list {\n" typ;
4396 pr " uint32_t len; /* Number of elements in list. */\n";
4397 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4400 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4401 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4406 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4407 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4409 * We have to use an underscore instead of a dash because otherwise
4410 * rpcgen generates incorrect code.
4412 * This header is NOT exported to clients, but see also generate_structs_h.
4414 and generate_xdr () =
4415 generate_header CStyle LGPLv2;
4417 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4418 pr "typedef string str<>;\n";
4421 (* Internal structures. *)
4425 pr "struct guestfs_int_%s {\n" typ;
4427 | name, FChar -> pr " char %s;\n" name
4428 | name, FString -> pr " string %s<>;\n" name
4429 | name, FBuffer -> pr " opaque %s<>;\n" name
4430 | name, FUUID -> pr " opaque %s[32];\n" name
4431 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4432 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4433 | name, FOptPercent -> pr " float %s;\n" name
4437 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4442 fun (shortname, style, _, _, _, _, _) ->
4443 let name = "guestfs_" ^ shortname in
4445 (match snd style with
4448 pr "struct %s_args {\n" name;
4451 | Pathname n | Device n | Dev_or_Path n | String n -> pr " string %s<>;\n" n
4452 | OptString n -> pr " str *%s;\n" n
4453 | StringList n | DeviceList n -> pr " str %s<>;\n" n
4454 | Bool n -> pr " bool %s;\n" n
4455 | Int n -> pr " int %s;\n" n
4456 | FileIn _ | FileOut _ -> ()
4460 (match fst style with
4463 pr "struct %s_ret {\n" name;
4467 pr "struct %s_ret {\n" name;
4468 pr " hyper %s;\n" n;
4471 pr "struct %s_ret {\n" name;
4474 | RConstString _ | RConstOptString _ ->
4475 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4477 pr "struct %s_ret {\n" name;
4478 pr " string %s<>;\n" n;
4481 pr "struct %s_ret {\n" name;
4482 pr " str %s<>;\n" n;
4484 | RStruct (n, typ) ->
4485 pr "struct %s_ret {\n" name;
4486 pr " guestfs_int_%s %s;\n" typ n;
4488 | RStructList (n, typ) ->
4489 pr "struct %s_ret {\n" name;
4490 pr " guestfs_int_%s_list %s;\n" typ n;
4493 pr "struct %s_ret {\n" name;
4494 pr " str %s<>;\n" n;
4497 pr "struct %s_ret {\n" name;
4498 pr " opaque %s<>;\n" n;
4503 (* Table of procedure numbers. *)
4504 pr "enum guestfs_procedure {\n";
4506 fun (shortname, _, proc_nr, _, _, _, _) ->
4507 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4509 pr " GUESTFS_PROC_NR_PROCS\n";
4513 (* Having to choose a maximum message size is annoying for several
4514 * reasons (it limits what we can do in the API), but it (a) makes
4515 * the protocol a lot simpler, and (b) provides a bound on the size
4516 * of the daemon which operates in limited memory space. For large
4517 * file transfers you should use FTP.
4519 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4522 (* Message header, etc. *)
4524 /* The communication protocol is now documented in the guestfs(3)
4528 const GUESTFS_PROGRAM = 0x2000F5F5;
4529 const GUESTFS_PROTOCOL_VERSION = 1;
4531 /* These constants must be larger than any possible message length. */
4532 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4533 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4535 enum guestfs_message_direction {
4536 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4537 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4540 enum guestfs_message_status {
4541 GUESTFS_STATUS_OK = 0,
4542 GUESTFS_STATUS_ERROR = 1
4545 const GUESTFS_ERROR_LEN = 256;
4547 struct guestfs_message_error {
4548 string error_message<GUESTFS_ERROR_LEN>;
4551 struct guestfs_message_header {
4552 unsigned prog; /* GUESTFS_PROGRAM */
4553 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4554 guestfs_procedure proc; /* GUESTFS_PROC_x */
4555 guestfs_message_direction direction;
4556 unsigned serial; /* message serial number */
4557 guestfs_message_status status;
4560 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4562 struct guestfs_chunk {
4563 int cancel; /* if non-zero, transfer is cancelled */
4564 /* data size is 0 bytes if the transfer has finished successfully */
4565 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4569 (* Generate the guestfs-structs.h file. *)
4570 and generate_structs_h () =
4571 generate_header CStyle LGPLv2;
4573 (* This is a public exported header file containing various
4574 * structures. The structures are carefully written to have
4575 * exactly the same in-memory format as the XDR structures that
4576 * we use on the wire to the daemon. The reason for creating
4577 * copies of these structures here is just so we don't have to
4578 * export the whole of guestfs_protocol.h (which includes much
4579 * unrelated and XDR-dependent stuff that we don't want to be
4580 * public, or required by clients).
4582 * To reiterate, we will pass these structures to and from the
4583 * client with a simple assignment or memcpy, so the format
4584 * must be identical to what rpcgen / the RFC defines.
4587 (* Public structures. *)
4590 pr "struct guestfs_%s {\n" typ;
4593 | name, FChar -> pr " char %s;\n" name
4594 | name, FString -> pr " char *%s;\n" name
4596 pr " uint32_t %s_len;\n" name;
4597 pr " char *%s;\n" name
4598 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4599 | name, FUInt32 -> pr " uint32_t %s;\n" name
4600 | name, FInt32 -> pr " int32_t %s;\n" name
4601 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4602 | name, FInt64 -> pr " int64_t %s;\n" name
4603 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4607 pr "struct guestfs_%s_list {\n" typ;
4608 pr " uint32_t len;\n";
4609 pr " struct guestfs_%s *val;\n" typ;
4612 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4613 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4617 (* Generate the guestfs-actions.h file. *)
4618 and generate_actions_h () =
4619 generate_header CStyle LGPLv2;
4621 fun (shortname, style, _, _, _, _, _) ->
4622 let name = "guestfs_" ^ shortname in
4623 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4627 (* Generate the guestfs-internal-actions.h file. *)
4628 and generate_internal_actions_h () =
4629 generate_header CStyle LGPLv2;
4631 fun (shortname, style, _, _, _, _, _) ->
4632 let name = "guestfs__" ^ shortname in
4633 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4635 ) non_daemon_functions
4637 (* Generate the client-side dispatch stubs. *)
4638 and generate_client_actions () =
4639 generate_header CStyle LGPLv2;
4645 #include \"guestfs.h\"
4646 #include \"guestfs-internal-actions.h\"
4647 #include \"guestfs_protocol.h\"
4649 #define error guestfs_error
4650 //#define perrorf guestfs_perrorf
4651 //#define safe_malloc guestfs_safe_malloc
4652 #define safe_realloc guestfs_safe_realloc
4653 //#define safe_strdup guestfs_safe_strdup
4654 #define safe_memdup guestfs_safe_memdup
4656 /* Check the return message from a call for validity. */
4658 check_reply_header (guestfs_h *g,
4659 const struct guestfs_message_header *hdr,
4660 unsigned int proc_nr, unsigned int serial)
4662 if (hdr->prog != GUESTFS_PROGRAM) {
4663 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4666 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4667 error (g, \"wrong protocol version (%%d/%%d)\",
4668 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4671 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4672 error (g, \"unexpected message direction (%%d/%%d)\",
4673 hdr->direction, GUESTFS_DIRECTION_REPLY);
4676 if (hdr->proc != proc_nr) {
4677 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4680 if (hdr->serial != serial) {
4681 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4688 /* Check we are in the right state to run a high-level action. */
4690 check_state (guestfs_h *g, const char *caller)
4692 if (!guestfs__is_ready (g)) {
4693 if (guestfs__is_config (g) || guestfs__is_launching (g))
4694 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4697 error (g, \"%%s called from the wrong state, %%d != READY\",
4698 caller, guestfs__get_state (g));
4706 (* Generate code to generate guestfish call traces. *)
4707 let trace_call shortname style =
4708 pr " if (guestfs__get_trace (g)) {\n";
4711 List.exists (function
4712 | StringList _ | DeviceList _ -> true
4713 | _ -> false) (snd style) in
4719 pr " printf (\"%s\");\n" shortname;
4722 | String n (* strings *)
4728 (* guestfish doesn't support string escaping, so neither do we *)
4729 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
4730 | OptString n -> (* string option *)
4731 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4732 pr " else printf (\" null\");\n"
4734 | DeviceList n -> (* string list *)
4735 pr " putchar (' ');\n";
4736 pr " putchar ('\"');\n";
4737 pr " for (i = 0; %s[i]; ++i) {\n" n;
4738 pr " if (i > 0) putchar (' ');\n";
4739 pr " fputs (%s[i], stdout);\n" n;
4741 pr " putchar ('\"');\n";
4742 | Bool n -> (* boolean *)
4743 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
4744 | Int n -> (* int *)
4745 pr " printf (\" %%d\", %s);\n" n
4747 pr " putchar ('\\n');\n";
4752 (* For non-daemon functions, generate a wrapper around each function. *)
4754 fun (shortname, style, _, _, _, _, _) ->
4755 let name = "guestfs_" ^ shortname in
4757 generate_prototype ~extern:false ~semicolon:false ~newline:true
4758 ~handle:"g" name style;
4760 trace_call shortname style;
4761 pr " return guestfs__%s " shortname;
4762 generate_c_call_args ~handle:"g" style;
4766 ) non_daemon_functions;
4768 (* Client-side stubs for each function. *)
4770 fun (shortname, style, _, _, _, _, _) ->
4771 let name = "guestfs_" ^ shortname in
4773 (* Generate the action stub. *)
4774 generate_prototype ~extern:false ~semicolon:false ~newline:true
4775 ~handle:"g" name style;
4778 match fst style with
4779 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4780 | RConstString _ | RConstOptString _ ->
4781 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4782 | RString _ | RStringList _
4783 | RStruct _ | RStructList _
4784 | RHashtable _ | RBufferOut _ ->
4789 (match snd style with
4791 | _ -> pr " struct %s_args args;\n" name
4794 pr " guestfs_message_header hdr;\n";
4795 pr " guestfs_message_error err;\n";
4797 match fst style with
4799 | RConstString _ | RConstOptString _ ->
4800 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4802 | RBool _ | RString _ | RStringList _
4803 | RStruct _ | RStructList _
4804 | RHashtable _ | RBufferOut _ ->
4805 pr " struct %s_ret ret;\n" name;
4808 pr " int serial;\n";
4811 trace_call shortname style;
4812 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4813 pr " guestfs___set_busy (g);\n";
4816 (* Send the main header and arguments. *)
4817 (match snd style with
4819 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4820 (String.uppercase shortname)
4824 | Pathname n | Device n | Dev_or_Path n | String n ->
4825 pr " args.%s = (char *) %s;\n" n n
4827 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
4828 | StringList n | DeviceList n ->
4829 pr " args.%s.%s_val = (char **) %s;\n" n n n;
4830 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4832 pr " args.%s = %s;\n" n n
4834 pr " args.%s = %s;\n" n n
4835 | FileIn _ | FileOut _ -> ()
4837 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4838 (String.uppercase shortname);
4839 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4842 pr " if (serial == -1) {\n";
4843 pr " guestfs___end_busy (g);\n";
4844 pr " return %s;\n" error_code;
4848 (* Send any additional files (FileIn) requested. *)
4849 let need_read_reply_label = ref false in
4853 pr " r = guestfs___send_file (g, %s);\n" n;
4854 pr " if (r == -1) {\n";
4855 pr " guestfs___end_busy (g);\n";
4856 pr " return %s;\n" error_code;
4858 pr " if (r == -2) /* daemon cancelled */\n";
4859 pr " goto read_reply;\n";
4860 need_read_reply_label := true;
4865 (* Wait for the reply from the remote end. *)
4866 if !need_read_reply_label then pr " read_reply:\n";
4867 pr " memset (&hdr, 0, sizeof hdr);\n";
4868 pr " memset (&err, 0, sizeof err);\n";
4869 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
4871 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
4875 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
4878 pr " if (r == -1) {\n";
4879 pr " guestfs___end_busy (g);\n";
4880 pr " return %s;\n" error_code;
4884 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4885 (String.uppercase shortname);
4886 pr " guestfs___end_busy (g);\n";
4887 pr " return %s;\n" error_code;
4891 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
4892 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
4893 pr " free (err.error_message);\n";
4894 pr " guestfs___end_busy (g);\n";
4895 pr " return %s;\n" error_code;
4899 (* Expecting to receive further files (FileOut)? *)
4903 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
4904 pr " guestfs___end_busy (g);\n";
4905 pr " return %s;\n" error_code;
4911 pr " guestfs___end_busy (g);\n";
4913 (match fst style with
4914 | RErr -> pr " return 0;\n"
4915 | RInt n | RInt64 n | RBool n ->
4916 pr " return ret.%s;\n" n
4917 | RConstString _ | RConstOptString _ ->
4918 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4920 pr " return ret.%s; /* caller will free */\n" n
4921 | RStringList n | RHashtable n ->
4922 pr " /* caller will free this, but we need to add a NULL entry */\n";
4923 pr " ret.%s.%s_val =\n" n n;
4924 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
4925 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
4927 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
4928 pr " return ret.%s.%s_val;\n" n n
4930 pr " /* caller will free this */\n";
4931 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4932 | RStructList (n, _) ->
4933 pr " /* caller will free this */\n";
4934 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4936 pr " *size_r = ret.%s.%s_len;\n" n n;
4937 pr " return ret.%s.%s_val; /* caller will free */\n" n n
4943 (* Functions to free structures. *)
4944 pr "/* Structure-freeing functions. These rely on the fact that the\n";
4945 pr " * structure format is identical to the XDR format. See note in\n";
4946 pr " * generator.ml.\n";
4953 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4955 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4961 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4963 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4970 (* Generate daemon/actions.h. *)
4971 and generate_daemon_actions_h () =
4972 generate_header CStyle GPLv2;
4974 pr "#include \"../src/guestfs_protocol.h\"\n";
4978 fun (name, style, _, _, _, _, _) ->
4980 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4984 (* Generate the server-side stubs. *)
4985 and generate_daemon_actions () =
4986 generate_header CStyle GPLv2;
4988 pr "#include <config.h>\n";
4990 pr "#include <stdio.h>\n";
4991 pr "#include <stdlib.h>\n";
4992 pr "#include <string.h>\n";
4993 pr "#include <inttypes.h>\n";
4994 pr "#include <rpc/types.h>\n";
4995 pr "#include <rpc/xdr.h>\n";
4997 pr "#include \"daemon.h\"\n";
4998 pr "#include \"c-ctype.h\"\n";
4999 pr "#include \"../src/guestfs_protocol.h\"\n";
5000 pr "#include \"actions.h\"\n";
5004 fun (name, style, _, _, _, _, _) ->
5005 (* Generate server-side stubs. *)
5006 pr "static void %s_stub (XDR *xdr_in)\n" name;
5009 match fst style with
5010 | RErr | RInt _ -> pr " int r;\n"; "-1"
5011 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5012 | RBool _ -> pr " int r;\n"; "-1"
5013 | RConstString _ | RConstOptString _ ->
5014 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5015 | RString _ -> pr " char *r;\n"; "NULL"
5016 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5017 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5018 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5020 pr " size_t size;\n";
5024 (match snd style with
5027 pr " struct guestfs_%s_args args;\n" name;
5030 | Device n | Dev_or_Path n
5033 | OptString n -> pr " char *%s;\n" n
5034 | StringList n | DeviceList n -> pr " char **%s;\n" n
5035 | Bool n -> pr " int %s;\n" n
5036 | Int n -> pr " int %s;\n" n
5037 | FileIn _ | FileOut _ -> ()
5042 (match snd style with
5045 pr " memset (&args, 0, sizeof args);\n";
5047 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5048 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5052 pr " char *%s = args.%s;\n" n n
5054 let pr_list_handling_code n =
5055 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5056 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5057 pr " if (%s == NULL) {\n" n;
5058 pr " reply_with_perror (\"realloc\");\n";
5061 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5062 pr " args.%s.%s_val = %s;\n" n n n;
5068 pr " ABS_PATH (%s, goto done);\n" n;
5071 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5074 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5075 | String n -> pr_args n
5076 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5078 pr_list_handling_code n;
5080 pr_list_handling_code n;
5081 pr " /* Ensure that each is a device,\n";
5082 pr " * and perform device name translation. */\n";
5083 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5084 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5086 | Bool n -> pr " %s = args.%s;\n" n n
5087 | Int n -> pr " %s = args.%s;\n" n n
5088 | FileIn _ | FileOut _ -> ()
5094 (* this is used at least for do_equal *)
5095 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5096 (* Emit NEED_ROOT just once, even when there are two or
5097 more Pathname args *)
5098 pr " NEED_ROOT (goto done);\n";
5101 (* Don't want to call the impl with any FileIn or FileOut
5102 * parameters, since these go "outside" the RPC protocol.
5105 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5107 pr " r = do_%s " name;
5108 generate_c_call_args (fst style, args');
5111 pr " if (r == %s)\n" error_code;
5112 pr " /* do_%s has already called reply_with_error */\n" name;
5116 (* If there are any FileOut parameters, then the impl must
5117 * send its own reply.
5120 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5122 pr " /* do_%s has already sent a reply */\n" name
5124 match fst style with
5125 | RErr -> pr " reply (NULL, NULL);\n"
5126 | RInt n | RInt64 n | RBool n ->
5127 pr " struct guestfs_%s_ret ret;\n" name;
5128 pr " ret.%s = r;\n" n;
5129 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5131 | RConstString _ | RConstOptString _ ->
5132 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5134 pr " struct guestfs_%s_ret ret;\n" name;
5135 pr " ret.%s = r;\n" n;
5136 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5139 | RStringList n | RHashtable n ->
5140 pr " struct guestfs_%s_ret ret;\n" name;
5141 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5142 pr " ret.%s.%s_val = r;\n" n n;
5143 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5145 pr " free_strings (r);\n"
5147 pr " struct guestfs_%s_ret ret;\n" name;
5148 pr " ret.%s = *r;\n" n;
5149 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5151 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5153 | RStructList (n, _) ->
5154 pr " struct guestfs_%s_ret ret;\n" name;
5155 pr " ret.%s = *r;\n" n;
5156 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5158 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5161 pr " struct guestfs_%s_ret ret;\n" name;
5162 pr " ret.%s.%s_val = r;\n" n n;
5163 pr " ret.%s.%s_len = size;\n" n n;
5164 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5169 (* Free the args. *)
5170 (match snd style with
5175 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5182 (* Dispatch function. *)
5183 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5185 pr " switch (proc_nr) {\n";
5188 fun (name, style, _, _, _, _, _) ->
5189 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5190 pr " %s_stub (xdr_in);\n" name;
5195 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";
5200 (* LVM columns and tokenization functions. *)
5201 (* XXX This generates crap code. We should rethink how we
5207 pr "static const char *lvm_%s_cols = \"%s\";\n"
5208 typ (String.concat "," (List.map fst cols));
5211 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5213 pr " char *tok, *p, *next;\n";
5217 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5220 pr " if (!str) {\n";
5221 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5224 pr " if (!*str || c_isspace (*str)) {\n";
5225 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5230 fun (name, coltype) ->
5231 pr " if (!tok) {\n";
5232 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5235 pr " p = strchrnul (tok, ',');\n";
5236 pr " if (*p) next = p+1; else next = NULL;\n";
5237 pr " *p = '\\0';\n";
5240 pr " r->%s = strdup (tok);\n" name;
5241 pr " if (r->%s == NULL) {\n" name;
5242 pr " perror (\"strdup\");\n";
5246 pr " for (i = j = 0; i < 32; ++j) {\n";
5247 pr " if (tok[j] == '\\0') {\n";
5248 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5250 pr " } else if (tok[j] != '-')\n";
5251 pr " r->%s[i++] = tok[j];\n" name;
5254 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5255 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5259 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5260 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5264 pr " if (tok[0] == '\\0')\n";
5265 pr " r->%s = -1;\n" name;
5266 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5267 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5270 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5271 assert false (* can never be an LVM column *)
5273 pr " tok = next;\n";
5276 pr " if (tok != NULL) {\n";
5277 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5284 pr "guestfs_int_lvm_%s_list *\n" typ;
5285 pr "parse_command_line_%ss (void)\n" typ;
5287 pr " char *out, *err;\n";
5288 pr " char *p, *pend;\n";
5290 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
5291 pr " void *newp;\n";
5293 pr " ret = malloc (sizeof *ret);\n";
5294 pr " if (!ret) {\n";
5295 pr " reply_with_perror (\"malloc\");\n";
5296 pr " return NULL;\n";
5299 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5300 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5302 pr " r = command (&out, &err,\n";
5303 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
5304 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5305 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5306 pr " if (r == -1) {\n";
5307 pr " reply_with_error (\"%%s\", err);\n";
5308 pr " free (out);\n";
5309 pr " free (err);\n";
5310 pr " free (ret);\n";
5311 pr " return NULL;\n";
5314 pr " free (err);\n";
5316 pr " /* Tokenize each line of the output. */\n";
5319 pr " while (p) {\n";
5320 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
5321 pr " if (pend) {\n";
5322 pr " *pend = '\\0';\n";
5326 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
5329 pr " if (!*p) { /* Empty line? Skip it. */\n";
5334 pr " /* Allocate some space to store this next entry. */\n";
5335 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5336 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5337 pr " if (newp == NULL) {\n";
5338 pr " reply_with_perror (\"realloc\");\n";
5339 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5340 pr " free (ret);\n";
5341 pr " free (out);\n";
5342 pr " return NULL;\n";
5344 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5346 pr " /* Tokenize the next entry. */\n";
5347 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5348 pr " if (r == -1) {\n";
5349 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5350 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5351 pr " free (ret);\n";
5352 pr " free (out);\n";
5353 pr " return NULL;\n";
5360 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5362 pr " free (out);\n";
5363 pr " return ret;\n";
5366 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5368 (* Generate a list of function names, for debugging in the daemon.. *)
5369 and generate_daemon_names () =
5370 generate_header CStyle GPLv2;
5372 pr "#include <config.h>\n";
5374 pr "#include \"daemon.h\"\n";
5377 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5378 pr "const char *function_names[] = {\n";
5380 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5384 (* Generate the tests. *)
5385 and generate_tests () =
5386 generate_header CStyle GPLv2;
5393 #include <sys/types.h>
5396 #include \"guestfs.h\"
5398 static guestfs_h *g;
5399 static int suppress_error = 0;
5401 static void print_error (guestfs_h *g, void *data, const char *msg)
5403 if (!suppress_error)
5404 fprintf (stderr, \"%%s\\n\", msg);
5407 /* FIXME: nearly identical code appears in fish.c */
5408 static void print_strings (char *const *argv)
5412 for (argc = 0; argv[argc] != NULL; ++argc)
5413 printf (\"\\t%%s\\n\", argv[argc]);
5417 static void print_table (char const *const *argv)
5421 for (i = 0; argv[i] != NULL; i += 2)
5422 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5428 (* Generate a list of commands which are not tested anywhere. *)
5429 pr "static void no_test_warnings (void)\n";
5432 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5434 fun (_, _, _, _, tests, _, _) ->
5435 let tests = filter_map (
5437 | (_, (Always|If _|Unless _), test) -> Some test
5438 | (_, Disabled, _) -> None
5440 let seq = List.concat (List.map seq_of_test tests) in
5441 let cmds_tested = List.map List.hd seq in
5442 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5446 fun (name, _, _, _, _, _, _) ->
5447 if not (Hashtbl.mem hash name) then
5448 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5454 (* Generate the actual tests. Note that we generate the tests
5455 * in reverse order, deliberately, so that (in general) the
5456 * newest tests run first. This makes it quicker and easier to
5461 fun (name, _, _, _, tests, _, _) ->
5462 mapi (generate_one_test name) tests
5463 ) (List.rev all_functions) in
5464 let test_names = List.concat test_names in
5465 let nr_tests = List.length test_names in
5468 int main (int argc, char *argv[])
5471 unsigned long int n_failed = 0;
5472 const char *filename;
5474 int nr_tests, test_num = 0;
5476 setbuf (stdout, NULL);
5478 no_test_warnings ();
5480 g = guestfs_create ();
5482 printf (\"guestfs_create FAILED\\n\");
5486 guestfs_set_error_handler (g, print_error, NULL);
5488 guestfs_set_path (g, \"../appliance\");
5490 filename = \"test1.img\";
5491 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5496 if (lseek (fd, %d, SEEK_SET) == -1) {
5502 if (write (fd, &c, 1) == -1) {
5508 if (close (fd) == -1) {
5513 if (guestfs_add_drive (g, filename) == -1) {
5514 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5518 filename = \"test2.img\";
5519 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5524 if (lseek (fd, %d, SEEK_SET) == -1) {
5530 if (write (fd, &c, 1) == -1) {
5536 if (close (fd) == -1) {
5541 if (guestfs_add_drive (g, filename) == -1) {
5542 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5546 filename = \"test3.img\";
5547 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5552 if (lseek (fd, %d, SEEK_SET) == -1) {
5558 if (write (fd, &c, 1) == -1) {
5564 if (close (fd) == -1) {
5569 if (guestfs_add_drive (g, filename) == -1) {
5570 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5574 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5575 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5579 if (guestfs_launch (g) == -1) {
5580 printf (\"guestfs_launch FAILED\\n\");
5584 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5587 /* Cancel previous alarm. */
5592 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5596 pr " test_num++;\n";
5597 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5598 pr " if (%s () == -1) {\n" test_name;
5599 pr " printf (\"%s FAILED\\n\");\n" test_name;
5600 pr " n_failed++;\n";
5605 pr " guestfs_close (g);\n";
5606 pr " unlink (\"test1.img\");\n";
5607 pr " unlink (\"test2.img\");\n";
5608 pr " unlink (\"test3.img\");\n";
5611 pr " if (n_failed > 0) {\n";
5612 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5620 and generate_one_test name i (init, prereq, test) =
5621 let test_name = sprintf "test_%s_%d" name i in
5624 static int %s_skip (void)
5628 str = getenv (\"TEST_ONLY\");
5630 return strstr (str, \"%s\") == NULL;
5631 str = getenv (\"SKIP_%s\");
5632 if (str && strcmp (str, \"1\") == 0) return 1;
5633 str = getenv (\"SKIP_TEST_%s\");
5634 if (str && strcmp (str, \"1\") == 0) return 1;
5638 " test_name name (String.uppercase test_name) (String.uppercase name);
5641 | Disabled | Always -> ()
5642 | If code | Unless code ->
5643 pr "static int %s_prereq (void)\n" test_name;
5651 static int %s (void)
5654 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5658 " test_name test_name test_name;
5662 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5664 pr " if (! %s_prereq ()) {\n" test_name;
5665 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5669 generate_one_test_body name i test_name init test;
5671 pr " if (%s_prereq ()) {\n" test_name;
5672 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5676 generate_one_test_body name i test_name init test;
5678 generate_one_test_body name i test_name init test
5686 and generate_one_test_body name i test_name init test =
5688 | InitNone (* XXX at some point, InitNone and InitEmpty became
5689 * folded together as the same thing. Really we should
5690 * make InitNone do nothing at all, but the tests may
5691 * need to be checked to make sure this is OK.
5694 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5695 List.iter (generate_test_command_call test_name)
5696 [["blockdev_setrw"; "/dev/sda"];
5700 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5701 List.iter (generate_test_command_call test_name)
5702 [["blockdev_setrw"; "/dev/sda"];
5705 ["sfdiskM"; "/dev/sda"; ","]]
5707 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5708 List.iter (generate_test_command_call test_name)
5709 [["blockdev_setrw"; "/dev/sda"];
5712 ["sfdiskM"; "/dev/sda"; ","];
5713 ["mkfs"; "ext2"; "/dev/sda1"];
5714 ["mount"; "/dev/sda1"; "/"]]
5715 | InitBasicFSonLVM ->
5716 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5718 List.iter (generate_test_command_call test_name)
5719 [["blockdev_setrw"; "/dev/sda"];
5722 ["sfdiskM"; "/dev/sda"; ","];
5723 ["pvcreate"; "/dev/sda1"];
5724 ["vgcreate"; "VG"; "/dev/sda1"];
5725 ["lvcreate"; "LV"; "VG"; "8"];
5726 ["mkfs"; "ext2"; "/dev/VG/LV"];
5727 ["mount"; "/dev/VG/LV"; "/"]]
5729 pr " /* InitISOFS for %s */\n" test_name;
5730 List.iter (generate_test_command_call test_name)
5731 [["blockdev_setrw"; "/dev/sda"];
5734 ["mount_ro"; "/dev/sdd"; "/"]]
5737 let get_seq_last = function
5739 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5742 let seq = List.rev seq in
5743 List.rev (List.tl seq), List.hd seq
5748 pr " /* TestRun for %s (%d) */\n" name i;
5749 List.iter (generate_test_command_call test_name) seq
5750 | TestOutput (seq, expected) ->
5751 pr " /* TestOutput for %s (%d) */\n" name i;
5752 pr " const char *expected = \"%s\";\n" (c_quote expected);
5753 let seq, last = get_seq_last seq in
5755 pr " if (strcmp (r, expected) != 0) {\n";
5756 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5760 List.iter (generate_test_command_call test_name) seq;
5761 generate_test_command_call ~test test_name last
5762 | TestOutputList (seq, expected) ->
5763 pr " /* TestOutputList for %s (%d) */\n" name i;
5764 let seq, last = get_seq_last seq in
5768 pr " if (!r[%d]) {\n" i;
5769 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5770 pr " print_strings (r);\n";
5774 pr " const char *expected = \"%s\";\n" (c_quote str);
5775 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5776 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5781 pr " if (r[%d] != NULL) {\n" (List.length expected);
5782 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5784 pr " print_strings (r);\n";
5788 List.iter (generate_test_command_call test_name) seq;
5789 generate_test_command_call ~test test_name last
5790 | TestOutputListOfDevices (seq, expected) ->
5791 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
5792 let seq, last = get_seq_last seq in
5796 pr " if (!r[%d]) {\n" i;
5797 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5798 pr " print_strings (r);\n";
5802 pr " const char *expected = \"%s\";\n" (c_quote str);
5803 pr " r[%d][5] = 's';\n" i;
5804 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5805 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5810 pr " if (r[%d] != NULL) {\n" (List.length expected);
5811 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5813 pr " print_strings (r);\n";
5817 List.iter (generate_test_command_call test_name) seq;
5818 generate_test_command_call ~test test_name last
5819 | TestOutputInt (seq, expected) ->
5820 pr " /* TestOutputInt for %s (%d) */\n" name i;
5821 let seq, last = get_seq_last seq in
5823 pr " if (r != %d) {\n" expected;
5824 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5830 List.iter (generate_test_command_call test_name) seq;
5831 generate_test_command_call ~test test_name last
5832 | TestOutputIntOp (seq, op, expected) ->
5833 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
5834 let seq, last = get_seq_last seq in
5836 pr " if (! (r %s %d)) {\n" op expected;
5837 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5838 test_name op expected;
5843 List.iter (generate_test_command_call test_name) seq;
5844 generate_test_command_call ~test test_name last
5845 | TestOutputTrue seq ->
5846 pr " /* TestOutputTrue for %s (%d) */\n" name i;
5847 let seq, last = get_seq_last seq in
5850 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5855 List.iter (generate_test_command_call test_name) seq;
5856 generate_test_command_call ~test test_name last
5857 | TestOutputFalse seq ->
5858 pr " /* TestOutputFalse for %s (%d) */\n" name i;
5859 let seq, last = get_seq_last seq in
5862 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5867 List.iter (generate_test_command_call test_name) seq;
5868 generate_test_command_call ~test test_name last
5869 | TestOutputLength (seq, expected) ->
5870 pr " /* TestOutputLength for %s (%d) */\n" name i;
5871 let seq, last = get_seq_last seq in
5874 pr " for (j = 0; j < %d; ++j)\n" expected;
5875 pr " if (r[j] == NULL) {\n";
5876 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
5878 pr " print_strings (r);\n";
5881 pr " if (r[j] != NULL) {\n";
5882 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
5884 pr " print_strings (r);\n";
5888 List.iter (generate_test_command_call test_name) seq;
5889 generate_test_command_call ~test test_name last
5890 | TestOutputBuffer (seq, expected) ->
5891 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
5892 pr " const char *expected = \"%s\";\n" (c_quote expected);
5893 let seq, last = get_seq_last seq in
5894 let len = String.length expected in
5896 pr " if (size != %d) {\n" len;
5897 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5900 pr " if (strncmp (r, expected, size) != 0) {\n";
5901 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5905 List.iter (generate_test_command_call test_name) seq;
5906 generate_test_command_call ~test test_name last
5907 | TestOutputStruct (seq, checks) ->
5908 pr " /* TestOutputStruct for %s (%d) */\n" name i;
5909 let seq, last = get_seq_last seq in
5913 | CompareWithInt (field, expected) ->
5914 pr " if (r->%s != %d) {\n" field expected;
5915 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5916 test_name field expected;
5917 pr " (int) r->%s);\n" field;
5920 | CompareWithIntOp (field, op, expected) ->
5921 pr " if (!(r->%s %s %d)) {\n" field op expected;
5922 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5923 test_name field op expected;
5924 pr " (int) r->%s);\n" field;
5927 | CompareWithString (field, expected) ->
5928 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5929 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5930 test_name field expected;
5931 pr " r->%s);\n" field;
5934 | CompareFieldsIntEq (field1, field2) ->
5935 pr " if (r->%s != r->%s) {\n" field1 field2;
5936 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5937 test_name field1 field2;
5938 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
5941 | CompareFieldsStrEq (field1, field2) ->
5942 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5943 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5944 test_name field1 field2;
5945 pr " r->%s, r->%s);\n" field1 field2;
5950 List.iter (generate_test_command_call test_name) seq;
5951 generate_test_command_call ~test test_name last
5952 | TestLastFail seq ->
5953 pr " /* TestLastFail for %s (%d) */\n" name i;
5954 let seq, last = get_seq_last seq in
5955 List.iter (generate_test_command_call test_name) seq;
5956 generate_test_command_call test_name ~expect_error:true last
5958 (* Generate the code to run a command, leaving the result in 'r'.
5959 * If you expect to get an error then you should set expect_error:true.
5961 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5963 | [] -> assert false
5965 (* Look up the command to find out what args/ret it has. *)
5968 let _, style, _, _, _, _, _ =
5969 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5972 failwithf "%s: in test, command %s was not found" test_name name in
5974 if List.length (snd style) <> List.length args then
5975 failwithf "%s: in test, wrong number of args given to %s"
5982 | OptString n, "NULL" -> ()
5985 | Dev_or_Path n, arg
5987 | OptString n, arg ->
5988 pr " const char *%s = \"%s\";\n" n (c_quote arg);
5991 | FileIn _, _ | FileOut _, _ -> ()
5992 | StringList n, arg | DeviceList n, arg ->
5993 let strs = string_split " " arg in
5996 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
5998 pr " const char *const %s[] = {\n" n;
6000 fun i _ -> pr " %s_%d,\n" n i
6004 ) (List.combine (snd style) args);
6007 match fst style with
6008 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6009 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6010 | RConstString _ | RConstOptString _ ->
6011 pr " const char *r;\n"; "NULL"
6012 | RString _ -> pr " char *r;\n"; "NULL"
6013 | RStringList _ | RHashtable _ ->
6017 | RStruct (_, typ) ->
6018 pr " struct guestfs_%s *r;\n" typ; "NULL"
6019 | RStructList (_, typ) ->
6020 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6023 pr " size_t size;\n";
6026 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
6027 pr " r = guestfs_%s (g" name;
6029 (* Generate the parameters. *)
6032 | OptString _, "NULL" -> pr ", NULL"
6034 | Device n, _ | Dev_or_Path n, _
6038 | FileIn _, arg | FileOut _, arg ->
6039 pr ", \"%s\"" (c_quote arg)
6040 | StringList n, _ | DeviceList n, _ ->
6041 pr ", (char **) %s" n
6044 try int_of_string arg
6045 with Failure "int_of_string" ->
6046 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6049 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6050 ) (List.combine (snd style) args);
6052 (match fst style with
6053 | RBufferOut _ -> pr ", &size"
6059 if not expect_error then
6060 pr " if (r == %s)\n" error_code
6062 pr " if (r != %s)\n" error_code;
6065 (* Insert the test code. *)
6071 (match fst style with
6072 | RErr | RInt _ | RInt64 _ | RBool _
6073 | RConstString _ | RConstOptString _ -> ()
6074 | RString _ | RBufferOut _ -> pr " free (r);\n"
6075 | RStringList _ | RHashtable _ ->
6076 pr " for (i = 0; r[i] != NULL; ++i)\n";
6077 pr " free (r[i]);\n";
6079 | RStruct (_, typ) ->
6080 pr " guestfs_free_%s (r);\n" typ
6081 | RStructList (_, typ) ->
6082 pr " guestfs_free_%s_list (r);\n" typ
6088 let str = replace_str str "\r" "\\r" in
6089 let str = replace_str str "\n" "\\n" in
6090 let str = replace_str str "\t" "\\t" in
6091 let str = replace_str str "\000" "\\0" in
6094 (* Generate a lot of different functions for guestfish. *)
6095 and generate_fish_cmds () =
6096 generate_header CStyle GPLv2;
6100 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6102 let all_functions_sorted =
6104 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6105 ) all_functions_sorted in
6107 pr "#include <stdio.h>\n";
6108 pr "#include <stdlib.h>\n";
6109 pr "#include <string.h>\n";
6110 pr "#include <inttypes.h>\n";
6112 pr "#include <guestfs.h>\n";
6113 pr "#include \"c-ctype.h\"\n";
6114 pr "#include \"fish.h\"\n";
6117 (* list_commands function, which implements guestfish -h *)
6118 pr "void list_commands (void)\n";
6120 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6121 pr " list_builtin_commands ();\n";
6123 fun (name, _, _, flags, _, shortdesc, _) ->
6124 let name = replace_char name '_' '-' in
6125 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6127 ) all_functions_sorted;
6128 pr " printf (\" %%s\\n\",";
6129 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6133 (* display_command function, which implements guestfish -h cmd *)
6134 pr "void display_command (const char *cmd)\n";
6137 fun (name, style, _, flags, _, shortdesc, longdesc) ->
6138 let name2 = replace_char name '_' '-' in
6140 try find_map (function FishAlias n -> Some n | _ -> None) flags
6141 with Not_found -> name in
6142 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6144 match snd style with
6148 name2 (String.concat "> <" (List.map name_of_argt args)) in
6151 if List.mem ProtocolLimitWarning flags then
6152 ("\n\n" ^ protocol_limit_warning)
6155 (* For DangerWillRobinson commands, we should probably have
6156 * guestfish prompt before allowing you to use them (especially
6157 * in interactive mode). XXX
6161 if List.mem DangerWillRobinson flags then
6162 ("\n\n" ^ danger_will_robinson)
6167 match deprecation_notice flags with
6169 | Some txt -> "\n\n" ^ txt in
6171 let describe_alias =
6172 if name <> alias then
6173 sprintf "\n\nYou can use '%s' as an alias for this command." alias
6177 pr "strcasecmp (cmd, \"%s\") == 0" name;
6178 if name <> name2 then
6179 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6180 if name <> alias then
6181 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6183 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
6185 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6188 pr " display_builtin_command (cmd);\n";
6192 let emit_print_list_function typ =
6193 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6196 pr " unsigned int i;\n";
6198 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6199 pr " printf (\"[%%d] = {\\n\", i);\n";
6200 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
6201 pr " printf (\"}\\n\");\n";
6207 (* print_* functions *)
6211 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6213 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6216 pr " unsigned int i;\n";
6222 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6224 pr " printf (\"%s: \");\n" name;
6225 pr " for (i = 0; i < 32; ++i)\n";
6226 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6227 pr " printf (\"\\n\");\n"
6229 pr " printf (\"%%s%s: \", indent);\n" name;
6230 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6231 pr " if (c_isprint (%s->%s[i]))\n" typ name;
6232 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6234 pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6235 pr " printf (\"\\n\");\n"
6236 | name, (FUInt64|FBytes) ->
6237 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6240 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6243 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6246 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6249 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6251 | name, FOptPercent ->
6252 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6253 typ name name typ name;
6254 pr " else printf (\"%%s%s: \\n\", indent);\n" name
6260 (* Emit a print_TYPE_list function definition only if that function is used. *)
6263 | typ, (RStructListOnly | RStructAndList) ->
6264 (* generate the function for typ *)
6265 emit_print_list_function typ
6266 | typ, _ -> () (* empty *)
6269 (* Emit a print_TYPE function definition only if that function is used. *)
6272 | typ, RStructOnly ->
6273 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6275 pr " print_%s_indent (%s, \"\");\n" typ typ;
6278 | typ, _ -> () (* empty *)
6281 (* run_<action> actions *)
6283 fun (name, style, _, flags, _, _, _) ->
6284 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6286 (match fst style with
6289 | RBool _ -> pr " int r;\n"
6290 | RInt64 _ -> pr " int64_t r;\n"
6291 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
6292 | RString _ -> pr " char *r;\n"
6293 | RStringList _ | RHashtable _ -> pr " char **r;\n"
6294 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
6295 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
6298 pr " size_t size;\n";
6303 | Device n | Dev_or_Path n
6307 | FileOut n -> pr " const char *%s;\n" n
6308 | StringList n | DeviceList n -> pr " char **%s;\n" n
6309 | Bool n -> pr " int %s;\n" n
6310 | Int n -> pr " int %s;\n" n
6313 (* Check and convert parameters. *)
6314 let argc_expected = List.length (snd style) in
6315 pr " if (argc != %d) {\n" argc_expected;
6316 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6318 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6325 | Device name | Dev_or_Path name | String name -> pr " %s = argv[%d];\n" name i
6327 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6330 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6333 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6335 | StringList name | DeviceList name ->
6336 pr " %s = parse_string_list (argv[%d]);\n" name i;
6337 pr " if (%s == NULL) return -1;\n" name;
6339 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6341 pr " %s = atoi (argv[%d]);\n" name i
6344 (* Call C API function. *)
6346 try find_map (function FishAction n -> Some n | _ -> None) flags
6347 with Not_found -> sprintf "guestfs_%s" name in
6349 generate_c_call_args ~handle:"g" style;
6354 | Pathname name | Device name | Dev_or_Path name | String name
6355 | OptString name | FileIn name | FileOut name | Bool name
6357 | StringList name | DeviceList name ->
6358 pr " free_strings (%s);\n" name
6361 (* Check return value for errors and display command results. *)
6362 (match fst style with
6363 | RErr -> pr " return r;\n"
6365 pr " if (r == -1) return -1;\n";
6366 pr " printf (\"%%d\\n\", r);\n";
6369 pr " if (r == -1) return -1;\n";
6370 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6373 pr " if (r == -1) return -1;\n";
6374 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6377 pr " if (r == NULL) return -1;\n";
6378 pr " printf (\"%%s\\n\", r);\n";
6380 | RConstOptString _ ->
6381 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6384 pr " if (r == NULL) return -1;\n";
6385 pr " printf (\"%%s\\n\", r);\n";
6389 pr " if (r == NULL) return -1;\n";
6390 pr " print_strings (r);\n";
6391 pr " free_strings (r);\n";
6393 | RStruct (_, typ) ->
6394 pr " if (r == NULL) return -1;\n";
6395 pr " print_%s (r);\n" typ;
6396 pr " guestfs_free_%s (r);\n" typ;
6398 | RStructList (_, typ) ->
6399 pr " if (r == NULL) return -1;\n";
6400 pr " print_%s_list (r);\n" typ;
6401 pr " guestfs_free_%s_list (r);\n" typ;
6404 pr " if (r == NULL) return -1;\n";
6405 pr " print_table (r);\n";
6406 pr " free_strings (r);\n";
6409 pr " if (r == NULL) return -1;\n";
6410 pr " fwrite (r, size, 1, stdout);\n";
6418 (* run_action function *)
6419 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6422 fun (name, _, _, flags, _, _, _) ->
6423 let name2 = replace_char name '_' '-' in
6425 try find_map (function FishAlias n -> Some n | _ -> None) flags
6426 with Not_found -> name in
6428 pr "strcasecmp (cmd, \"%s\") == 0" name;
6429 if name <> name2 then
6430 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6431 if name <> alias then
6432 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6434 pr " return run_%s (cmd, argc, argv);\n" name;
6438 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6445 (* Readline completion for guestfish. *)
6446 and generate_fish_completion () =
6447 generate_header CStyle GPLv2;
6451 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6461 #ifdef HAVE_LIBREADLINE
6462 #include <readline/readline.h>
6467 #ifdef HAVE_LIBREADLINE
6469 static const char *const commands[] = {
6470 BUILTIN_COMMANDS_FOR_COMPLETION,
6473 (* Get the commands, including the aliases. They don't need to be
6474 * sorted - the generator() function just does a dumb linear search.
6478 fun (name, _, _, flags, _, _, _) ->
6479 let name2 = replace_char name '_' '-' in
6481 try find_map (function FishAlias n -> Some n | _ -> None) flags
6482 with Not_found -> name in
6484 if name <> alias then [name2; alias] else [name2]
6486 let commands = List.flatten commands in
6488 List.iter (pr " \"%s\",\n") commands;
6494 generator (const char *text, int state)
6496 static int index, len;
6501 len = strlen (text);
6504 rl_attempted_completion_over = 1;
6506 while ((name = commands[index]) != NULL) {
6508 if (strncasecmp (name, text, len) == 0)
6509 return strdup (name);
6515 #endif /* HAVE_LIBREADLINE */
6517 char **do_completion (const char *text, int start, int end)
6519 char **matches = NULL;
6521 #ifdef HAVE_LIBREADLINE
6522 rl_completion_append_character = ' ';
6525 matches = rl_completion_matches (text, generator);
6526 else if (complete_dest_paths)
6527 matches = rl_completion_matches (text, complete_dest_paths_generator);
6534 (* Generate the POD documentation for guestfish. *)
6535 and generate_fish_actions_pod () =
6536 let all_functions_sorted =
6538 fun (_, _, _, flags, _, _, _) ->
6539 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6540 ) all_functions_sorted in
6542 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6545 fun (name, style, _, flags, _, _, longdesc) ->
6547 Str.global_substitute rex (
6550 try Str.matched_group 1 s
6552 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6553 "C<" ^ replace_char sub '_' '-' ^ ">"
6555 let name = replace_char name '_' '-' in
6557 try find_map (function FishAlias n -> Some n | _ -> None) flags
6558 with Not_found -> name in
6560 pr "=head2 %s" name;
6561 if name <> alias then
6568 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6569 | OptString n -> pr " %s" n
6570 | StringList n | DeviceList n -> pr " '%s ...'" n
6571 | Bool _ -> pr " true|false"
6572 | Int n -> pr " %s" n
6573 | FileIn n | FileOut n -> pr " (%s|-)" n
6577 pr "%s\n\n" longdesc;
6579 if List.exists (function FileIn _ | FileOut _ -> true
6580 | _ -> false) (snd style) then
6581 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6583 if List.mem ProtocolLimitWarning flags then
6584 pr "%s\n\n" protocol_limit_warning;
6586 if List.mem DangerWillRobinson flags then
6587 pr "%s\n\n" danger_will_robinson;
6589 match deprecation_notice flags with
6591 | Some txt -> pr "%s\n\n" txt
6592 ) all_functions_sorted
6594 (* Generate a C function prototype. *)
6595 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6596 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6598 ?handle name style =
6599 if extern then pr "extern ";
6600 if static then pr "static ";
6601 (match fst style with
6603 | RInt _ -> pr "int "
6604 | RInt64 _ -> pr "int64_t "
6605 | RBool _ -> pr "int "
6606 | RConstString _ | RConstOptString _ -> pr "const char *"
6607 | RString _ | RBufferOut _ -> pr "char *"
6608 | RStringList _ | RHashtable _ -> pr "char **"
6609 | RStruct (_, typ) ->
6610 if not in_daemon then pr "struct guestfs_%s *" typ
6611 else pr "guestfs_int_%s *" typ
6612 | RStructList (_, typ) ->
6613 if not in_daemon then pr "struct guestfs_%s_list *" typ
6614 else pr "guestfs_int_%s_list *" typ
6616 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6617 pr "%s%s (" prefix name;
6618 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6621 let comma = ref false in
6624 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6628 if single_line then pr ", " else pr ",\n\t\t"
6635 | Device n | Dev_or_Path n
6639 pr "const char *%s" n
6640 | StringList n | DeviceList n ->
6642 pr "char *const *%s" n
6643 | Bool n -> next (); pr "int %s" n
6644 | Int n -> next (); pr "int %s" n
6647 if not in_daemon then (next (); pr "const char *%s" n)
6649 if is_RBufferOut then (next (); pr "size_t *size_r");
6652 if semicolon then pr ";";
6653 if newline then pr "\n"
6655 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6656 and generate_c_call_args ?handle ?(decl = false) style =
6658 let comma = ref false in
6660 if !comma then pr ", ";
6665 | Some handle -> pr "%s" handle; comma := true
6670 pr "%s" (name_of_argt arg)
6672 (* For RBufferOut calls, add implicit &size parameter. *)
6674 match fst style with
6682 (* Generate the OCaml bindings interface. *)
6683 and generate_ocaml_mli () =
6684 generate_header OCamlStyle LGPLv2;
6687 (** For API documentation you should refer to the C API
6688 in the guestfs(3) manual page. The OCaml API uses almost
6689 exactly the same calls. *)
6692 (** A [guestfs_h] handle. *)
6694 exception Error of string
6695 (** This exception is raised when there is an error. *)
6697 val create : unit -> t
6699 val close : t -> unit
6700 (** Handles are closed by the garbage collector when they become
6701 unreferenced, but callers can also call this in order to
6702 provide predictable cleanup. *)
6705 generate_ocaml_structure_decls ();
6709 fun (name, style, _, _, _, shortdesc, _) ->
6710 generate_ocaml_prototype name style;
6711 pr "(** %s *)\n" shortdesc;
6715 (* Generate the OCaml bindings implementation. *)
6716 and generate_ocaml_ml () =
6717 generate_header OCamlStyle LGPLv2;
6721 exception Error of string
6722 external create : unit -> t = \"ocaml_guestfs_create\"
6723 external close : t -> unit = \"ocaml_guestfs_close\"
6726 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6730 generate_ocaml_structure_decls ();
6734 fun (name, style, _, _, _, shortdesc, _) ->
6735 generate_ocaml_prototype ~is_external:true name style;
6738 (* Generate the OCaml bindings C implementation. *)
6739 and generate_ocaml_c () =
6740 generate_header CStyle LGPLv2;
6747 #include <caml/config.h>
6748 #include <caml/alloc.h>
6749 #include <caml/callback.h>
6750 #include <caml/fail.h>
6751 #include <caml/memory.h>
6752 #include <caml/mlvalues.h>
6753 #include <caml/signals.h>
6755 #include <guestfs.h>
6757 #include \"guestfs_c.h\"
6759 /* Copy a hashtable of string pairs into an assoc-list. We return
6760 * the list in reverse order, but hashtables aren't supposed to be
6763 static CAMLprim value
6764 copy_table (char * const * argv)
6767 CAMLlocal5 (rv, pairv, kv, vv, cons);
6771 for (i = 0; argv[i] != NULL; i += 2) {
6772 kv = caml_copy_string (argv[i]);
6773 vv = caml_copy_string (argv[i+1]);
6774 pairv = caml_alloc (2, 0);
6775 Store_field (pairv, 0, kv);
6776 Store_field (pairv, 1, vv);
6777 cons = caml_alloc (2, 0);
6778 Store_field (cons, 1, rv);
6780 Store_field (cons, 0, pairv);
6788 (* Struct copy functions. *)
6790 let emit_ocaml_copy_list_function typ =
6791 pr "static CAMLprim value\n";
6792 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6794 pr " CAMLparam0 ();\n";
6795 pr " CAMLlocal2 (rv, v);\n";
6796 pr " unsigned int i;\n";
6798 pr " if (%ss->len == 0)\n" typ;
6799 pr " CAMLreturn (Atom (0));\n";
6801 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
6802 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6803 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
6804 pr " caml_modify (&Field (rv, i), v);\n";
6806 pr " CAMLreturn (rv);\n";
6814 let has_optpercent_col =
6815 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6817 pr "static CAMLprim value\n";
6818 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6820 pr " CAMLparam0 ();\n";
6821 if has_optpercent_col then
6822 pr " CAMLlocal3 (rv, v, v2);\n"
6824 pr " CAMLlocal2 (rv, v);\n";
6826 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
6831 pr " v = caml_copy_string (%s->%s);\n" typ name
6833 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
6834 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6837 pr " v = caml_alloc_string (32);\n";
6838 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
6839 | name, (FBytes|FInt64|FUInt64) ->
6840 pr " v = caml_copy_int64 (%s->%s);\n" typ name
6841 | name, (FInt32|FUInt32) ->
6842 pr " v = caml_copy_int32 (%s->%s);\n" typ name
6843 | name, FOptPercent ->
6844 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6845 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
6846 pr " v = caml_alloc (1, 0);\n";
6847 pr " Store_field (v, 0, v2);\n";
6848 pr " } else /* None */\n";
6849 pr " v = Val_int (0);\n";
6851 pr " v = Val_int (%s->%s);\n" typ name
6853 pr " Store_field (rv, %d, v);\n" i
6855 pr " CAMLreturn (rv);\n";
6860 (* Emit a copy_TYPE_list function definition only if that function is used. *)
6863 | typ, (RStructListOnly | RStructAndList) ->
6864 (* generate the function for typ *)
6865 emit_ocaml_copy_list_function typ
6866 | typ, _ -> () (* empty *)
6871 fun (name, style, _, _, _, _, _) ->
6873 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6875 let needs_extra_vs =
6876 match fst style with RConstOptString _ -> true | _ -> false in
6878 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6879 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6880 List.iter (pr ", value %s") (List.tl params); pr ");\n";
6882 pr "CAMLprim value\n";
6883 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6884 List.iter (pr ", value %s") (List.tl params);
6889 | [p1; p2; p3; p4; p5] ->
6890 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
6891 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6892 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6893 pr " CAMLxparam%d (%s);\n"
6894 (List.length rest) (String.concat ", " rest)
6896 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6898 if not needs_extra_vs then
6899 pr " CAMLlocal1 (rv);\n"
6901 pr " CAMLlocal3 (rv, v, v2);\n";
6904 pr " guestfs_h *g = Guestfs_val (gv);\n";
6905 pr " if (g == NULL)\n";
6906 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
6912 | Device n | Dev_or_Path n
6916 pr " const char *%s = String_val (%sv);\n" n n
6918 pr " const char *%s =\n" n;
6919 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6921 | StringList n | DeviceList n ->
6922 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6924 pr " int %s = Bool_val (%sv);\n" n n
6926 pr " int %s = Int_val (%sv);\n" n n
6929 match fst style with
6930 | RErr -> pr " int r;\n"; "-1"
6931 | RInt _ -> pr " int r;\n"; "-1"
6932 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6933 | RBool _ -> pr " int r;\n"; "-1"
6934 | RConstString _ | RConstOptString _ ->
6935 pr " const char *r;\n"; "NULL"
6936 | RString _ -> pr " char *r;\n"; "NULL"
6941 | RStruct (_, typ) ->
6942 pr " struct guestfs_%s *r;\n" typ; "NULL"
6943 | RStructList (_, typ) ->
6944 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6951 pr " size_t size;\n";
6955 pr " caml_enter_blocking_section ();\n";
6956 pr " r = guestfs_%s " name;
6957 generate_c_call_args ~handle:"g" style;
6959 pr " caml_leave_blocking_section ();\n";
6963 | StringList n | DeviceList n ->
6964 pr " ocaml_guestfs_free_strings (%s);\n" n;
6965 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6966 | FileIn _ | FileOut _ -> ()
6969 pr " if (r == %s)\n" error_code;
6970 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6973 (match fst style with
6974 | RErr -> pr " rv = Val_unit;\n"
6975 | RInt _ -> pr " rv = Val_int (r);\n"
6977 pr " rv = caml_copy_int64 (r);\n"
6978 | RBool _ -> pr " rv = Val_bool (r);\n"
6980 pr " rv = caml_copy_string (r);\n"
6981 | RConstOptString _ ->
6982 pr " if (r) { /* Some string */\n";
6983 pr " v = caml_alloc (1, 0);\n";
6984 pr " v2 = caml_copy_string (r);\n";
6985 pr " Store_field (v, 0, v2);\n";
6986 pr " } else /* None */\n";
6987 pr " v = Val_int (0);\n";
6989 pr " rv = caml_copy_string (r);\n";
6992 pr " rv = caml_copy_string_array ((const char **) r);\n";
6993 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6995 | RStruct (_, typ) ->
6996 pr " rv = copy_%s (r);\n" typ;
6997 pr " guestfs_free_%s (r);\n" typ;
6998 | RStructList (_, typ) ->
6999 pr " rv = copy_%s_list (r);\n" typ;
7000 pr " guestfs_free_%s_list (r);\n" typ;
7002 pr " rv = copy_table (r);\n";
7003 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7006 pr " rv = caml_alloc_string (size);\n";
7007 pr " memcpy (String_val (rv), r, size);\n";
7010 pr " CAMLreturn (rv);\n";
7014 if List.length params > 5 then (
7015 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7016 pr "CAMLprim value ";
7017 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7018 pr "CAMLprim value\n";
7019 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7021 pr " return ocaml_guestfs_%s (argv[0]" name;
7022 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7029 and generate_ocaml_structure_decls () =
7032 pr "type %s = {\n" typ;
7035 | name, FString -> pr " %s : string;\n" name
7036 | name, FBuffer -> pr " %s : string;\n" name
7037 | name, FUUID -> pr " %s : string;\n" name
7038 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
7039 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
7040 | name, FChar -> pr " %s : char;\n" name
7041 | name, FOptPercent -> pr " %s : float option;\n" name
7047 and generate_ocaml_prototype ?(is_external = false) name style =
7048 if is_external then pr "external " else pr "val ";
7049 pr "%s : t -> " name;
7052 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7053 | OptString _ -> pr "string option -> "
7054 | StringList _ | DeviceList _ -> pr "string array -> "
7055 | Bool _ -> pr "bool -> "
7056 | Int _ -> pr "int -> "
7058 (match fst style with
7059 | RErr -> pr "unit" (* all errors are turned into exceptions *)
7060 | RInt _ -> pr "int"
7061 | RInt64 _ -> pr "int64"
7062 | RBool _ -> pr "bool"
7063 | RConstString _ -> pr "string"
7064 | RConstOptString _ -> pr "string option"
7065 | RString _ | RBufferOut _ -> pr "string"
7066 | RStringList _ -> pr "string array"
7067 | RStruct (_, typ) -> pr "%s" typ
7068 | RStructList (_, typ) -> pr "%s array" typ
7069 | RHashtable _ -> pr "(string * string) list"
7071 if is_external then (
7073 if List.length (snd style) + 1 > 5 then
7074 pr "\"ocaml_guestfs_%s_byte\" " name;
7075 pr "\"ocaml_guestfs_%s\"" name
7079 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7080 and generate_perl_xs () =
7081 generate_header CStyle LGPLv2;
7084 #include \"EXTERN.h\"
7088 #include <guestfs.h>
7091 #define PRId64 \"lld\"
7095 my_newSVll(long long val) {
7096 #ifdef USE_64_BIT_ALL
7097 return newSViv(val);
7101 len = snprintf(buf, 100, \"%%\" PRId64, val);
7102 return newSVpv(buf, len);
7107 #define PRIu64 \"llu\"
7111 my_newSVull(unsigned long long val) {
7112 #ifdef USE_64_BIT_ALL
7113 return newSVuv(val);
7117 len = snprintf(buf, 100, \"%%\" PRIu64, val);
7118 return newSVpv(buf, len);
7122 /* http://www.perlmonks.org/?node_id=680842 */
7124 XS_unpack_charPtrPtr (SV *arg) {
7129 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7130 croak (\"array reference expected\");
7132 av = (AV *)SvRV (arg);
7133 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7135 croak (\"malloc failed\");
7137 for (i = 0; i <= av_len (av); i++) {
7138 SV **elem = av_fetch (av, i, 0);
7140 if (!elem || !*elem)
7141 croak (\"missing element in list\");
7143 ret[i] = SvPV_nolen (*elem);
7151 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
7158 RETVAL = guestfs_create ();
7160 croak (\"could not create guestfs handle\");
7161 guestfs_set_error_handler (RETVAL, NULL, NULL);
7174 fun (name, style, _, _, _, _, _) ->
7175 (match fst style with
7176 | RErr -> pr "void\n"
7177 | RInt _ -> pr "SV *\n"
7178 | RInt64 _ -> pr "SV *\n"
7179 | RBool _ -> pr "SV *\n"
7180 | RConstString _ -> pr "SV *\n"
7181 | RConstOptString _ -> pr "SV *\n"
7182 | RString _ -> pr "SV *\n"
7183 | RBufferOut _ -> pr "SV *\n"
7185 | RStruct _ | RStructList _
7187 pr "void\n" (* all lists returned implictly on the stack *)
7189 (* Call and arguments. *)
7191 generate_c_call_args ~handle:"g" ~decl:true style;
7193 pr " guestfs_h *g;\n";
7197 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7200 (* http://www.perlmonks.org/?node_id=554277
7201 * Note that the implicit handle argument means we have
7202 * to add 1 to the ST(x) operator.
7204 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7205 | StringList n | DeviceList n -> pr " char **%s;\n" n
7206 | Bool n -> pr " int %s;\n" n
7207 | Int n -> pr " int %s;\n" n
7210 let do_cleanups () =
7213 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7214 | FileIn _ | FileOut _ -> ()
7215 | StringList n | DeviceList n -> pr " free (%s);\n" n
7220 (match fst style with
7225 pr " r = guestfs_%s " name;
7226 generate_c_call_args ~handle:"g" style;
7229 pr " if (r == -1)\n";
7230 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7236 pr " %s = guestfs_%s " n name;
7237 generate_c_call_args ~handle:"g" style;
7240 pr " if (%s == -1)\n" n;
7241 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7242 pr " RETVAL = newSViv (%s);\n" n;
7247 pr " int64_t %s;\n" n;
7249 pr " %s = guestfs_%s " n name;
7250 generate_c_call_args ~handle:"g" style;
7253 pr " if (%s == -1)\n" n;
7254 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7255 pr " RETVAL = my_newSVll (%s);\n" n;
7260 pr " const char *%s;\n" n;
7262 pr " %s = guestfs_%s " n name;
7263 generate_c_call_args ~handle:"g" style;
7266 pr " if (%s == NULL)\n" n;
7267 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7268 pr " RETVAL = newSVpv (%s, 0);\n" n;
7271 | RConstOptString n ->
7273 pr " const char *%s;\n" n;
7275 pr " %s = guestfs_%s " n name;
7276 generate_c_call_args ~handle:"g" style;
7279 pr " if (%s == NULL)\n" n;
7280 pr " RETVAL = &PL_sv_undef;\n";
7282 pr " RETVAL = newSVpv (%s, 0);\n" n;
7287 pr " char *%s;\n" 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 " RETVAL = newSVpv (%s, 0);\n" n;
7296 pr " free (%s);\n" n;
7299 | RStringList n | RHashtable n ->
7301 pr " char **%s;\n" n;
7304 pr " %s = guestfs_%s " n name;
7305 generate_c_call_args ~handle:"g" style;
7308 pr " if (%s == NULL)\n" n;
7309 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7310 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7311 pr " EXTEND (SP, n);\n";
7312 pr " for (i = 0; i < n; ++i) {\n";
7313 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7314 pr " free (%s[i]);\n" n;
7316 pr " free (%s);\n" n;
7317 | RStruct (n, typ) ->
7318 let cols = cols_of_struct typ in
7319 generate_perl_struct_code typ cols name style n do_cleanups
7320 | RStructList (n, typ) ->
7321 let cols = cols_of_struct typ in
7322 generate_perl_struct_list_code typ cols name style n do_cleanups
7325 pr " char *%s;\n" n;
7326 pr " size_t size;\n";
7328 pr " %s = guestfs_%s " n name;
7329 generate_c_call_args ~handle:"g" style;
7332 pr " if (%s == NULL)\n" n;
7333 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7334 pr " RETVAL = newSVpv (%s, size);\n" n;
7335 pr " free (%s);\n" n;
7343 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7345 pr " struct guestfs_%s_list *%s;\n" typ n;
7349 pr " %s = guestfs_%s " n name;
7350 generate_c_call_args ~handle:"g" style;
7353 pr " if (%s == NULL)\n" n;
7354 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7355 pr " EXTEND (SP, %s->len);\n" n;
7356 pr " for (i = 0; i < %s->len; ++i) {\n" n;
7357 pr " hv = newHV ();\n";
7361 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7362 name (String.length name) n name
7364 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7365 name (String.length name) n name
7367 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7368 name (String.length name) n name n name
7369 | name, (FBytes|FUInt64) ->
7370 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7371 name (String.length name) n name
7373 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7374 name (String.length name) n name
7375 | name, (FInt32|FUInt32) ->
7376 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7377 name (String.length name) n name
7379 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7380 name (String.length name) n name
7381 | name, FOptPercent ->
7382 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7383 name (String.length name) n name
7385 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7387 pr " guestfs_free_%s_list (%s);\n" typ n
7389 and generate_perl_struct_code typ cols name style n do_cleanups =
7391 pr " struct guestfs_%s *%s;\n" typ n;
7393 pr " %s = guestfs_%s " n name;
7394 generate_c_call_args ~handle:"g" style;
7397 pr " if (%s == NULL)\n" n;
7398 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7399 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7401 fun ((name, _) as col) ->
7402 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7406 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7409 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7412 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7414 | name, (FBytes|FUInt64) ->
7415 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7418 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7420 | name, (FInt32|FUInt32) ->
7421 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7424 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7426 | name, FOptPercent ->
7427 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7430 pr " free (%s);\n" n
7432 (* Generate Sys/Guestfs.pm. *)
7433 and generate_perl_pm () =
7434 generate_header HashStyle LGPLv2;
7441 Sys::Guestfs - Perl bindings for libguestfs
7447 my $h = Sys::Guestfs->new ();
7448 $h->add_drive ('guest.img');
7450 $h->mount ('/dev/sda1', '/');
7451 $h->touch ('/hello');
7456 The C<Sys::Guestfs> module provides a Perl XS binding to the
7457 libguestfs API for examining and modifying virtual machine
7460 Amongst the things this is good for: making batch configuration
7461 changes to guests, getting disk used/free statistics (see also:
7462 virt-df), migrating between virtualization systems (see also:
7463 virt-p2v), performing partial backups, performing partial guest
7464 clones, cloning guests and changing registry/UUID/hostname info, and
7467 Libguestfs uses Linux kernel and qemu code, and can access any type of
7468 guest filesystem that Linux and qemu can, including but not limited
7469 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7470 schemes, qcow, qcow2, vmdk.
7472 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7473 LVs, what filesystem is in each LV, etc.). It can also run commands
7474 in the context of the guest. Also you can access filesystems over FTP.
7476 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7477 functions for using libguestfs from Perl, including integration
7482 All errors turn into calls to C<croak> (see L<Carp(3)>).
7490 package Sys::Guestfs;
7496 XSLoader::load ('Sys::Guestfs');
7498 =item $h = Sys::Guestfs->new ();
7500 Create a new guestfs handle.
7506 my $class = ref ($proto) || $proto;
7508 my $self = Sys::Guestfs::_create ();
7509 bless $self, $class;
7515 (* Actions. We only need to print documentation for these as
7516 * they are pulled in from the XS code automatically.
7519 fun (name, style, _, flags, _, _, longdesc) ->
7520 if not (List.mem NotInDocs flags) then (
7521 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7523 generate_perl_prototype name style;
7525 pr "%s\n\n" longdesc;
7526 if List.mem ProtocolLimitWarning flags then
7527 pr "%s\n\n" protocol_limit_warning;
7528 if List.mem DangerWillRobinson flags then
7529 pr "%s\n\n" danger_will_robinson;
7530 match deprecation_notice flags with
7532 | Some txt -> pr "%s\n\n" txt
7534 ) all_functions_sorted;
7546 Copyright (C) 2009 Red Hat Inc.
7550 Please see the file COPYING.LIB for the full license.
7556 L<http://libguestfs.org>,
7557 L<Sys::Guestfs::Lib(3)>.
7562 and generate_perl_prototype name style =
7563 (match fst style with
7571 | RBufferOut n -> pr "$%s = " n
7573 | RHashtable n -> pr "%%%s = " n
7575 | RStructList (n,_) -> pr "@%s = " n
7578 let comma = ref false in
7581 if !comma then pr ", ";
7584 | Pathname n | Device n | Dev_or_Path n | String n
7585 | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7587 | StringList n | DeviceList n ->
7592 (* Generate Python C module. *)
7593 and generate_python_c () =
7594 generate_header CStyle LGPLv2;
7603 #include \"guestfs.h\"
7611 get_handle (PyObject *obj)
7614 assert (obj != Py_None);
7615 return ((Pyguestfs_Object *) obj)->g;
7619 put_handle (guestfs_h *g)
7623 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7626 /* This list should be freed (but not the strings) after use. */
7628 get_string_list (PyObject *obj)
7635 if (!PyList_Check (obj)) {
7636 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7640 len = PyList_Size (obj);
7641 r = malloc (sizeof (char *) * (len+1));
7643 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7647 for (i = 0; i < len; ++i)
7648 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7655 put_string_list (char * const * const argv)
7660 for (argc = 0; argv[argc] != NULL; ++argc)
7663 list = PyList_New (argc);
7664 for (i = 0; i < argc; ++i)
7665 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7671 put_table (char * const * const argv)
7673 PyObject *list, *item;
7676 for (argc = 0; argv[argc] != NULL; ++argc)
7679 list = PyList_New (argc >> 1);
7680 for (i = 0; i < argc; i += 2) {
7681 item = PyTuple_New (2);
7682 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7683 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7684 PyList_SetItem (list, i >> 1, item);
7691 free_strings (char **argv)
7695 for (argc = 0; argv[argc] != NULL; ++argc)
7701 py_guestfs_create (PyObject *self, PyObject *args)
7705 g = guestfs_create ();
7707 PyErr_SetString (PyExc_RuntimeError,
7708 \"guestfs.create: failed to allocate handle\");
7711 guestfs_set_error_handler (g, NULL, NULL);
7712 return put_handle (g);
7716 py_guestfs_close (PyObject *self, PyObject *args)
7721 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7723 g = get_handle (py_g);
7727 Py_INCREF (Py_None);
7733 let emit_put_list_function typ =
7734 pr "static PyObject *\n";
7735 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7737 pr " PyObject *list;\n";
7740 pr " list = PyList_New (%ss->len);\n" typ;
7741 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7742 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7743 pr " return list;\n";
7748 (* Structures, turned into Python dictionaries. *)
7751 pr "static PyObject *\n";
7752 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7754 pr " PyObject *dict;\n";
7756 pr " dict = PyDict_New ();\n";
7760 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7761 pr " PyString_FromString (%s->%s));\n"
7764 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7765 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7768 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7769 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
7771 | name, (FBytes|FUInt64) ->
7772 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7773 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
7776 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7777 pr " PyLong_FromLongLong (%s->%s));\n"
7780 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7781 pr " PyLong_FromUnsignedLong (%s->%s));\n"
7784 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7785 pr " PyLong_FromLong (%s->%s));\n"
7787 | name, FOptPercent ->
7788 pr " if (%s->%s >= 0)\n" typ name;
7789 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7790 pr " PyFloat_FromDouble ((double) %s->%s));\n"
7793 pr " Py_INCREF (Py_None);\n";
7794 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7797 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7798 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7800 pr " return dict;\n";
7806 (* Emit a put_TYPE_list function definition only if that function is used. *)
7809 | typ, (RStructListOnly | RStructAndList) ->
7810 (* generate the function for typ *)
7811 emit_put_list_function typ
7812 | typ, _ -> () (* empty *)
7815 (* Python wrapper functions. *)
7817 fun (name, style, _, _, _, _, _) ->
7818 pr "static PyObject *\n";
7819 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7822 pr " PyObject *py_g;\n";
7823 pr " guestfs_h *g;\n";
7824 pr " PyObject *py_r;\n";
7827 match fst style with
7828 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7829 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7830 | RConstString _ | RConstOptString _ ->
7831 pr " const char *r;\n"; "NULL"
7832 | RString _ -> pr " char *r;\n"; "NULL"
7833 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7834 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7835 | RStructList (_, typ) ->
7836 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7839 pr " size_t size;\n";
7844 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7845 pr " const char *%s;\n" n
7846 | OptString n -> pr " const char *%s;\n" n
7847 | StringList n | DeviceList n ->
7848 pr " PyObject *py_%s;\n" n;
7849 pr " char **%s;\n" n
7850 | Bool n -> pr " int %s;\n" n
7851 | Int n -> pr " int %s;\n" n
7856 (* Convert the parameters. *)
7857 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
7860 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7861 | OptString _ -> pr "z"
7862 | StringList _ | DeviceList _ -> pr "O"
7863 | Bool _ -> pr "i" (* XXX Python has booleans? *)
7866 pr ":guestfs_%s\",\n" name;
7870 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7871 | OptString n -> pr ", &%s" n
7872 | StringList n | DeviceList n -> pr ", &py_%s" n
7873 | Bool n -> pr ", &%s" n
7874 | Int n -> pr ", &%s" n
7878 pr " return NULL;\n";
7880 pr " g = get_handle (py_g);\n";
7883 | Pathname _ | Device _ | Dev_or_Path _ | String _
7884 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7885 | StringList n | DeviceList n ->
7886 pr " %s = get_string_list (py_%s);\n" n n;
7887 pr " if (!%s) return NULL;\n" n
7892 pr " r = guestfs_%s " name;
7893 generate_c_call_args ~handle:"g" style;
7898 | Pathname _ | Device _ | Dev_or_Path _ | String _
7899 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7900 | StringList n | DeviceList n ->
7901 pr " free (%s);\n" n
7904 pr " if (r == %s) {\n" error_code;
7905 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7906 pr " return NULL;\n";
7910 (match fst style with
7912 pr " Py_INCREF (Py_None);\n";
7913 pr " py_r = Py_None;\n"
7915 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
7916 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
7917 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
7918 | RConstOptString _ ->
7920 pr " py_r = PyString_FromString (r);\n";
7922 pr " Py_INCREF (Py_None);\n";
7923 pr " py_r = Py_None;\n";
7926 pr " py_r = PyString_FromString (r);\n";
7929 pr " py_r = put_string_list (r);\n";
7930 pr " free_strings (r);\n"
7931 | RStruct (_, typ) ->
7932 pr " py_r = put_%s (r);\n" typ;
7933 pr " guestfs_free_%s (r);\n" typ
7934 | RStructList (_, typ) ->
7935 pr " py_r = put_%s_list (r);\n" typ;
7936 pr " guestfs_free_%s_list (r);\n" typ
7938 pr " py_r = put_table (r);\n";
7939 pr " free_strings (r);\n"
7941 pr " py_r = PyString_FromStringAndSize (r, size);\n";
7945 pr " return py_r;\n";
7950 (* Table of functions. *)
7951 pr "static PyMethodDef methods[] = {\n";
7952 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7953 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7955 fun (name, _, _, _, _, _, _) ->
7956 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7959 pr " { NULL, NULL, 0, NULL }\n";
7963 (* Init function. *)
7966 initlibguestfsmod (void)
7968 static int initialized = 0;
7970 if (initialized) return;
7971 Py_InitModule ((char *) \"libguestfsmod\", methods);
7976 (* Generate Python module. *)
7977 and generate_python_py () =
7978 generate_header HashStyle LGPLv2;
7981 u\"\"\"Python bindings for libguestfs
7984 g = guestfs.GuestFS ()
7985 g.add_drive (\"guest.img\")
7987 parts = g.list_partitions ()
7989 The guestfs module provides a Python binding to the libguestfs API
7990 for examining and modifying virtual machine disk images.
7992 Amongst the things this is good for: making batch configuration
7993 changes to guests, getting disk used/free statistics (see also:
7994 virt-df), migrating between virtualization systems (see also:
7995 virt-p2v), performing partial backups, performing partial guest
7996 clones, cloning guests and changing registry/UUID/hostname info, and
7999 Libguestfs uses Linux kernel and qemu code, and can access any type of
8000 guest filesystem that Linux and qemu can, including but not limited
8001 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8002 schemes, qcow, qcow2, vmdk.
8004 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8005 LVs, what filesystem is in each LV, etc.). It can also run commands
8006 in the context of the guest. Also you can access filesystems over FTP.
8008 Errors which happen while using the API are turned into Python
8009 RuntimeError exceptions.
8011 To create a guestfs handle you usually have to perform the following
8014 # Create the handle, call add_drive at least once, and possibly
8015 # several times if the guest has multiple block devices:
8016 g = guestfs.GuestFS ()
8017 g.add_drive (\"guest.img\")
8019 # Launch the qemu subprocess and wait for it to become ready:
8022 # Now you can issue commands, for example:
8027 import libguestfsmod
8030 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8032 def __init__ (self):
8033 \"\"\"Create a new libguestfs handle.\"\"\"
8034 self._o = libguestfsmod.create ()
8037 libguestfsmod.close (self._o)
8042 fun (name, style, _, flags, _, _, longdesc) ->
8044 generate_py_call_args ~handle:"self" (snd style);
8047 if not (List.mem NotInDocs flags) then (
8048 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8050 match fst style with
8051 | RErr | RInt _ | RInt64 _ | RBool _
8052 | RConstOptString _ | RConstString _
8053 | RString _ | RBufferOut _ -> doc
8055 doc ^ "\n\nThis function returns a list of strings."
8056 | RStruct (_, typ) ->
8057 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8058 | RStructList (_, typ) ->
8059 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
8061 doc ^ "\n\nThis function returns a dictionary." in
8063 if List.mem ProtocolLimitWarning flags then
8064 doc ^ "\n\n" ^ protocol_limit_warning
8067 if List.mem DangerWillRobinson flags then
8068 doc ^ "\n\n" ^ danger_will_robinson
8071 match deprecation_notice flags with
8073 | Some txt -> doc ^ "\n\n" ^ txt in
8074 let doc = pod2text ~width:60 name doc in
8075 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8076 let doc = String.concat "\n " doc in
8077 pr " u\"\"\"%s\"\"\"\n" doc;
8079 pr " return libguestfsmod.%s " name;
8080 generate_py_call_args ~handle:"self._o" (snd style);
8085 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8086 and generate_py_call_args ~handle args =
8088 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8091 (* Useful if you need the longdesc POD text as plain text. Returns a
8094 * Because this is very slow (the slowest part of autogeneration),
8095 * we memoize the results.
8097 and pod2text ~width name longdesc =
8098 let key = width, name, longdesc in
8099 try Hashtbl.find pod2text_memo key
8101 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8102 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8104 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8105 let chan = Unix.open_process_in cmd in
8106 let lines = ref [] in
8108 let line = input_line chan in
8109 if i = 1 then (* discard the first line of output *)
8112 let line = triml line in
8113 lines := line :: !lines;
8116 let lines = try loop 1 with End_of_file -> List.rev !lines in
8117 Unix.unlink filename;
8118 (match Unix.close_process_in chan with
8119 | Unix.WEXITED 0 -> ()
8121 failwithf "pod2text: process exited with non-zero status (%d)" i
8122 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8123 failwithf "pod2text: process signalled or stopped by signal %d" i
8125 Hashtbl.add pod2text_memo key lines;
8126 pod2text_memo_updated ();
8129 (* Generate ruby bindings. *)
8130 and generate_ruby_c () =
8131 generate_header CStyle LGPLv2;
8139 #include \"guestfs.h\"
8141 #include \"extconf.h\"
8143 /* For Ruby < 1.9 */
8145 #define RARRAY_LEN(r) (RARRAY((r))->len)
8148 static VALUE m_guestfs; /* guestfs module */
8149 static VALUE c_guestfs; /* guestfs_h handle */
8150 static VALUE e_Error; /* used for all errors */
8152 static void ruby_guestfs_free (void *p)
8155 guestfs_close ((guestfs_h *) p);
8158 static VALUE ruby_guestfs_create (VALUE m)
8162 g = guestfs_create ();
8164 rb_raise (e_Error, \"failed to create guestfs handle\");
8166 /* Don't print error messages to stderr by default. */
8167 guestfs_set_error_handler (g, NULL, NULL);
8169 /* Wrap it, and make sure the close function is called when the
8172 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8175 static VALUE ruby_guestfs_close (VALUE gv)
8178 Data_Get_Struct (gv, guestfs_h, g);
8180 ruby_guestfs_free (g);
8181 DATA_PTR (gv) = NULL;
8189 fun (name, style, _, _, _, _, _) ->
8190 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8191 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8194 pr " guestfs_h *g;\n";
8195 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
8197 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8203 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8204 pr " Check_Type (%sv, T_STRING);\n" n;
8205 pr " const char *%s = StringValueCStr (%sv);\n" n n;
8207 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8208 pr " \"%s\", \"%s\");\n" n name
8210 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8211 | StringList n | DeviceList n ->
8212 pr " char **%s;\n" n;
8213 pr " Check_Type (%sv, T_ARRAY);\n" n;
8215 pr " int i, len;\n";
8216 pr " len = RARRAY_LEN (%sv);\n" n;
8217 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8219 pr " for (i = 0; i < len; ++i) {\n";
8220 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
8221 pr " %s[i] = StringValueCStr (v);\n" n;
8223 pr " %s[len] = NULL;\n" n;
8226 pr " int %s = RTEST (%sv);\n" n n
8228 pr " int %s = NUM2INT (%sv);\n" n n
8233 match fst style with
8234 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8235 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8236 | RConstString _ | RConstOptString _ ->
8237 pr " const char *r;\n"; "NULL"
8238 | RString _ -> pr " char *r;\n"; "NULL"
8239 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8240 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8241 | RStructList (_, typ) ->
8242 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8245 pr " size_t size;\n";
8249 pr " r = guestfs_%s " name;
8250 generate_c_call_args ~handle:"g" style;
8255 | Pathname _ | Device _ | Dev_or_Path _ | String _
8256 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8257 | StringList n | DeviceList n ->
8258 pr " free (%s);\n" n
8261 pr " if (r == %s)\n" error_code;
8262 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8265 (match fst style with
8267 pr " return Qnil;\n"
8268 | RInt _ | RBool _ ->
8269 pr " return INT2NUM (r);\n"
8271 pr " return ULL2NUM (r);\n"
8273 pr " return rb_str_new2 (r);\n";
8274 | RConstOptString _ ->
8276 pr " return rb_str_new2 (r);\n";
8278 pr " return Qnil;\n";
8280 pr " VALUE rv = rb_str_new2 (r);\n";
8284 pr " int i, len = 0;\n";
8285 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
8286 pr " VALUE rv = rb_ary_new2 (len);\n";
8287 pr " for (i = 0; r[i] != NULL; ++i) {\n";
8288 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8289 pr " free (r[i]);\n";
8293 | RStruct (_, typ) ->
8294 let cols = cols_of_struct typ in
8295 generate_ruby_struct_code typ cols
8296 | RStructList (_, typ) ->
8297 let cols = cols_of_struct typ in
8298 generate_ruby_struct_list_code typ cols
8300 pr " VALUE rv = rb_hash_new ();\n";
8302 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
8303 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8304 pr " free (r[i]);\n";
8305 pr " free (r[i+1]);\n";
8310 pr " VALUE rv = rb_str_new (r, size);\n";
8320 /* Initialize the module. */
8321 void Init__guestfs ()
8323 m_guestfs = rb_define_module (\"Guestfs\");
8324 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8325 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8327 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8328 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8331 (* Define the rest of the methods. *)
8333 fun (name, style, _, _, _, _, _) ->
8334 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
8335 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8340 (* Ruby code to return a struct. *)
8341 and generate_ruby_struct_code typ cols =
8342 pr " VALUE rv = rb_hash_new ();\n";
8346 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8348 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8350 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8351 | name, (FBytes|FUInt64) ->
8352 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8354 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8356 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8358 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8359 | name, FOptPercent ->
8360 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8361 | name, FChar -> (* XXX wrong? *)
8362 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8364 pr " guestfs_free_%s (r);\n" typ;
8367 (* Ruby code to return a struct list. *)
8368 and generate_ruby_struct_list_code typ cols =
8369 pr " VALUE rv = rb_ary_new2 (r->len);\n";
8371 pr " for (i = 0; i < r->len; ++i) {\n";
8372 pr " VALUE hv = rb_hash_new ();\n";
8376 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8378 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
8380 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8381 | name, (FBytes|FUInt64) ->
8382 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8384 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8386 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8388 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8389 | name, FOptPercent ->
8390 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8391 | name, FChar -> (* XXX wrong? *)
8392 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8394 pr " rb_ary_push (rv, hv);\n";
8396 pr " guestfs_free_%s_list (r);\n" typ;
8399 (* Generate Java bindings GuestFS.java file. *)
8400 and generate_java_java () =
8401 generate_header CStyle LGPLv2;
8404 package com.redhat.et.libguestfs;
8406 import java.util.HashMap;
8407 import com.redhat.et.libguestfs.LibGuestFSException;
8408 import com.redhat.et.libguestfs.PV;
8409 import com.redhat.et.libguestfs.VG;
8410 import com.redhat.et.libguestfs.LV;
8411 import com.redhat.et.libguestfs.Stat;
8412 import com.redhat.et.libguestfs.StatVFS;
8413 import com.redhat.et.libguestfs.IntBool;
8414 import com.redhat.et.libguestfs.Dirent;
8417 * The GuestFS object is a libguestfs handle.
8421 public class GuestFS {
8422 // Load the native code.
8424 System.loadLibrary (\"guestfs_jni\");
8428 * The native guestfs_h pointer.
8433 * Create a libguestfs handle.
8435 * @throws LibGuestFSException
8437 public GuestFS () throws LibGuestFSException
8441 private native long _create () throws LibGuestFSException;
8444 * Close a libguestfs handle.
8446 * You can also leave handles to be collected by the garbage
8447 * collector, but this method ensures that the resources used
8448 * by the handle are freed up immediately. If you call any
8449 * other methods after closing the handle, you will get an
8452 * @throws LibGuestFSException
8454 public void close () throws LibGuestFSException
8460 private native void _close (long g) throws LibGuestFSException;
8462 public void finalize () throws LibGuestFSException
8470 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8471 if not (List.mem NotInDocs flags); then (
8472 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8474 if List.mem ProtocolLimitWarning flags then
8475 doc ^ "\n\n" ^ protocol_limit_warning
8478 if List.mem DangerWillRobinson flags then
8479 doc ^ "\n\n" ^ danger_will_robinson
8482 match deprecation_notice flags with
8484 | Some txt -> doc ^ "\n\n" ^ txt in
8485 let doc = pod2text ~width:60 name doc in
8486 let doc = List.map ( (* RHBZ#501883 *)
8489 | nonempty -> nonempty
8491 let doc = String.concat "\n * " doc in
8494 pr " * %s\n" shortdesc;
8497 pr " * @throws LibGuestFSException\n";
8501 generate_java_prototype ~public:true ~semicolon:false name style;
8504 pr " if (g == 0)\n";
8505 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8508 if fst style <> RErr then pr "return ";
8510 generate_java_call_args ~handle:"g" (snd style);
8514 generate_java_prototype ~privat:true ~native:true name style;
8521 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8522 and generate_java_call_args ~handle args =
8524 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8527 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8528 ?(semicolon=true) name style =
8529 if privat then pr "private ";
8530 if public then pr "public ";
8531 if native then pr "native ";
8534 (match fst style with
8535 | RErr -> pr "void ";
8536 | RInt _ -> pr "int ";
8537 | RInt64 _ -> pr "long ";
8538 | RBool _ -> pr "boolean ";
8539 | RConstString _ | RConstOptString _ | RString _
8540 | RBufferOut _ -> pr "String ";
8541 | RStringList _ -> pr "String[] ";
8542 | RStruct (_, typ) ->
8543 let name = java_name_of_struct typ in
8545 | RStructList (_, typ) ->
8546 let name = java_name_of_struct typ in
8548 | RHashtable _ -> pr "HashMap<String,String> ";
8551 if native then pr "_%s " name else pr "%s " name;
8553 let needs_comma = ref false in
8562 if !needs_comma then pr ", ";
8563 needs_comma := true;
8567 | Device n | Dev_or_Path n
8573 | StringList n | DeviceList n ->
8582 pr " throws LibGuestFSException";
8583 if semicolon then pr ";"
8585 and generate_java_struct jtyp cols =
8586 generate_header CStyle LGPLv2;
8589 package com.redhat.et.libguestfs;
8592 * Libguestfs %s structure.
8604 | name, FBuffer -> pr " public String %s;\n" name
8605 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8606 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8607 | name, FChar -> pr " public char %s;\n" name
8608 | name, FOptPercent ->
8609 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8610 pr " public float %s;\n" name
8615 and generate_java_c () =
8616 generate_header CStyle LGPLv2;
8623 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8624 #include \"guestfs.h\"
8626 /* Note that this function returns. The exception is not thrown
8627 * until after the wrapper function returns.
8630 throw_exception (JNIEnv *env, const char *msg)
8633 cl = (*env)->FindClass (env,
8634 \"com/redhat/et/libguestfs/LibGuestFSException\");
8635 (*env)->ThrowNew (env, cl, msg);
8638 JNIEXPORT jlong JNICALL
8639 Java_com_redhat_et_libguestfs_GuestFS__1create
8640 (JNIEnv *env, jobject obj)
8644 g = guestfs_create ();
8646 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8649 guestfs_set_error_handler (g, NULL, NULL);
8650 return (jlong) (long) g;
8653 JNIEXPORT void JNICALL
8654 Java_com_redhat_et_libguestfs_GuestFS__1close
8655 (JNIEnv *env, jobject obj, jlong jg)
8657 guestfs_h *g = (guestfs_h *) (long) jg;
8664 fun (name, style, _, _, _, _, _) ->
8666 (match fst style with
8667 | RErr -> pr "void ";
8668 | RInt _ -> pr "jint ";
8669 | RInt64 _ -> pr "jlong ";
8670 | RBool _ -> pr "jboolean ";
8671 | RConstString _ | RConstOptString _ | RString _
8672 | RBufferOut _ -> pr "jstring ";
8673 | RStruct _ | RHashtable _ ->
8675 | RStringList _ | RStructList _ ->
8679 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8680 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8682 pr " (JNIEnv *env, jobject obj, jlong jg";
8686 | Device n | Dev_or_Path n
8691 pr ", jstring j%s" n
8692 | StringList n | DeviceList n ->
8693 pr ", jobjectArray j%s" n
8695 pr ", jboolean j%s" n
8701 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8702 let error_code, no_ret =
8703 match fst style with
8704 | RErr -> pr " int r;\n"; "-1", ""
8706 | RInt _ -> pr " int r;\n"; "-1", "0"
8707 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8708 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8709 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8711 pr " jstring jr;\n";
8712 pr " char *r;\n"; "NULL", "NULL"
8714 pr " jobjectArray jr;\n";
8717 pr " jstring jstr;\n";
8718 pr " char **r;\n"; "NULL", "NULL"
8719 | RStruct (_, typ) ->
8720 pr " jobject jr;\n";
8722 pr " jfieldID fl;\n";
8723 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8724 | RStructList (_, typ) ->
8725 pr " jobjectArray jr;\n";
8727 pr " jfieldID fl;\n";
8728 pr " jobject jfl;\n";
8729 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8730 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8732 pr " jstring jr;\n";
8734 pr " size_t size;\n";
8739 | Device n | Dev_or_Path n
8744 pr " const char *%s;\n" n
8745 | StringList n | DeviceList n ->
8746 pr " int %s_len;\n" n;
8747 pr " const char **%s;\n" n
8754 (match fst style with
8755 | RStringList _ | RStructList _ -> true
8756 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8758 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8759 List.exists (function
8760 | StringList _ -> true
8761 | DeviceList _ -> true
8762 | _ -> false) (snd style) in
8768 (* Get the parameters. *)
8772 | Device n | Dev_or_Path n
8776 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8778 (* This is completely undocumented, but Java null becomes
8781 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8782 | StringList n | DeviceList n ->
8783 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8784 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8785 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8786 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8788 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8790 pr " %s[%s_len] = NULL;\n" n n;
8793 pr " %s = j%s;\n" n n
8796 (* Make the call. *)
8797 pr " r = guestfs_%s " name;
8798 generate_c_call_args ~handle:"g" style;
8801 (* Release the parameters. *)
8805 | Device n | Dev_or_Path n
8809 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8812 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8813 | StringList n | DeviceList n ->
8814 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8815 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8817 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8819 pr " free (%s);\n" n
8824 (* Check for errors. *)
8825 pr " if (r == %s) {\n" error_code;
8826 pr " throw_exception (env, guestfs_last_error (g));\n";
8827 pr " return %s;\n" no_ret;
8831 (match fst style with
8833 | RInt _ -> pr " return (jint) r;\n"
8834 | RBool _ -> pr " return (jboolean) r;\n"
8835 | RInt64 _ -> pr " return (jlong) r;\n"
8836 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
8837 | RConstOptString _ ->
8838 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8840 pr " jr = (*env)->NewStringUTF (env, r);\n";
8844 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8845 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8846 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
8847 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8848 pr " for (i = 0; i < r_len; ++i) {\n";
8849 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
8850 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8851 pr " free (r[i]);\n";
8855 | RStruct (_, typ) ->
8856 let jtyp = java_name_of_struct typ in
8857 let cols = cols_of_struct typ in
8858 generate_java_struct_return typ jtyp cols
8859 | RStructList (_, typ) ->
8860 let jtyp = java_name_of_struct typ in
8861 let cols = cols_of_struct typ in
8862 generate_java_struct_list_return typ jtyp cols
8865 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8866 pr " return NULL;\n"
8868 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8877 and generate_java_struct_return typ jtyp cols =
8878 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8879 pr " jr = (*env)->AllocObject (env, cl);\n";
8883 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8884 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8887 pr " char s[33];\n";
8888 pr " memcpy (s, r->%s, 32);\n" name;
8890 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8891 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8895 pr " int len = r->%s_len;\n" name;
8896 pr " char s[len+1];\n";
8897 pr " memcpy (s, r->%s, len);\n" name;
8898 pr " s[len] = 0;\n";
8899 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8900 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8902 | name, (FBytes|FUInt64|FInt64) ->
8903 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8904 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8905 | name, (FUInt32|FInt32) ->
8906 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8907 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8908 | name, FOptPercent ->
8909 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8910 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8912 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8913 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8918 and generate_java_struct_list_return typ jtyp cols =
8919 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8920 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8921 pr " for (i = 0; i < r->len; ++i) {\n";
8922 pr " jfl = (*env)->AllocObject (env, cl);\n";
8926 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8927 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8930 pr " char s[33];\n";
8931 pr " memcpy (s, r->val[i].%s, 32);\n" name;
8933 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8934 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8938 pr " int len = r->val[i].%s_len;\n" name;
8939 pr " char s[len+1];\n";
8940 pr " memcpy (s, r->val[i].%s, len);\n" name;
8941 pr " s[len] = 0;\n";
8942 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8943 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8945 | name, (FBytes|FUInt64|FInt64) ->
8946 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8947 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8948 | name, (FUInt32|FInt32) ->
8949 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8950 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8951 | name, FOptPercent ->
8952 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8953 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8955 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8956 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8958 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8960 pr " guestfs_free_%s_list (r);\n" typ;
8963 and generate_java_makefile_inc () =
8964 generate_header HashStyle GPLv2;
8966 pr "java_built_sources = \\\n";
8969 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8971 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8973 and generate_haskell_hs () =
8974 generate_header HaskellStyle LGPLv2;
8976 (* XXX We only know how to generate partial FFI for Haskell
8977 * at the moment. Please help out!
8979 let can_generate style =
8983 | RInt64 _, _ -> true
8986 | RConstOptString _, _
8992 | RBufferOut _, _ -> false in
8995 {-# INCLUDE <guestfs.h> #-}
8996 {-# LANGUAGE ForeignFunctionInterface #-}
9001 (* List out the names of the actions we want to export. *)
9003 fun (name, style, _, _, _, _, _) ->
9004 if can_generate style then pr ",\n %s" name
9011 import Foreign.C.Types
9013 import Control.Exception
9014 import Data.Typeable
9016 data GuestfsS = GuestfsS -- represents the opaque C struct
9017 type GuestfsP = Ptr GuestfsS -- guestfs_h *
9018 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9020 -- XXX define properly later XXX
9024 data IntBool = IntBool
9026 data StatVFS = StatVFS
9027 data Hashtable = Hashtable
9029 foreign import ccall unsafe \"guestfs_create\" c_create
9031 foreign import ccall unsafe \"&guestfs_close\" c_close
9032 :: FunPtr (GuestfsP -> IO ())
9033 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9034 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9036 create :: IO GuestfsH
9039 c_set_error_handler p nullPtr nullPtr
9040 h <- newForeignPtr c_close p
9043 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9044 :: GuestfsP -> IO CString
9046 -- last_error :: GuestfsH -> IO (Maybe String)
9047 -- last_error h = do
9048 -- str <- withForeignPtr h (\\p -> c_last_error p)
9049 -- maybePeek peekCString str
9051 last_error :: GuestfsH -> IO (String)
9053 str <- withForeignPtr h (\\p -> c_last_error p)
9055 then return \"no error\"
9056 else peekCString str
9060 (* Generate wrappers for each foreign function. *)
9062 fun (name, style, _, _, _, _, _) ->
9063 if can_generate style then (
9064 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9066 generate_haskell_prototype ~handle:"GuestfsP" style;
9070 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9072 pr "%s %s = do\n" name
9073 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9075 (* Convert pointer arguments using with* functions. *)
9080 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9081 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9082 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9083 | Bool _ | Int _ -> ()
9085 (* Convert integer arguments. *)
9089 | Bool n -> sprintf "(fromBool %s)" n
9090 | Int n -> sprintf "(fromIntegral %s)" n
9091 | FileIn n | FileOut n
9092 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9094 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9095 (String.concat " " ("p" :: args));
9096 (match fst style with
9097 | RErr | RInt _ | RInt64 _ | RBool _ ->
9098 pr " if (r == -1)\n";
9100 pr " err <- last_error h\n";
9102 | RConstString _ | RConstOptString _ | RString _
9103 | RStringList _ | RStruct _
9104 | RStructList _ | RHashtable _ | RBufferOut _ ->
9105 pr " if (r == nullPtr)\n";
9107 pr " err <- last_error h\n";
9110 (match fst style with
9112 pr " else return ()\n"
9114 pr " else return (fromIntegral r)\n"
9116 pr " else return (fromIntegral r)\n"
9118 pr " else return (toBool r)\n"
9127 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9133 and generate_haskell_prototype ~handle ?(hs = false) style =
9135 let string = if hs then "String" else "CString" in
9136 let int = if hs then "Int" else "CInt" in
9137 let bool = if hs then "Bool" else "CInt" in
9138 let int64 = if hs then "Integer" else "Int64" in
9142 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9143 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9144 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9145 | Bool _ -> pr "%s" bool
9146 | Int _ -> pr "%s" int
9147 | FileIn _ -> pr "%s" string
9148 | FileOut _ -> pr "%s" string
9153 (match fst style with
9154 | RErr -> if not hs then pr "CInt"
9155 | RInt _ -> pr "%s" int
9156 | RInt64 _ -> pr "%s" int64
9157 | RBool _ -> pr "%s" bool
9158 | RConstString _ -> pr "%s" string
9159 | RConstOptString _ -> pr "Maybe %s" string
9160 | RString _ -> pr "%s" string
9161 | RStringList _ -> pr "[%s]" string
9162 | RStruct (_, typ) ->
9163 let name = java_name_of_struct typ in
9165 | RStructList (_, typ) ->
9166 let name = java_name_of_struct typ in
9168 | RHashtable _ -> pr "Hashtable"
9169 | RBufferOut _ -> pr "%s" string
9173 and generate_bindtests () =
9174 generate_header CStyle LGPLv2;
9179 #include <inttypes.h>
9182 #include \"guestfs.h\"
9183 #include \"guestfs-internal-actions.h\"
9184 #include \"guestfs_protocol.h\"
9186 #define error guestfs_error
9187 #define safe_calloc guestfs_safe_calloc
9188 #define safe_malloc guestfs_safe_malloc
9191 print_strings (char *const *argv)
9196 for (argc = 0; argv[argc] != NULL; ++argc) {
9197 if (argc > 0) printf (\", \");
9198 printf (\"\\\"%%s\\\"\", argv[argc]);
9203 /* The test0 function prints its parameters to stdout. */
9207 match test_functions with
9208 | [] -> assert false
9209 | test0 :: tests -> test0, tests in
9212 let (name, style, _, _, _, _, _) = test0 in
9213 generate_prototype ~extern:false ~semicolon:false ~newline:true
9214 ~handle:"g" ~prefix:"guestfs__" name style;
9219 | Device n | Dev_or_Path n
9222 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
9223 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9224 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
9225 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9226 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
9228 pr " /* Java changes stdout line buffering so we need this: */\n";
9229 pr " fflush (stdout);\n";
9235 fun (name, style, _, _, _, _, _) ->
9236 if String.sub name (String.length name - 3) 3 <> "err" then (
9237 pr "/* Test normal return. */\n";
9238 generate_prototype ~extern:false ~semicolon:false ~newline:true
9239 ~handle:"g" ~prefix:"guestfs__" name style;
9241 (match fst style with
9246 pr " sscanf (val, \"%%d\", &r);\n";
9250 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
9253 pr " return strcmp (val, \"true\") == 0;\n"
9255 | RConstOptString _ ->
9256 (* Can't return the input string here. Return a static
9257 * string so we ensure we get a segfault if the caller
9260 pr " return \"static string\";\n"
9262 pr " return strdup (val);\n"
9264 pr " char **strs;\n";
9266 pr " sscanf (val, \"%%d\", &n);\n";
9267 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9268 pr " for (i = 0; i < n; ++i) {\n";
9269 pr " strs[i] = safe_malloc (g, 16);\n";
9270 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
9272 pr " strs[n] = NULL;\n";
9273 pr " return strs;\n"
9274 | RStruct (_, typ) ->
9275 pr " struct guestfs_%s *r;\n" typ;
9276 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9278 | RStructList (_, typ) ->
9279 pr " struct guestfs_%s_list *r;\n" typ;
9280 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9281 pr " sscanf (val, \"%%d\", &r->len);\n";
9282 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9285 pr " char **strs;\n";
9287 pr " sscanf (val, \"%%d\", &n);\n";
9288 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9289 pr " for (i = 0; i < n; ++i) {\n";
9290 pr " strs[i*2] = safe_malloc (g, 16);\n";
9291 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
9292 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
9293 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9295 pr " strs[n*2] = NULL;\n";
9296 pr " return strs;\n"
9298 pr " return strdup (val);\n"
9303 pr "/* Test error return. */\n";
9304 generate_prototype ~extern:false ~semicolon:false ~newline:true
9305 ~handle:"g" ~prefix:"guestfs__" name style;
9307 pr " error (g, \"error\");\n";
9308 (match fst style with
9309 | RErr | RInt _ | RInt64 _ | RBool _ ->
9311 | RConstString _ | RConstOptString _
9312 | RString _ | RStringList _ | RStruct _
9316 pr " return NULL;\n"
9323 and generate_ocaml_bindtests () =
9324 generate_header OCamlStyle GPLv2;
9328 let g = Guestfs.create () in
9335 | CallString s -> "\"" ^ s ^ "\""
9336 | CallOptString None -> "None"
9337 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9338 | CallStringList xs ->
9339 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9340 | CallInt i when i >= 0 -> string_of_int i
9341 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9342 | CallBool b -> string_of_bool b
9347 generate_lang_bindtests (
9348 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
9351 pr "print_endline \"EOF\"\n"
9353 and generate_perl_bindtests () =
9354 pr "#!/usr/bin/perl -w\n";
9355 generate_header HashStyle GPLv2;
9362 my $g = Sys::Guestfs->new ();
9366 String.concat ", " (
9369 | CallString s -> "\"" ^ s ^ "\""
9370 | CallOptString None -> "undef"
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 -> if b then "1" else "0"
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_python_bindtests () =
9387 generate_header HashStyle GPLv2;
9392 g = guestfs.GuestFS ()
9396 String.concat ", " (
9399 | CallString s -> "\"" ^ s ^ "\""
9400 | CallOptString None -> "None"
9401 | CallOptString (Some s) -> sprintf "\"%s\"" s
9402 | CallStringList xs ->
9403 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9404 | CallInt i -> string_of_int i
9405 | CallBool b -> if b then "1" else "0"
9410 generate_lang_bindtests (
9411 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9414 pr "print \"EOF\"\n"
9416 and generate_ruby_bindtests () =
9417 generate_header HashStyle GPLv2;
9422 g = Guestfs::create()
9426 String.concat ", " (
9429 | CallString s -> "\"" ^ s ^ "\""
9430 | CallOptString None -> "nil"
9431 | CallOptString (Some s) -> sprintf "\"%s\"" s
9432 | CallStringList xs ->
9433 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9434 | CallInt i -> string_of_int i
9435 | CallBool b -> string_of_bool b
9440 generate_lang_bindtests (
9441 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9444 pr "print \"EOF\\n\"\n"
9446 and generate_java_bindtests () =
9447 generate_header CStyle GPLv2;
9450 import com.redhat.et.libguestfs.*;
9452 public class Bindtests {
9453 public static void main (String[] argv)
9456 GuestFS g = new GuestFS ();
9460 String.concat ", " (
9463 | CallString s -> "\"" ^ s ^ "\""
9464 | CallOptString None -> "null"
9465 | CallOptString (Some s) -> sprintf "\"%s\"" s
9466 | CallStringList xs ->
9468 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9469 | CallInt i -> string_of_int i
9470 | CallBool b -> string_of_bool b
9475 generate_lang_bindtests (
9476 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9480 System.out.println (\"EOF\");
9482 catch (Exception exn) {
9483 System.err.println (exn);
9490 and generate_haskell_bindtests () =
9491 generate_header HaskellStyle GPLv2;
9494 module Bindtests where
9495 import qualified Guestfs
9505 | CallString s -> "\"" ^ s ^ "\""
9506 | CallOptString None -> "Nothing"
9507 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9508 | CallStringList xs ->
9509 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9510 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9511 | CallInt i -> string_of_int i
9512 | CallBool true -> "True"
9513 | CallBool false -> "False"
9518 generate_lang_bindtests (
9519 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9522 pr " putStrLn \"EOF\"\n"
9524 (* Language-independent bindings tests - we do it this way to
9525 * ensure there is parity in testing bindings across all languages.
9527 and generate_lang_bindtests call =
9528 call "test0" [CallString "abc"; CallOptString (Some "def");
9529 CallStringList []; CallBool false;
9530 CallInt 0; CallString "123"; CallString "456"];
9531 call "test0" [CallString "abc"; CallOptString None;
9532 CallStringList []; CallBool false;
9533 CallInt 0; CallString "123"; CallString "456"];
9534 call "test0" [CallString ""; CallOptString (Some "def");
9535 CallStringList []; CallBool false;
9536 CallInt 0; CallString "123"; CallString "456"];
9537 call "test0" [CallString ""; CallOptString (Some "");
9538 CallStringList []; CallBool false;
9539 CallInt 0; CallString "123"; CallString "456"];
9540 call "test0" [CallString "abc"; CallOptString (Some "def");
9541 CallStringList ["1"]; CallBool false;
9542 CallInt 0; CallString "123"; CallString "456"];
9543 call "test0" [CallString "abc"; CallOptString (Some "def");
9544 CallStringList ["1"; "2"]; CallBool false;
9545 CallInt 0; CallString "123"; CallString "456"];
9546 call "test0" [CallString "abc"; CallOptString (Some "def");
9547 CallStringList ["1"]; CallBool true;
9548 CallInt 0; CallString "123"; CallString "456"];
9549 call "test0" [CallString "abc"; CallOptString (Some "def");
9550 CallStringList ["1"]; CallBool false;
9551 CallInt (-1); CallString "123"; CallString "456"];
9552 call "test0" [CallString "abc"; CallOptString (Some "def");
9553 CallStringList ["1"]; CallBool false;
9554 CallInt (-2); CallString "123"; CallString "456"];
9555 call "test0" [CallString "abc"; CallOptString (Some "def");
9556 CallStringList ["1"]; CallBool false;
9557 CallInt 1; CallString "123"; CallString "456"];
9558 call "test0" [CallString "abc"; CallOptString (Some "def");
9559 CallStringList ["1"]; CallBool false;
9560 CallInt 2; CallString "123"; CallString "456"];
9561 call "test0" [CallString "abc"; CallOptString (Some "def");
9562 CallStringList ["1"]; CallBool false;
9563 CallInt 4095; CallString "123"; CallString "456"];
9564 call "test0" [CallString "abc"; CallOptString (Some "def");
9565 CallStringList ["1"]; CallBool false;
9566 CallInt 0; CallString ""; CallString ""]
9568 (* XXX Add here tests of the return and error functions. *)
9570 (* This is used to generate the src/MAX_PROC_NR file which
9571 * contains the maximum procedure number, a surrogate for the
9572 * ABI version number. See src/Makefile.am for the details.
9574 and generate_max_proc_nr () =
9575 let proc_nrs = List.map (
9576 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9577 ) daemon_functions in
9579 let max_proc_nr = List.fold_left max 0 proc_nrs in
9581 pr "%d\n" max_proc_nr
9583 let output_to filename =
9584 let filename_new = filename ^ ".new" in
9585 chan := open_out filename_new;
9590 (* Is the new file different from the current file? *)
9591 if Sys.file_exists filename && files_equal filename filename_new then
9592 Unix.unlink filename_new (* same, so skip it *)
9594 (* different, overwrite old one *)
9595 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9596 Unix.rename filename_new filename;
9597 Unix.chmod filename 0o444;
9598 printf "written %s\n%!" filename;
9607 if not (Sys.file_exists "HACKING") then (
9609 You are probably running this from the wrong directory.
9610 Run it from the top source directory using the command
9616 let close = output_to "src/guestfs_protocol.x" in
9620 let close = output_to "src/guestfs-structs.h" in
9621 generate_structs_h ();
9624 let close = output_to "src/guestfs-actions.h" in
9625 generate_actions_h ();
9628 let close = output_to "src/guestfs-internal-actions.h" in
9629 generate_internal_actions_h ();
9632 let close = output_to "src/guestfs-actions.c" in
9633 generate_client_actions ();
9636 let close = output_to "daemon/actions.h" in
9637 generate_daemon_actions_h ();
9640 let close = output_to "daemon/stubs.c" in
9641 generate_daemon_actions ();
9644 let close = output_to "daemon/names.c" in
9645 generate_daemon_names ();
9648 let close = output_to "capitests/tests.c" in
9652 let close = output_to "src/guestfs-bindtests.c" in
9653 generate_bindtests ();
9656 let close = output_to "fish/cmds.c" in
9657 generate_fish_cmds ();
9660 let close = output_to "fish/completion.c" in
9661 generate_fish_completion ();
9664 let close = output_to "guestfs-structs.pod" in
9665 generate_structs_pod ();
9668 let close = output_to "guestfs-actions.pod" in
9669 generate_actions_pod ();
9672 let close = output_to "guestfish-actions.pod" in
9673 generate_fish_actions_pod ();
9676 let close = output_to "ocaml/guestfs.mli" in
9677 generate_ocaml_mli ();
9680 let close = output_to "ocaml/guestfs.ml" in
9681 generate_ocaml_ml ();
9684 let close = output_to "ocaml/guestfs_c_actions.c" in
9685 generate_ocaml_c ();
9688 let close = output_to "ocaml/bindtests.ml" in
9689 generate_ocaml_bindtests ();
9692 let close = output_to "perl/Guestfs.xs" in
9693 generate_perl_xs ();
9696 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9697 generate_perl_pm ();
9700 let close = output_to "perl/bindtests.pl" in
9701 generate_perl_bindtests ();
9704 let close = output_to "python/guestfs-py.c" in
9705 generate_python_c ();
9708 let close = output_to "python/guestfs.py" in
9709 generate_python_py ();
9712 let close = output_to "python/bindtests.py" in
9713 generate_python_bindtests ();
9716 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9720 let close = output_to "ruby/bindtests.rb" in
9721 generate_ruby_bindtests ();
9724 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9725 generate_java_java ();
9730 let cols = cols_of_struct typ in
9731 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9732 let close = output_to filename in
9733 generate_java_struct jtyp cols;
9737 let close = output_to "java/Makefile.inc" in
9738 generate_java_makefile_inc ();
9741 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9745 let close = output_to "java/Bindtests.java" in
9746 generate_java_bindtests ();
9749 let close = output_to "haskell/Guestfs.hs" in
9750 generate_haskell_hs ();
9753 let close = output_to "haskell/Bindtests.hs" in
9754 generate_haskell_bindtests ();
9757 let close = output_to "src/MAX_PROC_NR" in
9758 generate_max_proc_nr ();
9761 (* Always generate this file last, and unconditionally. It's used
9762 * by the Makefile to know when we must re-run the generator.
9764 let chan = open_out "src/stamp-generator" in