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 | Int64 of string (* any 64 bit int *)
146 (* These are treated as filenames (simple string parameters) in
147 * the C API and bindings. But in the RPC protocol, we transfer
148 * the actual file content up to or down from the daemon.
149 * FileIn: local machine -> daemon (in request)
150 * FileOut: daemon -> local machine (in reply)
151 * In guestfish (only), the special name "-" means read from
152 * stdin or write to stdout.
157 (* Opaque buffer which can contain arbitrary 8 bit data.
158 * In the C API, this is expressed as <char *, int> pair.
159 * Most other languages have a string type which can contain
160 * ASCII NUL. We use whatever type is appropriate for each
162 * Buffers are limited by the total message size. To transfer
163 * large blocks of data, use FileIn/FileOut parameters instead.
164 * To return an arbitrary buffer, use RBufferOut.
170 | ProtocolLimitWarning (* display warning about protocol size limits *)
171 | DangerWillRobinson (* flags particularly dangerous commands *)
172 | FishAlias of string (* provide an alias for this cmd in guestfish *)
173 | FishAction of string (* call this function in guestfish *)
174 | NotInFish (* do not export via guestfish *)
175 | NotInDocs (* do not add this function to documentation *)
176 | DeprecatedBy of string (* function is deprecated, use .. instead *)
178 (* You can supply zero or as many tests as you want per API call.
180 * Note that the test environment has 3 block devices, of size 500MB,
181 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
182 * a fourth ISO block device with some known files on it (/dev/sdd).
184 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
185 * Number of cylinders was 63 for IDE emulated disks with precisely
186 * the same size. How exactly this is calculated is a mystery.
188 * The ISO block device (/dev/sdd) comes from images/test.iso.
190 * To be able to run the tests in a reasonable amount of time,
191 * the virtual machine and block devices are reused between tests.
192 * So don't try testing kill_subprocess :-x
194 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
196 * Don't assume anything about the previous contents of the block
197 * devices. Use 'Init*' to create some initial scenarios.
199 * You can add a prerequisite clause to any individual test. This
200 * is a run-time check, which, if it fails, causes the test to be
201 * skipped. Useful if testing a command which might not work on
202 * all variations of libguestfs builds. A test that has prerequisite
203 * of 'Always' is run unconditionally.
205 * In addition, packagers can skip individual tests by setting the
206 * environment variables: eg:
207 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
208 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
210 type tests = (test_init * test_prereq * test) list
212 (* Run the command sequence and just expect nothing to fail. *)
215 (* Run the command sequence and expect the output of the final
216 * command to be the string.
218 | TestOutput of seq * string
220 (* Run the command sequence and expect the output of the final
221 * command to be the list of strings.
223 | TestOutputList of seq * string list
225 (* Run the command sequence and expect the output of the final
226 * command to be the list of block devices (could be either
227 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
228 * character of each string).
230 | TestOutputListOfDevices of seq * string list
232 (* Run the command sequence and expect the output of the final
233 * command to be the integer.
235 | TestOutputInt of seq * int
237 (* Run the command sequence and expect the output of the final
238 * command to be <op> <int>, eg. ">=", "1".
240 | TestOutputIntOp of seq * string * int
242 (* Run the command sequence and expect the output of the final
243 * command to be a true value (!= 0 or != NULL).
245 | TestOutputTrue of seq
247 (* Run the command sequence and expect the output of the final
248 * command to be a false value (== 0 or == NULL, but not an error).
250 | TestOutputFalse of seq
252 (* Run the command sequence and expect the output of the final
253 * command to be a list of the given length (but don't care about
256 | TestOutputLength of seq * int
258 (* Run the command sequence and expect the output of the final
259 * command to be a buffer (RBufferOut), ie. string + size.
261 | TestOutputBuffer of seq * string
263 (* Run the command sequence and expect the output of the final
264 * command to be a structure.
266 | TestOutputStruct of seq * test_field_compare list
268 (* Run the command sequence and expect the final command (only)
271 | TestLastFail of seq
273 and test_field_compare =
274 | CompareWithInt of string * int
275 | CompareWithIntOp of string * string * int
276 | CompareWithString of string * string
277 | CompareFieldsIntEq of string * string
278 | CompareFieldsStrEq of string * string
280 (* Test prerequisites. *)
282 (* Test always runs. *)
285 (* Test is currently disabled - eg. it fails, or it tests some
286 * unimplemented feature.
290 (* 'string' is some C code (a function body) that should return
291 * true or false. The test will run if the code returns true.
295 (* As for 'If' but the test runs _unless_ the code returns true. *)
298 (* Some initial scenarios for testing. *)
300 (* Do nothing, block devices could contain random stuff including
301 * LVM PVs, and some filesystems might be mounted. This is usually
306 (* Block devices are empty and no filesystems are mounted. *)
309 (* /dev/sda contains a single partition /dev/sda1, with random
310 * content. /dev/sdb and /dev/sdc may have random content.
315 (* /dev/sda contains a single partition /dev/sda1, which is formatted
316 * as ext2, empty [except for lost+found] and mounted on /.
317 * /dev/sdb and /dev/sdc may have random content.
323 * /dev/sda1 (is a PV):
324 * /dev/VG/LV (size 8MB):
325 * formatted as ext2, empty [except for lost+found], mounted on /
326 * /dev/sdb and /dev/sdc may have random content.
330 (* /dev/sdd (the ISO, see images/ directory in source)
335 (* Sequence of commands for testing. *)
337 and cmd = string list
339 (* Note about long descriptions: When referring to another
340 * action, use the format C<guestfs_other> (ie. the full name of
341 * the C function). This will be replaced as appropriate in other
344 * Apart from that, long descriptions are just perldoc paragraphs.
347 (* Generate a random UUID (used in tests). *)
349 let chan = Unix.open_process_in "uuidgen" in
350 let uuid = input_line chan in
351 (match Unix.close_process_in chan with
352 | Unix.WEXITED 0 -> ()
354 failwith "uuidgen: process exited with non-zero status"
355 | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
356 failwith "uuidgen: process signalled or stopped by signal"
360 (* These test functions are used in the language binding tests. *)
362 let test_all_args = [
365 StringList "strlist";
373 let test_all_rets = [
374 (* except for RErr, which is tested thoroughly elsewhere *)
375 "test0rint", RInt "valout";
376 "test0rint64", RInt64 "valout";
377 "test0rbool", RBool "valout";
378 "test0rconststring", RConstString "valout";
379 "test0rconstoptstring", RConstOptString "valout";
380 "test0rstring", RString "valout";
381 "test0rstringlist", RStringList "valout";
382 "test0rstruct", RStruct ("valout", "lvm_pv");
383 "test0rstructlist", RStructList ("valout", "lvm_pv");
384 "test0rhashtable", RHashtable "valout";
387 let test_functions = [
388 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
390 "internal test function - do not use",
392 This is an internal test function which is used to test whether
393 the automatically generated bindings can handle every possible
394 parameter type correctly.
396 It echos the contents of each parameter to stdout.
398 You probably don't want to call this function.");
402 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
404 "internal test function - do not use",
406 This is an internal test function which is used to test whether
407 the automatically generated bindings can handle every possible
408 return type correctly.
410 It converts string C<val> to the return type.
412 You probably don't want to call this function.");
413 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
415 "internal test function - do not use",
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
421 This function always returns an error.
423 You probably don't want to call this function.")]
427 (* non_daemon_functions are any functions which don't get processed
428 * in the daemon, eg. functions for setting and getting local
429 * configuration values.
432 let non_daemon_functions = test_functions @ [
433 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
435 "launch the qemu subprocess",
437 Internally libguestfs is implemented by running a virtual machine
440 You should call this after configuring the handle
441 (eg. adding drives) but before performing any actions.");
443 ("wait_ready", (RErr, []), -1, [NotInFish],
445 "wait until the qemu subprocess launches (no op)",
447 This function is a no op.
449 In versions of the API E<lt> 1.0.71 you had to call this function
450 just after calling C<guestfs_launch> to wait for the launch
451 to complete. However this is no longer necessary because
452 C<guestfs_launch> now does the waiting.
454 If you see any calls to this function in code then you can just
455 remove them, unless you want to retain compatibility with older
456 versions of the API.");
458 ("kill_subprocess", (RErr, []), -1, [],
460 "kill the qemu subprocess",
462 This kills the qemu subprocess. You should never need to call this.");
464 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
466 "add an image to examine or modify",
468 This function adds a virtual machine disk image C<filename> to the
469 guest. The first time you call this function, the disk appears as IDE
470 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
473 You don't necessarily need to be root when using libguestfs. However
474 you obviously do need sufficient permissions to access the filename
475 for whatever operations you want to perform (ie. read access if you
476 just want to read the image or write access if you want to modify the
479 This is equivalent to the qemu parameter
480 C<-drive file=filename,cache=off,if=...>.
481 C<cache=off> is omitted in cases where it is not supported by
482 the underlying filesystem.
484 Note that this call checks for the existence of C<filename>. This
485 stops you from specifying other types of drive which are supported
486 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
487 the general C<guestfs_config> call instead.");
489 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
491 "add a CD-ROM disk image to examine",
493 This function adds a virtual CD-ROM disk image to the guest.
495 This is equivalent to the qemu parameter C<-cdrom filename>.
497 Note that this call checks for the existence of C<filename>. This
498 stops you from specifying other types of drive which are supported
499 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
500 the general C<guestfs_config> call instead.");
502 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
504 "add a drive in snapshot mode (read-only)",
506 This adds a drive in snapshot mode, making it effectively
509 Note that writes to the device are allowed, and will be seen for
510 the duration of the guestfs handle, but they are written
511 to a temporary file which is discarded as soon as the guestfs
512 handle is closed. We don't currently have any method to enable
513 changes to be committed, although qemu can support this.
515 This is equivalent to the qemu parameter
516 C<-drive file=filename,snapshot=on,if=...>.
518 Note that this call checks for the existence of C<filename>. This
519 stops you from specifying other types of drive which are supported
520 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
521 the general C<guestfs_config> call instead.");
523 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
525 "add qemu parameters",
527 This can be used to add arbitrary qemu command line parameters
528 of the form C<-param value>. Actually it's not quite arbitrary - we
529 prevent you from setting some parameters which would interfere with
530 parameters that we use.
532 The first character of C<param> string must be a C<-> (dash).
534 C<value> can be NULL.");
536 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
538 "set the qemu binary",
540 Set the qemu binary that we will use.
542 The default is chosen when the library was compiled by the
545 You can also override this by setting the C<LIBGUESTFS_QEMU>
546 environment variable.
548 Setting C<qemu> to C<NULL> restores the default qemu binary.");
550 ("get_qemu", (RConstString "qemu", []), -1, [],
551 [InitNone, Always, TestRun (
553 "get the qemu binary",
555 Return the current qemu binary.
557 This is always non-NULL. If it wasn't set already, then this will
558 return the default qemu binary name.");
560 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
562 "set the search path",
564 Set the path that libguestfs searches for kernel and initrd.img.
566 The default is C<$libdir/guestfs> unless overridden by setting
567 C<LIBGUESTFS_PATH> environment variable.
569 Setting C<path> to C<NULL> restores the default path.");
571 ("get_path", (RConstString "path", []), -1, [],
572 [InitNone, Always, TestRun (
574 "get the search path",
576 Return the current search path.
578 This is always non-NULL. If it wasn't set already, then this will
579 return the default path.");
581 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
583 "add options to kernel command line",
585 This function is used to add additional options to the
586 guest kernel command line.
588 The default is C<NULL> unless overridden by setting
589 C<LIBGUESTFS_APPEND> environment variable.
591 Setting C<append> to C<NULL> means I<no> additional options
592 are passed (libguestfs always adds a few of its own).");
594 ("get_append", (RConstOptString "append", []), -1, [],
595 (* This cannot be tested with the current framework. The
596 * function can return NULL in normal operations, which the
597 * test framework interprets as an error.
600 "get the additional kernel options",
602 Return the additional kernel options which are added to the
603 guest kernel command line.
605 If C<NULL> then no options are added.");
607 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
611 If C<autosync> is true, this enables autosync. Libguestfs will make a
612 best effort attempt to run C<guestfs_umount_all> followed by
613 C<guestfs_sync> when the handle is closed
614 (also if the program exits without closing handles).
616 This is disabled by default (except in guestfish where it is
617 enabled by default).");
619 ("get_autosync", (RBool "autosync", []), -1, [],
620 [InitNone, Always, TestRun (
621 [["get_autosync"]])],
624 Get the autosync flag.");
626 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
630 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
632 Verbose messages are disabled unless the environment variable
633 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
635 ("get_verbose", (RBool "verbose", []), -1, [],
639 This returns the verbose messages flag.");
641 ("is_ready", (RBool "ready", []), -1, [],
642 [InitNone, Always, TestOutputTrue (
644 "is ready to accept commands",
646 This returns true iff this handle is ready to accept commands
647 (in the C<READY> state).
649 For more information on states, see L<guestfs(3)>.");
651 ("is_config", (RBool "config", []), -1, [],
652 [InitNone, Always, TestOutputFalse (
654 "is in configuration state",
656 This returns true iff this handle is being configured
657 (in the C<CONFIG> state).
659 For more information on states, see L<guestfs(3)>.");
661 ("is_launching", (RBool "launching", []), -1, [],
662 [InitNone, Always, TestOutputFalse (
663 [["is_launching"]])],
664 "is launching subprocess",
666 This returns true iff this handle is launching the subprocess
667 (in the C<LAUNCHING> state).
669 For more information on states, see L<guestfs(3)>.");
671 ("is_busy", (RBool "busy", []), -1, [],
672 [InitNone, Always, TestOutputFalse (
674 "is busy processing a command",
676 This returns true iff this handle is busy processing a command
677 (in the C<BUSY> state).
679 For more information on states, see L<guestfs(3)>.");
681 ("get_state", (RInt "state", []), -1, [],
683 "get the current state",
685 This returns the current state as an opaque integer. This is
686 only useful for printing debug and internal error messages.
688 For more information on states, see L<guestfs(3)>.");
690 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
691 [InitNone, Always, TestOutputInt (
692 [["set_memsize"; "500"];
693 ["get_memsize"]], 500)],
694 "set memory allocated to the qemu subprocess",
696 This sets the memory size in megabytes allocated to the
697 qemu subprocess. This only has any effect if called before
700 You can also change this by setting the environment
701 variable C<LIBGUESTFS_MEMSIZE> before the handle is
704 For more information on the architecture of libguestfs,
705 see L<guestfs(3)>.");
707 ("get_memsize", (RInt "memsize", []), -1, [],
708 [InitNone, Always, TestOutputIntOp (
709 [["get_memsize"]], ">=", 256)],
710 "get memory allocated to the qemu subprocess",
712 This gets the memory size in megabytes allocated to the
715 If C<guestfs_set_memsize> was not called
716 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
717 then this returns the compiled-in default value for memsize.
719 For more information on the architecture of libguestfs,
720 see L<guestfs(3)>.");
722 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
723 [InitNone, Always, TestOutputIntOp (
724 [["get_pid"]], ">=", 1)],
725 "get PID of qemu subprocess",
727 Return the process ID of the qemu subprocess. If there is no
728 qemu subprocess, then this will return an error.
730 This is an internal call used for debugging and testing.");
732 ("version", (RStruct ("version", "version"), []), -1, [],
733 [InitNone, Always, TestOutputStruct (
734 [["version"]], [CompareWithInt ("major", 1)])],
735 "get the library version number",
737 Return the libguestfs version number that the program is linked
740 Note that because of dynamic linking this is not necessarily
741 the version of libguestfs that you compiled against. You can
742 compile the program, and then at runtime dynamically link
743 against a completely different C<libguestfs.so> library.
745 This call was added in version C<1.0.58>. In previous
746 versions of libguestfs there was no way to get the version
747 number. From C code you can use ELF weak linking tricks to find out if
748 this symbol exists (if it doesn't, then it's an earlier version).
750 The call returns a structure with four elements. The first
751 three (C<major>, C<minor> and C<release>) are numbers and
752 correspond to the usual version triplet. The fourth element
753 (C<extra>) is a string and is normally empty, but may be
754 used for distro-specific information.
756 To construct the original version string:
757 C<$major.$minor.$release$extra>
759 I<Note:> Don't use this call to test for availability
760 of features. Distro backports makes this unreliable.");
762 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
763 [InitNone, Always, TestOutputTrue (
764 [["set_selinux"; "true"];
766 "set SELinux enabled or disabled at appliance boot",
768 This sets the selinux flag that is passed to the appliance
769 at boot time. The default is C<selinux=0> (disabled).
771 Note that if SELinux is enabled, it is always in
772 Permissive mode (C<enforcing=0>).
774 For more information on the architecture of libguestfs,
775 see L<guestfs(3)>.");
777 ("get_selinux", (RBool "selinux", []), -1, [],
779 "get SELinux enabled flag",
781 This returns the current setting of the selinux flag which
782 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
784 For more information on the architecture of libguestfs,
785 see L<guestfs(3)>.");
787 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
788 [InitNone, Always, TestOutputFalse (
789 [["set_trace"; "false"];
791 "enable or disable command traces",
793 If the command trace flag is set to 1, then commands are
794 printed on stdout before they are executed in a format
795 which is very similar to the one used by guestfish. In
796 other words, you can run a program with this enabled, and
797 you will get out a script which you can feed to guestfish
798 to perform the same set of actions.
800 If you want to trace C API calls into libguestfs (and
801 other libraries) then possibly a better way is to use
802 the external ltrace(1) command.
804 Command traces are disabled unless the environment variable
805 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
807 ("get_trace", (RBool "trace", []), -1, [],
809 "get command trace enabled flag",
811 Return the command trace flag.");
813 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
814 [InitNone, Always, TestOutputFalse (
815 [["set_direct"; "false"];
817 "enable or disable direct appliance mode",
819 If the direct appliance mode flag is enabled, then stdin and
820 stdout are passed directly through to the appliance once it
823 One consequence of this is that log messages aren't caught
824 by the library and handled by C<guestfs_set_log_message_callback>,
825 but go straight to stdout.
827 You probably don't want to use this unless you know what you
830 The default is disabled.");
832 ("get_direct", (RBool "direct", []), -1, [],
834 "get direct appliance mode flag",
836 Return the direct appliance mode flag.");
840 (* daemon_functions are any functions which cause some action
841 * to take place in the daemon.
844 let daemon_functions = [
845 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
846 [InitEmpty, Always, TestOutput (
847 [["sfdiskM"; "/dev/sda"; ","];
848 ["mkfs"; "ext2"; "/dev/sda1"];
849 ["mount"; "/dev/sda1"; "/"];
850 ["write_file"; "/new"; "new file contents"; "0"];
851 ["cat"; "/new"]], "new file contents")],
852 "mount a guest disk at a position in the filesystem",
854 Mount a guest disk at a position in the filesystem. Block devices
855 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
856 the guest. If those block devices contain partitions, they will have
857 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
860 The rules are the same as for L<mount(2)>: A filesystem must
861 first be mounted on C</> before others can be mounted. Other
862 filesystems can only be mounted on directories which already
865 The mounted filesystem is writable, if we have sufficient permissions
866 on the underlying device.
868 The filesystem options C<sync> and C<noatime> are set with this
869 call, in order to improve reliability.");
871 ("sync", (RErr, []), 2, [],
872 [ InitEmpty, Always, TestRun [["sync"]]],
873 "sync disks, writes are flushed through to the disk image",
875 This syncs the disk, so that any writes are flushed through to the
876 underlying disk image.
878 You should always call this if you have modified a disk image, before
879 closing the handle.");
881 ("touch", (RErr, [Pathname "path"]), 3, [],
882 [InitBasicFS, Always, TestOutputTrue (
884 ["exists"; "/new"]])],
885 "update file timestamps or create a new file",
887 Touch acts like the L<touch(1)> command. It can be used to
888 update the timestamps on a file, or, if the file does not exist,
889 to create a new zero-length file.");
891 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
892 [InitISOFS, Always, TestOutput (
893 [["cat"; "/known-2"]], "abcdef\n")],
894 "list the contents of a file",
896 Return the contents of the file named C<path>.
898 Note that this function cannot correctly handle binary files
899 (specifically, files containing C<\\0> character which is treated
900 as end of string). For those you need to use the C<guestfs_read_file>
901 or C<guestfs_download> functions which have a more complex interface.");
903 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
904 [], (* XXX Tricky to test because it depends on the exact format
905 * of the 'ls -l' command, which changes between F10 and F11.
907 "list the files in a directory (long format)",
909 List the files in C<directory> (relative to the root directory,
910 there is no cwd) in the format of 'ls -la'.
912 This command is mostly useful for interactive sessions. It
913 is I<not> intended that you try to parse the output string.");
915 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
916 [InitBasicFS, Always, TestOutputList (
919 ["touch"; "/newest"];
920 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
921 "list the files in a directory",
923 List the files in C<directory> (relative to the root directory,
924 there is no cwd). The '.' and '..' entries are not returned, but
925 hidden files are shown.
927 This command is mostly useful for interactive sessions. Programs
928 should probably use C<guestfs_readdir> instead.");
930 ("list_devices", (RStringList "devices", []), 7, [],
931 [InitEmpty, Always, TestOutputListOfDevices (
932 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
933 "list the block devices",
935 List all the block devices.
937 The full block device names are returned, eg. C</dev/sda>");
939 ("list_partitions", (RStringList "partitions", []), 8, [],
940 [InitBasicFS, Always, TestOutputListOfDevices (
941 [["list_partitions"]], ["/dev/sda1"]);
942 InitEmpty, Always, TestOutputListOfDevices (
943 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
944 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
945 "list the partitions",
947 List all the partitions detected on all block devices.
949 The full partition device names are returned, eg. C</dev/sda1>
951 This does not return logical volumes. For that you will need to
952 call C<guestfs_lvs>.");
954 ("pvs", (RStringList "physvols", []), 9, [],
955 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
956 [["pvs"]], ["/dev/sda1"]);
957 InitEmpty, Always, TestOutputListOfDevices (
958 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
959 ["pvcreate"; "/dev/sda1"];
960 ["pvcreate"; "/dev/sda2"];
961 ["pvcreate"; "/dev/sda3"];
962 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
963 "list the LVM physical volumes (PVs)",
965 List all the physical volumes detected. This is the equivalent
966 of the L<pvs(8)> command.
968 This returns a list of just the device names that contain
969 PVs (eg. C</dev/sda2>).
971 See also C<guestfs_pvs_full>.");
973 ("vgs", (RStringList "volgroups", []), 10, [],
974 [InitBasicFSonLVM, Always, TestOutputList (
976 InitEmpty, Always, TestOutputList (
977 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
978 ["pvcreate"; "/dev/sda1"];
979 ["pvcreate"; "/dev/sda2"];
980 ["pvcreate"; "/dev/sda3"];
981 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
982 ["vgcreate"; "VG2"; "/dev/sda3"];
983 ["vgs"]], ["VG1"; "VG2"])],
984 "list the LVM volume groups (VGs)",
986 List all the volumes groups detected. This is the equivalent
987 of the L<vgs(8)> command.
989 This returns a list of just the volume group names that were
990 detected (eg. C<VolGroup00>).
992 See also C<guestfs_vgs_full>.");
994 ("lvs", (RStringList "logvols", []), 11, [],
995 [InitBasicFSonLVM, Always, TestOutputList (
996 [["lvs"]], ["/dev/VG/LV"]);
997 InitEmpty, Always, TestOutputList (
998 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
999 ["pvcreate"; "/dev/sda1"];
1000 ["pvcreate"; "/dev/sda2"];
1001 ["pvcreate"; "/dev/sda3"];
1002 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1003 ["vgcreate"; "VG2"; "/dev/sda3"];
1004 ["lvcreate"; "LV1"; "VG1"; "50"];
1005 ["lvcreate"; "LV2"; "VG1"; "50"];
1006 ["lvcreate"; "LV3"; "VG2"; "50"];
1007 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1008 "list the LVM logical volumes (LVs)",
1010 List all the logical volumes detected. This is the equivalent
1011 of the L<lvs(8)> command.
1013 This returns a list of the logical volume device names
1014 (eg. C</dev/VolGroup00/LogVol00>).
1016 See also C<guestfs_lvs_full>.");
1018 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1019 [], (* XXX how to test? *)
1020 "list the LVM physical volumes (PVs)",
1022 List all the physical volumes detected. This is the equivalent
1023 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1025 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1026 [], (* XXX how to test? *)
1027 "list the LVM volume groups (VGs)",
1029 List all the volumes groups detected. This is the equivalent
1030 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1032 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1033 [], (* XXX how to test? *)
1034 "list the LVM logical volumes (LVs)",
1036 List all the logical volumes detected. This is the equivalent
1037 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1039 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1040 [InitISOFS, Always, TestOutputList (
1041 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1042 InitISOFS, Always, TestOutputList (
1043 [["read_lines"; "/empty"]], [])],
1044 "read file as lines",
1046 Return the contents of the file named C<path>.
1048 The file contents are returned as a list of lines. Trailing
1049 C<LF> and C<CRLF> character sequences are I<not> returned.
1051 Note that this function cannot correctly handle binary files
1052 (specifically, files containing C<\\0> character which is treated
1053 as end of line). For those you need to use the C<guestfs_read_file>
1054 function which has a more complex interface.");
1056 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1057 [], (* XXX Augeas code needs tests. *)
1058 "create a new Augeas handle",
1060 Create a new Augeas handle for editing configuration files.
1061 If there was any previous Augeas handle associated with this
1062 guestfs session, then it is closed.
1064 You must call this before using any other C<guestfs_aug_*>
1067 C<root> is the filesystem root. C<root> must not be NULL,
1070 The flags are the same as the flags defined in
1071 E<lt>augeas.hE<gt>, the logical I<or> of the following
1076 =item C<AUG_SAVE_BACKUP> = 1
1078 Keep the original file with a C<.augsave> extension.
1080 =item C<AUG_SAVE_NEWFILE> = 2
1082 Save changes into a file with extension C<.augnew>, and
1083 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1085 =item C<AUG_TYPE_CHECK> = 4
1087 Typecheck lenses (can be expensive).
1089 =item C<AUG_NO_STDINC> = 8
1091 Do not use standard load path for modules.
1093 =item C<AUG_SAVE_NOOP> = 16
1095 Make save a no-op, just record what would have been changed.
1097 =item C<AUG_NO_LOAD> = 32
1099 Do not load the tree in C<guestfs_aug_init>.
1103 To close the handle, you can call C<guestfs_aug_close>.
1105 To find out more about Augeas, see L<http://augeas.net/>.");
1107 ("aug_close", (RErr, []), 26, [],
1108 [], (* XXX Augeas code needs tests. *)
1109 "close the current Augeas handle",
1111 Close the current Augeas handle and free up any resources
1112 used by it. After calling this, you have to call
1113 C<guestfs_aug_init> again before you can use any other
1114 Augeas functions.");
1116 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1117 [], (* XXX Augeas code needs tests. *)
1118 "define an Augeas variable",
1120 Defines an Augeas variable C<name> whose value is the result
1121 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1124 On success this returns the number of nodes in C<expr>, or
1125 C<0> if C<expr> evaluates to something which is not a nodeset.");
1127 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1128 [], (* XXX Augeas code needs tests. *)
1129 "define an Augeas node",
1131 Defines a variable C<name> whose value is the result of
1134 If C<expr> evaluates to an empty nodeset, a node is created,
1135 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1136 C<name> will be the nodeset containing that single node.
1138 On success this returns a pair containing the
1139 number of nodes in the nodeset, and a boolean flag
1140 if a node was created.");
1142 ("aug_get", (RString "val", [String "augpath"]), 19, [],
1143 [], (* XXX Augeas code needs tests. *)
1144 "look up the value of an Augeas path",
1146 Look up the value associated with C<path>. If C<path>
1147 matches exactly one node, the C<value> is returned.");
1149 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1150 [], (* XXX Augeas code needs tests. *)
1151 "set Augeas path to value",
1153 Set the value associated with C<path> to C<value>.");
1155 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1156 [], (* XXX Augeas code needs tests. *)
1157 "insert a sibling Augeas node",
1159 Create a new sibling C<label> for C<path>, inserting it into
1160 the tree before or after C<path> (depending on the boolean
1163 C<path> must match exactly one existing node in the tree, and
1164 C<label> must be a label, ie. not contain C</>, C<*> or end
1165 with a bracketed index C<[N]>.");
1167 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1168 [], (* XXX Augeas code needs tests. *)
1169 "remove an Augeas path",
1171 Remove C<path> and all of its children.
1173 On success this returns the number of entries which were removed.");
1175 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1176 [], (* XXX Augeas code needs tests. *)
1179 Move the node C<src> to C<dest>. C<src> must match exactly
1180 one node. C<dest> is overwritten if it exists.");
1182 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1183 [], (* XXX Augeas code needs tests. *)
1184 "return Augeas nodes which match augpath",
1186 Returns a list of paths which match the path expression C<path>.
1187 The returned paths are sufficiently qualified so that they match
1188 exactly one node in the current tree.");
1190 ("aug_save", (RErr, []), 25, [],
1191 [], (* XXX Augeas code needs tests. *)
1192 "write all pending Augeas changes to disk",
1194 This writes all pending changes to disk.
1196 The flags which were passed to C<guestfs_aug_init> affect exactly
1197 how files are saved.");
1199 ("aug_load", (RErr, []), 27, [],
1200 [], (* XXX Augeas code needs tests. *)
1201 "load files into the tree",
1203 Load files into the tree.
1205 See C<aug_load> in the Augeas documentation for the full gory
1208 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1209 [], (* XXX Augeas code needs tests. *)
1210 "list Augeas nodes under augpath",
1212 This is just a shortcut for listing C<guestfs_aug_match>
1213 C<path/*> and sorting the resulting nodes into alphabetical order.");
1215 ("rm", (RErr, [Pathname "path"]), 29, [],
1216 [InitBasicFS, Always, TestRun
1219 InitBasicFS, Always, TestLastFail
1221 InitBasicFS, Always, TestLastFail
1226 Remove the single file C<path>.");
1228 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1229 [InitBasicFS, Always, TestRun
1232 InitBasicFS, Always, TestLastFail
1233 [["rmdir"; "/new"]];
1234 InitBasicFS, Always, TestLastFail
1236 ["rmdir"; "/new"]]],
1237 "remove a directory",
1239 Remove the single directory C<path>.");
1241 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1242 [InitBasicFS, Always, TestOutputFalse
1244 ["mkdir"; "/new/foo"];
1245 ["touch"; "/new/foo/bar"];
1247 ["exists"; "/new"]]],
1248 "remove a file or directory recursively",
1250 Remove the file or directory C<path>, recursively removing the
1251 contents if its a directory. This is like the C<rm -rf> shell
1254 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1255 [InitBasicFS, Always, TestOutputTrue
1257 ["is_dir"; "/new"]];
1258 InitBasicFS, Always, TestLastFail
1259 [["mkdir"; "/new/foo/bar"]]],
1260 "create a directory",
1262 Create a directory named C<path>.");
1264 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1265 [InitBasicFS, Always, TestOutputTrue
1266 [["mkdir_p"; "/new/foo/bar"];
1267 ["is_dir"; "/new/foo/bar"]];
1268 InitBasicFS, Always, TestOutputTrue
1269 [["mkdir_p"; "/new/foo/bar"];
1270 ["is_dir"; "/new/foo"]];
1271 InitBasicFS, Always, TestOutputTrue
1272 [["mkdir_p"; "/new/foo/bar"];
1273 ["is_dir"; "/new"]];
1274 (* Regression tests for RHBZ#503133: *)
1275 InitBasicFS, Always, TestRun
1277 ["mkdir_p"; "/new"]];
1278 InitBasicFS, Always, TestLastFail
1280 ["mkdir_p"; "/new"]]],
1281 "create a directory and parents",
1283 Create a directory named C<path>, creating any parent directories
1284 as necessary. This is like the C<mkdir -p> shell command.");
1286 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1287 [], (* XXX Need stat command to test *)
1290 Change the mode (permissions) of C<path> to C<mode>. Only
1291 numeric modes are supported.");
1293 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1294 [], (* XXX Need stat command to test *)
1295 "change file owner and group",
1297 Change the file owner to C<owner> and group to C<group>.
1299 Only numeric uid and gid are supported. If you want to use
1300 names, you will need to locate and parse the password file
1301 yourself (Augeas support makes this relatively easy).");
1303 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1304 [InitISOFS, Always, TestOutputTrue (
1305 [["exists"; "/empty"]]);
1306 InitISOFS, Always, TestOutputTrue (
1307 [["exists"; "/directory"]])],
1308 "test if file or directory exists",
1310 This returns C<true> if and only if there is a file, directory
1311 (or anything) with the given C<path> name.
1313 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1315 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1316 [InitISOFS, Always, TestOutputTrue (
1317 [["is_file"; "/known-1"]]);
1318 InitISOFS, Always, TestOutputFalse (
1319 [["is_file"; "/directory"]])],
1320 "test if file exists",
1322 This returns C<true> if and only if there is a file
1323 with the given C<path> name. Note that it returns false for
1324 other objects like directories.
1326 See also C<guestfs_stat>.");
1328 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1329 [InitISOFS, Always, TestOutputFalse (
1330 [["is_dir"; "/known-3"]]);
1331 InitISOFS, Always, TestOutputTrue (
1332 [["is_dir"; "/directory"]])],
1333 "test if file exists",
1335 This returns C<true> if and only if there is a directory
1336 with the given C<path> name. Note that it returns false for
1337 other objects like files.
1339 See also C<guestfs_stat>.");
1341 ("pvcreate", (RErr, [Device "device"]), 39, [],
1342 [InitEmpty, Always, TestOutputListOfDevices (
1343 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1344 ["pvcreate"; "/dev/sda1"];
1345 ["pvcreate"; "/dev/sda2"];
1346 ["pvcreate"; "/dev/sda3"];
1347 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1348 "create an LVM physical volume",
1350 This creates an LVM physical volume on the named C<device>,
1351 where C<device> should usually be a partition name such
1354 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1355 [InitEmpty, Always, TestOutputList (
1356 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1357 ["pvcreate"; "/dev/sda1"];
1358 ["pvcreate"; "/dev/sda2"];
1359 ["pvcreate"; "/dev/sda3"];
1360 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1361 ["vgcreate"; "VG2"; "/dev/sda3"];
1362 ["vgs"]], ["VG1"; "VG2"])],
1363 "create an LVM volume group",
1365 This creates an LVM volume group called C<volgroup>
1366 from the non-empty list of physical volumes C<physvols>.");
1368 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1369 [InitEmpty, Always, TestOutputList (
1370 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1371 ["pvcreate"; "/dev/sda1"];
1372 ["pvcreate"; "/dev/sda2"];
1373 ["pvcreate"; "/dev/sda3"];
1374 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1375 ["vgcreate"; "VG2"; "/dev/sda3"];
1376 ["lvcreate"; "LV1"; "VG1"; "50"];
1377 ["lvcreate"; "LV2"; "VG1"; "50"];
1378 ["lvcreate"; "LV3"; "VG2"; "50"];
1379 ["lvcreate"; "LV4"; "VG2"; "50"];
1380 ["lvcreate"; "LV5"; "VG2"; "50"];
1382 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1383 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1384 "create an LVM volume group",
1386 This creates an LVM volume group called C<logvol>
1387 on the volume group C<volgroup>, with C<size> megabytes.");
1389 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1390 [InitEmpty, Always, TestOutput (
1391 [["sfdiskM"; "/dev/sda"; ","];
1392 ["mkfs"; "ext2"; "/dev/sda1"];
1393 ["mount"; "/dev/sda1"; "/"];
1394 ["write_file"; "/new"; "new file contents"; "0"];
1395 ["cat"; "/new"]], "new file contents")],
1396 "make a filesystem",
1398 This creates a filesystem on C<device> (usually a partition
1399 or LVM logical volume). The filesystem type is C<fstype>, for
1402 ("sfdisk", (RErr, [Device "device";
1403 Int "cyls"; Int "heads"; Int "sectors";
1404 StringList "lines"]), 43, [DangerWillRobinson],
1406 "create partitions on a block device",
1408 This is a direct interface to the L<sfdisk(8)> program for creating
1409 partitions on block devices.
1411 C<device> should be a block device, for example C</dev/sda>.
1413 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1414 and sectors on the device, which are passed directly to sfdisk as
1415 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1416 of these, then the corresponding parameter is omitted. Usually for
1417 'large' disks, you can just pass C<0> for these, but for small
1418 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1419 out the right geometry and you will need to tell it.
1421 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1422 information refer to the L<sfdisk(8)> manpage.
1424 To create a single partition occupying the whole disk, you would
1425 pass C<lines> as a single element list, when the single element being
1426 the string C<,> (comma).
1428 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1430 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1431 [InitBasicFS, Always, TestOutput (
1432 [["write_file"; "/new"; "new file contents"; "0"];
1433 ["cat"; "/new"]], "new file contents");
1434 InitBasicFS, Always, TestOutput (
1435 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1436 ["cat"; "/new"]], "\nnew file contents\n");
1437 InitBasicFS, Always, TestOutput (
1438 [["write_file"; "/new"; "\n\n"; "0"];
1439 ["cat"; "/new"]], "\n\n");
1440 InitBasicFS, Always, TestOutput (
1441 [["write_file"; "/new"; ""; "0"];
1442 ["cat"; "/new"]], "");
1443 InitBasicFS, Always, TestOutput (
1444 [["write_file"; "/new"; "\n\n\n"; "0"];
1445 ["cat"; "/new"]], "\n\n\n");
1446 InitBasicFS, Always, TestOutput (
1447 [["write_file"; "/new"; "\n"; "0"];
1448 ["cat"; "/new"]], "\n")],
1451 This call creates a file called C<path>. The contents of the
1452 file is the string C<content> (which can contain any 8 bit data),
1453 with length C<size>.
1455 As a special case, if C<size> is C<0>
1456 then the length is calculated using C<strlen> (so in this case
1457 the content cannot contain embedded ASCII NULs).
1459 I<NB.> Owing to a bug, writing content containing ASCII NUL
1460 characters does I<not> work, even if the length is specified.
1461 We hope to resolve this bug in a future version. In the meantime
1462 use C<guestfs_upload>.");
1464 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1465 [InitEmpty, Always, TestOutputListOfDevices (
1466 [["sfdiskM"; "/dev/sda"; ","];
1467 ["mkfs"; "ext2"; "/dev/sda1"];
1468 ["mount"; "/dev/sda1"; "/"];
1469 ["mounts"]], ["/dev/sda1"]);
1470 InitEmpty, Always, TestOutputList (
1471 [["sfdiskM"; "/dev/sda"; ","];
1472 ["mkfs"; "ext2"; "/dev/sda1"];
1473 ["mount"; "/dev/sda1"; "/"];
1476 "unmount a filesystem",
1478 This unmounts the given filesystem. The filesystem may be
1479 specified either by its mountpoint (path) or the device which
1480 contains the filesystem.");
1482 ("mounts", (RStringList "devices", []), 46, [],
1483 [InitBasicFS, Always, TestOutputListOfDevices (
1484 [["mounts"]], ["/dev/sda1"])],
1485 "show mounted filesystems",
1487 This returns the list of currently mounted filesystems. It returns
1488 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1490 Some internal mounts are not shown.
1492 See also: C<guestfs_mountpoints>");
1494 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1495 [InitBasicFS, Always, TestOutputList (
1498 (* check that umount_all can unmount nested mounts correctly: *)
1499 InitEmpty, Always, TestOutputList (
1500 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1501 ["mkfs"; "ext2"; "/dev/sda1"];
1502 ["mkfs"; "ext2"; "/dev/sda2"];
1503 ["mkfs"; "ext2"; "/dev/sda3"];
1504 ["mount"; "/dev/sda1"; "/"];
1506 ["mount"; "/dev/sda2"; "/mp1"];
1507 ["mkdir"; "/mp1/mp2"];
1508 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1509 ["mkdir"; "/mp1/mp2/mp3"];
1512 "unmount all filesystems",
1514 This unmounts all mounted filesystems.
1516 Some internal mounts are not unmounted by this call.");
1518 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1520 "remove all LVM LVs, VGs and PVs",
1522 This command removes all LVM logical volumes, volume groups
1523 and physical volumes.");
1525 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1526 [InitISOFS, Always, TestOutput (
1527 [["file"; "/empty"]], "empty");
1528 InitISOFS, Always, TestOutput (
1529 [["file"; "/known-1"]], "ASCII text");
1530 InitISOFS, Always, TestLastFail (
1531 [["file"; "/notexists"]])],
1532 "determine file type",
1534 This call uses the standard L<file(1)> command to determine
1535 the type or contents of the file. This also works on devices,
1536 for example to find out whether a partition contains a filesystem.
1538 This call will also transparently look inside various types
1541 The exact command which runs is C<file -zbsL path>. Note in
1542 particular that the filename is not prepended to the output
1543 (the C<-b> option).");
1545 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1546 [InitBasicFS, Always, TestOutput (
1547 [["upload"; "test-command"; "/test-command"];
1548 ["chmod"; "0o755"; "/test-command"];
1549 ["command"; "/test-command 1"]], "Result1");
1550 InitBasicFS, Always, TestOutput (
1551 [["upload"; "test-command"; "/test-command"];
1552 ["chmod"; "0o755"; "/test-command"];
1553 ["command"; "/test-command 2"]], "Result2\n");
1554 InitBasicFS, Always, TestOutput (
1555 [["upload"; "test-command"; "/test-command"];
1556 ["chmod"; "0o755"; "/test-command"];
1557 ["command"; "/test-command 3"]], "\nResult3");
1558 InitBasicFS, Always, TestOutput (
1559 [["upload"; "test-command"; "/test-command"];
1560 ["chmod"; "0o755"; "/test-command"];
1561 ["command"; "/test-command 4"]], "\nResult4\n");
1562 InitBasicFS, Always, TestOutput (
1563 [["upload"; "test-command"; "/test-command"];
1564 ["chmod"; "0o755"; "/test-command"];
1565 ["command"; "/test-command 5"]], "\nResult5\n\n");
1566 InitBasicFS, Always, TestOutput (
1567 [["upload"; "test-command"; "/test-command"];
1568 ["chmod"; "0o755"; "/test-command"];
1569 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1570 InitBasicFS, Always, TestOutput (
1571 [["upload"; "test-command"; "/test-command"];
1572 ["chmod"; "0o755"; "/test-command"];
1573 ["command"; "/test-command 7"]], "");
1574 InitBasicFS, Always, TestOutput (
1575 [["upload"; "test-command"; "/test-command"];
1576 ["chmod"; "0o755"; "/test-command"];
1577 ["command"; "/test-command 8"]], "\n");
1578 InitBasicFS, Always, TestOutput (
1579 [["upload"; "test-command"; "/test-command"];
1580 ["chmod"; "0o755"; "/test-command"];
1581 ["command"; "/test-command 9"]], "\n\n");
1582 InitBasicFS, Always, TestOutput (
1583 [["upload"; "test-command"; "/test-command"];
1584 ["chmod"; "0o755"; "/test-command"];
1585 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1586 InitBasicFS, Always, TestOutput (
1587 [["upload"; "test-command"; "/test-command"];
1588 ["chmod"; "0o755"; "/test-command"];
1589 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1590 InitBasicFS, Always, TestLastFail (
1591 [["upload"; "test-command"; "/test-command"];
1592 ["chmod"; "0o755"; "/test-command"];
1593 ["command"; "/test-command"]])],
1594 "run a command from the guest filesystem",
1596 This call runs a command from the guest filesystem. The
1597 filesystem must be mounted, and must contain a compatible
1598 operating system (ie. something Linux, with the same
1599 or compatible processor architecture).
1601 The single parameter is an argv-style list of arguments.
1602 The first element is the name of the program to run.
1603 Subsequent elements are parameters. The list must be
1604 non-empty (ie. must contain a program name). Note that
1605 the command runs directly, and is I<not> invoked via
1606 the shell (see C<guestfs_sh>).
1608 The return value is anything printed to I<stdout> by
1611 If the command returns a non-zero exit status, then
1612 this function returns an error message. The error message
1613 string is the content of I<stderr> from the command.
1615 The C<$PATH> environment variable will contain at least
1616 C</usr/bin> and C</bin>. If you require a program from
1617 another location, you should provide the full path in the
1620 Shared libraries and data files required by the program
1621 must be available on filesystems which are mounted in the
1622 correct places. It is the caller's responsibility to ensure
1623 all filesystems that are needed are mounted at the right
1626 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1627 [InitBasicFS, Always, TestOutputList (
1628 [["upload"; "test-command"; "/test-command"];
1629 ["chmod"; "0o755"; "/test-command"];
1630 ["command_lines"; "/test-command 1"]], ["Result1"]);
1631 InitBasicFS, Always, TestOutputList (
1632 [["upload"; "test-command"; "/test-command"];
1633 ["chmod"; "0o755"; "/test-command"];
1634 ["command_lines"; "/test-command 2"]], ["Result2"]);
1635 InitBasicFS, Always, TestOutputList (
1636 [["upload"; "test-command"; "/test-command"];
1637 ["chmod"; "0o755"; "/test-command"];
1638 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1639 InitBasicFS, Always, TestOutputList (
1640 [["upload"; "test-command"; "/test-command"];
1641 ["chmod"; "0o755"; "/test-command"];
1642 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1643 InitBasicFS, Always, TestOutputList (
1644 [["upload"; "test-command"; "/test-command"];
1645 ["chmod"; "0o755"; "/test-command"];
1646 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1647 InitBasicFS, Always, TestOutputList (
1648 [["upload"; "test-command"; "/test-command"];
1649 ["chmod"; "0o755"; "/test-command"];
1650 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1651 InitBasicFS, Always, TestOutputList (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command_lines"; "/test-command 7"]], []);
1655 InitBasicFS, Always, TestOutputList (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command_lines"; "/test-command 8"]], [""]);
1659 InitBasicFS, Always, TestOutputList (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command_lines"; "/test-command 9"]], ["";""]);
1663 InitBasicFS, Always, TestOutputList (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1667 InitBasicFS, Always, TestOutputList (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1671 "run a command, returning lines",
1673 This is the same as C<guestfs_command>, but splits the
1674 result into a list of lines.
1676 See also: C<guestfs_sh_lines>");
1678 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1679 [InitISOFS, Always, TestOutputStruct (
1680 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1681 "get file information",
1683 Returns file information for the given C<path>.
1685 This is the same as the C<stat(2)> system call.");
1687 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1688 [InitISOFS, Always, TestOutputStruct (
1689 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1690 "get file information for a symbolic link",
1692 Returns file information for the given C<path>.
1694 This is the same as C<guestfs_stat> except that if C<path>
1695 is a symbolic link, then the link is stat-ed, not the file it
1698 This is the same as the C<lstat(2)> system call.");
1700 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1701 [InitISOFS, Always, TestOutputStruct (
1702 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1703 "get file system statistics",
1705 Returns file system statistics for any mounted file system.
1706 C<path> should be a file or directory in the mounted file system
1707 (typically it is the mount point itself, but it doesn't need to be).
1709 This is the same as the C<statvfs(2)> system call.");
1711 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1713 "get ext2/ext3/ext4 superblock details",
1715 This returns the contents of the ext2, ext3 or ext4 filesystem
1716 superblock on C<device>.
1718 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1719 manpage for more details. The list of fields returned isn't
1720 clearly defined, and depends on both the version of C<tune2fs>
1721 that libguestfs was built against, and the filesystem itself.");
1723 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1724 [InitEmpty, Always, TestOutputTrue (
1725 [["blockdev_setro"; "/dev/sda"];
1726 ["blockdev_getro"; "/dev/sda"]])],
1727 "set block device to read-only",
1729 Sets the block device named C<device> to read-only.
1731 This uses the L<blockdev(8)> command.");
1733 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1734 [InitEmpty, Always, TestOutputFalse (
1735 [["blockdev_setrw"; "/dev/sda"];
1736 ["blockdev_getro"; "/dev/sda"]])],
1737 "set block device to read-write",
1739 Sets the block device named C<device> to read-write.
1741 This uses the L<blockdev(8)> command.");
1743 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1744 [InitEmpty, Always, TestOutputTrue (
1745 [["blockdev_setro"; "/dev/sda"];
1746 ["blockdev_getro"; "/dev/sda"]])],
1747 "is block device set to read-only",
1749 Returns a boolean indicating if the block device is read-only
1750 (true if read-only, false if not).
1752 This uses the L<blockdev(8)> command.");
1754 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1755 [InitEmpty, Always, TestOutputInt (
1756 [["blockdev_getss"; "/dev/sda"]], 512)],
1757 "get sectorsize of block device",
1759 This returns the size of sectors on a block device.
1760 Usually 512, but can be larger for modern devices.
1762 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1765 This uses the L<blockdev(8)> command.");
1767 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1768 [InitEmpty, Always, TestOutputInt (
1769 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1770 "get blocksize of block device",
1772 This returns the block size of a device.
1774 (Note this is different from both I<size in blocks> and
1775 I<filesystem block size>).
1777 This uses the L<blockdev(8)> command.");
1779 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1781 "set blocksize of block device",
1783 This sets the block size of a device.
1785 (Note this is different from both I<size in blocks> and
1786 I<filesystem block size>).
1788 This uses the L<blockdev(8)> command.");
1790 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1791 [InitEmpty, Always, TestOutputInt (
1792 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1793 "get total size of device in 512-byte sectors",
1795 This returns the size of the device in units of 512-byte sectors
1796 (even if the sectorsize isn't 512 bytes ... weird).
1798 See also C<guestfs_blockdev_getss> for the real sector size of
1799 the device, and C<guestfs_blockdev_getsize64> for the more
1800 useful I<size in bytes>.
1802 This uses the L<blockdev(8)> command.");
1804 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1805 [InitEmpty, Always, TestOutputInt (
1806 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1807 "get total size of device in bytes",
1809 This returns the size of the device in bytes.
1811 See also C<guestfs_blockdev_getsz>.
1813 This uses the L<blockdev(8)> command.");
1815 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1816 [InitEmpty, Always, TestRun
1817 [["blockdev_flushbufs"; "/dev/sda"]]],
1818 "flush device buffers",
1820 This tells the kernel to flush internal buffers associated
1823 This uses the L<blockdev(8)> command.");
1825 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1826 [InitEmpty, Always, TestRun
1827 [["blockdev_rereadpt"; "/dev/sda"]]],
1828 "reread partition table",
1830 Reread the partition table on C<device>.
1832 This uses the L<blockdev(8)> command.");
1834 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1835 [InitBasicFS, Always, TestOutput (
1836 (* Pick a file from cwd which isn't likely to change. *)
1837 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1838 ["checksum"; "md5"; "/COPYING.LIB"]],
1839 Digest.to_hex (Digest.file "COPYING.LIB"))],
1840 "upload a file from the local machine",
1842 Upload local file C<filename> to C<remotefilename> on the
1845 C<filename> can also be a named pipe.
1847 See also C<guestfs_download>.");
1849 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1850 [InitBasicFS, Always, TestOutput (
1851 (* Pick a file from cwd which isn't likely to change. *)
1852 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1853 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1854 ["upload"; "testdownload.tmp"; "/upload"];
1855 ["checksum"; "md5"; "/upload"]],
1856 Digest.to_hex (Digest.file "COPYING.LIB"))],
1857 "download a file to the local machine",
1859 Download file C<remotefilename> and save it as C<filename>
1860 on the local machine.
1862 C<filename> can also be a named pipe.
1864 See also C<guestfs_upload>, C<guestfs_cat>.");
1866 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1867 [InitISOFS, Always, TestOutput (
1868 [["checksum"; "crc"; "/known-3"]], "2891671662");
1869 InitISOFS, Always, TestLastFail (
1870 [["checksum"; "crc"; "/notexists"]]);
1871 InitISOFS, Always, TestOutput (
1872 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1873 InitISOFS, Always, TestOutput (
1874 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1875 InitISOFS, Always, TestOutput (
1876 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1877 InitISOFS, Always, TestOutput (
1878 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1879 InitISOFS, Always, TestOutput (
1880 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1881 InitISOFS, Always, TestOutput (
1882 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1883 "compute MD5, SHAx or CRC checksum of file",
1885 This call computes the MD5, SHAx or CRC checksum of the
1888 The type of checksum to compute is given by the C<csumtype>
1889 parameter which must have one of the following values:
1895 Compute the cyclic redundancy check (CRC) specified by POSIX
1896 for the C<cksum> command.
1900 Compute the MD5 hash (using the C<md5sum> program).
1904 Compute the SHA1 hash (using the C<sha1sum> program).
1908 Compute the SHA224 hash (using the C<sha224sum> program).
1912 Compute the SHA256 hash (using the C<sha256sum> program).
1916 Compute the SHA384 hash (using the C<sha384sum> program).
1920 Compute the SHA512 hash (using the C<sha512sum> program).
1924 The checksum is returned as a printable string.");
1926 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1927 [InitBasicFS, Always, TestOutput (
1928 [["tar_in"; "../images/helloworld.tar"; "/"];
1929 ["cat"; "/hello"]], "hello\n")],
1930 "unpack tarfile to directory",
1932 This command uploads and unpacks local file C<tarfile> (an
1933 I<uncompressed> tar file) into C<directory>.
1935 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1937 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1939 "pack directory into tarfile",
1941 This command packs the contents of C<directory> and downloads
1942 it to local file C<tarfile>.
1944 To download a compressed tarball, use C<guestfs_tgz_out>.");
1946 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1947 [InitBasicFS, Always, TestOutput (
1948 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1949 ["cat"; "/hello"]], "hello\n")],
1950 "unpack compressed tarball to directory",
1952 This command uploads and unpacks local file C<tarball> (a
1953 I<gzip compressed> tar file) into C<directory>.
1955 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1957 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1959 "pack directory into compressed tarball",
1961 This command packs the contents of C<directory> and downloads
1962 it to local file C<tarball>.
1964 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1966 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1967 [InitBasicFS, Always, TestLastFail (
1969 ["mount_ro"; "/dev/sda1"; "/"];
1970 ["touch"; "/new"]]);
1971 InitBasicFS, Always, TestOutput (
1972 [["write_file"; "/new"; "data"; "0"];
1974 ["mount_ro"; "/dev/sda1"; "/"];
1975 ["cat"; "/new"]], "data")],
1976 "mount a guest disk, read-only",
1978 This is the same as the C<guestfs_mount> command, but it
1979 mounts the filesystem with the read-only (I<-o ro>) flag.");
1981 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1983 "mount a guest disk with mount options",
1985 This is the same as the C<guestfs_mount> command, but it
1986 allows you to set the mount options as for the
1987 L<mount(8)> I<-o> flag.");
1989 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1991 "mount a guest disk with mount options and vfstype",
1993 This is the same as the C<guestfs_mount> command, but it
1994 allows you to set both the mount options and the vfstype
1995 as for the L<mount(8)> I<-o> and I<-t> flags.");
1997 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1999 "debugging and internals",
2001 The C<guestfs_debug> command exposes some internals of
2002 C<guestfsd> (the guestfs daemon) that runs inside the
2005 There is no comprehensive help for this command. You have
2006 to look at the file C<daemon/debug.c> in the libguestfs source
2007 to find out what you can do.");
2009 ("lvremove", (RErr, [Device "device"]), 77, [],
2010 [InitEmpty, Always, TestOutputList (
2011 [["sfdiskM"; "/dev/sda"; ","];
2012 ["pvcreate"; "/dev/sda1"];
2013 ["vgcreate"; "VG"; "/dev/sda1"];
2014 ["lvcreate"; "LV1"; "VG"; "50"];
2015 ["lvcreate"; "LV2"; "VG"; "50"];
2016 ["lvremove"; "/dev/VG/LV1"];
2017 ["lvs"]], ["/dev/VG/LV2"]);
2018 InitEmpty, Always, TestOutputList (
2019 [["sfdiskM"; "/dev/sda"; ","];
2020 ["pvcreate"; "/dev/sda1"];
2021 ["vgcreate"; "VG"; "/dev/sda1"];
2022 ["lvcreate"; "LV1"; "VG"; "50"];
2023 ["lvcreate"; "LV2"; "VG"; "50"];
2024 ["lvremove"; "/dev/VG"];
2026 InitEmpty, Always, TestOutputList (
2027 [["sfdiskM"; "/dev/sda"; ","];
2028 ["pvcreate"; "/dev/sda1"];
2029 ["vgcreate"; "VG"; "/dev/sda1"];
2030 ["lvcreate"; "LV1"; "VG"; "50"];
2031 ["lvcreate"; "LV2"; "VG"; "50"];
2032 ["lvremove"; "/dev/VG"];
2034 "remove an LVM logical volume",
2036 Remove an LVM logical volume C<device>, where C<device> is
2037 the path to the LV, such as C</dev/VG/LV>.
2039 You can also remove all LVs in a volume group by specifying
2040 the VG name, C</dev/VG>.");
2042 ("vgremove", (RErr, [String "vgname"]), 78, [],
2043 [InitEmpty, Always, TestOutputList (
2044 [["sfdiskM"; "/dev/sda"; ","];
2045 ["pvcreate"; "/dev/sda1"];
2046 ["vgcreate"; "VG"; "/dev/sda1"];
2047 ["lvcreate"; "LV1"; "VG"; "50"];
2048 ["lvcreate"; "LV2"; "VG"; "50"];
2051 InitEmpty, Always, TestOutputList (
2052 [["sfdiskM"; "/dev/sda"; ","];
2053 ["pvcreate"; "/dev/sda1"];
2054 ["vgcreate"; "VG"; "/dev/sda1"];
2055 ["lvcreate"; "LV1"; "VG"; "50"];
2056 ["lvcreate"; "LV2"; "VG"; "50"];
2059 "remove an LVM volume group",
2061 Remove an LVM volume group C<vgname>, (for example C<VG>).
2063 This also forcibly removes all logical volumes in the volume
2066 ("pvremove", (RErr, [Device "device"]), 79, [],
2067 [InitEmpty, Always, TestOutputListOfDevices (
2068 [["sfdiskM"; "/dev/sda"; ","];
2069 ["pvcreate"; "/dev/sda1"];
2070 ["vgcreate"; "VG"; "/dev/sda1"];
2071 ["lvcreate"; "LV1"; "VG"; "50"];
2072 ["lvcreate"; "LV2"; "VG"; "50"];
2074 ["pvremove"; "/dev/sda1"];
2076 InitEmpty, Always, TestOutputListOfDevices (
2077 [["sfdiskM"; "/dev/sda"; ","];
2078 ["pvcreate"; "/dev/sda1"];
2079 ["vgcreate"; "VG"; "/dev/sda1"];
2080 ["lvcreate"; "LV1"; "VG"; "50"];
2081 ["lvcreate"; "LV2"; "VG"; "50"];
2083 ["pvremove"; "/dev/sda1"];
2085 InitEmpty, Always, TestOutputListOfDevices (
2086 [["sfdiskM"; "/dev/sda"; ","];
2087 ["pvcreate"; "/dev/sda1"];
2088 ["vgcreate"; "VG"; "/dev/sda1"];
2089 ["lvcreate"; "LV1"; "VG"; "50"];
2090 ["lvcreate"; "LV2"; "VG"; "50"];
2092 ["pvremove"; "/dev/sda1"];
2094 "remove an LVM physical volume",
2096 This wipes a physical volume C<device> so that LVM will no longer
2099 The implementation uses the C<pvremove> command which refuses to
2100 wipe physical volumes that contain any volume groups, so you have
2101 to remove those first.");
2103 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2104 [InitBasicFS, Always, TestOutput (
2105 [["set_e2label"; "/dev/sda1"; "testlabel"];
2106 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2107 "set the ext2/3/4 filesystem label",
2109 This sets the ext2/3/4 filesystem label of the filesystem on
2110 C<device> to C<label>. Filesystem labels are limited to
2113 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2114 to return the existing label on a filesystem.");
2116 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2118 "get the ext2/3/4 filesystem label",
2120 This returns the ext2/3/4 filesystem label of the filesystem on
2123 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2124 (let uuid = uuidgen () in
2125 [InitBasicFS, Always, TestOutput (
2126 [["set_e2uuid"; "/dev/sda1"; uuid];
2127 ["get_e2uuid"; "/dev/sda1"]], uuid);
2128 InitBasicFS, Always, TestOutput (
2129 [["set_e2uuid"; "/dev/sda1"; "clear"];
2130 ["get_e2uuid"; "/dev/sda1"]], "");
2131 (* We can't predict what UUIDs will be, so just check the commands run. *)
2132 InitBasicFS, Always, TestRun (
2133 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2134 InitBasicFS, Always, TestRun (
2135 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2136 "set the ext2/3/4 filesystem UUID",
2138 This sets the ext2/3/4 filesystem UUID of the filesystem on
2139 C<device> to C<uuid>. The format of the UUID and alternatives
2140 such as C<clear>, C<random> and C<time> are described in the
2141 L<tune2fs(8)> manpage.
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2144 to return the existing UUID of a filesystem.");
2146 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2148 "get the ext2/3/4 filesystem UUID",
2150 This returns the ext2/3/4 filesystem UUID of the filesystem on
2153 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2154 [InitBasicFS, Always, TestOutputInt (
2155 [["umount"; "/dev/sda1"];
2156 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2157 InitBasicFS, Always, TestOutputInt (
2158 [["umount"; "/dev/sda1"];
2159 ["zero"; "/dev/sda1"];
2160 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2161 "run the filesystem checker",
2163 This runs the filesystem checker (fsck) on C<device> which
2164 should have filesystem type C<fstype>.
2166 The returned integer is the status. See L<fsck(8)> for the
2167 list of status codes from C<fsck>.
2175 Multiple status codes can be summed together.
2179 A non-zero return code can mean \"success\", for example if
2180 errors have been corrected on the filesystem.
2184 Checking or repairing NTFS volumes is not supported
2189 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2191 ("zero", (RErr, [Device "device"]), 85, [],
2192 [InitBasicFS, Always, TestOutput (
2193 [["umount"; "/dev/sda1"];
2194 ["zero"; "/dev/sda1"];
2195 ["file"; "/dev/sda1"]], "data")],
2196 "write zeroes to the device",
2198 This command writes zeroes over the first few blocks of C<device>.
2200 How many blocks are zeroed isn't specified (but it's I<not> enough
2201 to securely wipe the device). It should be sufficient to remove
2202 any partition tables, filesystem superblocks and so on.
2204 See also: C<guestfs_scrub_device>.");
2206 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2207 (* Test disabled because grub-install incompatible with virtio-blk driver.
2208 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2210 [InitBasicFS, Disabled, TestOutputTrue (
2211 [["grub_install"; "/"; "/dev/sda1"];
2212 ["is_dir"; "/boot"]])],
2215 This command installs GRUB (the Grand Unified Bootloader) on
2216 C<device>, with the root directory being C<root>.");
2218 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2219 [InitBasicFS, Always, TestOutput (
2220 [["write_file"; "/old"; "file content"; "0"];
2221 ["cp"; "/old"; "/new"];
2222 ["cat"; "/new"]], "file content");
2223 InitBasicFS, Always, TestOutputTrue (
2224 [["write_file"; "/old"; "file content"; "0"];
2225 ["cp"; "/old"; "/new"];
2226 ["is_file"; "/old"]]);
2227 InitBasicFS, Always, TestOutput (
2228 [["write_file"; "/old"; "file content"; "0"];
2230 ["cp"; "/old"; "/dir/new"];
2231 ["cat"; "/dir/new"]], "file content")],
2234 This copies a file from C<src> to C<dest> where C<dest> is
2235 either a destination filename or destination directory.");
2237 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2238 [InitBasicFS, Always, TestOutput (
2239 [["mkdir"; "/olddir"];
2240 ["mkdir"; "/newdir"];
2241 ["write_file"; "/olddir/file"; "file content"; "0"];
2242 ["cp_a"; "/olddir"; "/newdir"];
2243 ["cat"; "/newdir/olddir/file"]], "file content")],
2244 "copy a file or directory recursively",
2246 This copies a file or directory from C<src> to C<dest>
2247 recursively using the C<cp -a> command.");
2249 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2250 [InitBasicFS, Always, TestOutput (
2251 [["write_file"; "/old"; "file content"; "0"];
2252 ["mv"; "/old"; "/new"];
2253 ["cat"; "/new"]], "file content");
2254 InitBasicFS, Always, TestOutputFalse (
2255 [["write_file"; "/old"; "file content"; "0"];
2256 ["mv"; "/old"; "/new"];
2257 ["is_file"; "/old"]])],
2260 This moves a file from C<src> to C<dest> where C<dest> is
2261 either a destination filename or destination directory.");
2263 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2264 [InitEmpty, Always, TestRun (
2265 [["drop_caches"; "3"]])],
2266 "drop kernel page cache, dentries and inodes",
2268 This instructs the guest kernel to drop its page cache,
2269 and/or dentries and inode caches. The parameter C<whattodrop>
2270 tells the kernel what precisely to drop, see
2271 L<http://linux-mm.org/Drop_Caches>
2273 Setting C<whattodrop> to 3 should drop everything.
2275 This automatically calls L<sync(2)> before the operation,
2276 so that the maximum guest memory is freed.");
2278 ("dmesg", (RString "kmsgs", []), 91, [],
2279 [InitEmpty, Always, TestRun (
2281 "return kernel messages",
2283 This returns the kernel messages (C<dmesg> output) from
2284 the guest kernel. This is sometimes useful for extended
2285 debugging of problems.
2287 Another way to get the same information is to enable
2288 verbose messages with C<guestfs_set_verbose> or by setting
2289 the environment variable C<LIBGUESTFS_DEBUG=1> before
2290 running the program.");
2292 ("ping_daemon", (RErr, []), 92, [],
2293 [InitEmpty, Always, TestRun (
2294 [["ping_daemon"]])],
2295 "ping the guest daemon",
2297 This is a test probe into the guestfs daemon running inside
2298 the qemu subprocess. Calling this function checks that the
2299 daemon responds to the ping message, without affecting the daemon
2300 or attached block device(s) in any other way.");
2302 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2303 [InitBasicFS, Always, TestOutputTrue (
2304 [["write_file"; "/file1"; "contents of a file"; "0"];
2305 ["cp"; "/file1"; "/file2"];
2306 ["equal"; "/file1"; "/file2"]]);
2307 InitBasicFS, Always, TestOutputFalse (
2308 [["write_file"; "/file1"; "contents of a file"; "0"];
2309 ["write_file"; "/file2"; "contents of another file"; "0"];
2310 ["equal"; "/file1"; "/file2"]]);
2311 InitBasicFS, Always, TestLastFail (
2312 [["equal"; "/file1"; "/file2"]])],
2313 "test if two files have equal contents",
2315 This compares the two files C<file1> and C<file2> and returns
2316 true if their content is exactly equal, or false otherwise.
2318 The external L<cmp(1)> program is used for the comparison.");
2320 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2321 [InitISOFS, Always, TestOutputList (
2322 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2323 InitISOFS, Always, TestOutputList (
2324 [["strings"; "/empty"]], [])],
2325 "print the printable strings in a file",
2327 This runs the L<strings(1)> command on a file and returns
2328 the list of printable strings found.");
2330 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2331 [InitISOFS, Always, TestOutputList (
2332 [["strings_e"; "b"; "/known-5"]], []);
2333 InitBasicFS, Disabled, TestOutputList (
2334 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2335 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2336 "print the printable strings in a file",
2338 This is like the C<guestfs_strings> command, but allows you to
2339 specify the encoding.
2341 See the L<strings(1)> manpage for the full list of encodings.
2343 Commonly useful encodings are C<l> (lower case L) which will
2344 show strings inside Windows/x86 files.
2346 The returned strings are transcoded to UTF-8.");
2348 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2349 [InitISOFS, Always, TestOutput (
2350 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2351 (* Test for RHBZ#501888c2 regression which caused large hexdump
2352 * commands to segfault.
2354 InitISOFS, Always, TestRun (
2355 [["hexdump"; "/100krandom"]])],
2356 "dump a file in hexadecimal",
2358 This runs C<hexdump -C> on the given C<path>. The result is
2359 the human-readable, canonical hex dump of the file.");
2361 ("zerofree", (RErr, [Device "device"]), 97, [],
2362 [InitNone, Always, TestOutput (
2363 [["sfdiskM"; "/dev/sda"; ","];
2364 ["mkfs"; "ext3"; "/dev/sda1"];
2365 ["mount"; "/dev/sda1"; "/"];
2366 ["write_file"; "/new"; "test file"; "0"];
2367 ["umount"; "/dev/sda1"];
2368 ["zerofree"; "/dev/sda1"];
2369 ["mount"; "/dev/sda1"; "/"];
2370 ["cat"; "/new"]], "test file")],
2371 "zero unused inodes and disk blocks on ext2/3 filesystem",
2373 This runs the I<zerofree> program on C<device>. This program
2374 claims to zero unused inodes and disk blocks on an ext2/3
2375 filesystem, thus making it possible to compress the filesystem
2378 You should B<not> run this program if the filesystem is
2381 It is possible that using this program can damage the filesystem
2382 or data on the filesystem.");
2384 ("pvresize", (RErr, [Device "device"]), 98, [],
2386 "resize an LVM physical volume",
2388 This resizes (expands or shrinks) an existing LVM physical
2389 volume to match the new size of the underlying device.");
2391 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2392 Int "cyls"; Int "heads"; Int "sectors";
2393 String "line"]), 99, [DangerWillRobinson],
2395 "modify a single partition on a block device",
2397 This runs L<sfdisk(8)> option to modify just the single
2398 partition C<n> (note: C<n> counts from 1).
2400 For other parameters, see C<guestfs_sfdisk>. You should usually
2401 pass C<0> for the cyls/heads/sectors parameters.");
2403 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2405 "display the partition table",
2407 This displays the partition table on C<device>, in the
2408 human-readable output of the L<sfdisk(8)> command. It is
2409 not intended to be parsed.");
2411 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2413 "display the kernel geometry",
2415 This displays the kernel's idea of the geometry of C<device>.
2417 The result is in human-readable format, and not designed to
2420 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2422 "display the disk geometry from the partition table",
2424 This displays the disk geometry of C<device> read from the
2425 partition table. Especially in the case where the underlying
2426 block device has been resized, this can be different from the
2427 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2429 The result is in human-readable format, and not designed to
2432 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2434 "activate or deactivate all volume groups",
2436 This command activates or (if C<activate> is false) deactivates
2437 all logical volumes in all volume groups.
2438 If activated, then they are made known to the
2439 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2440 then those devices disappear.
2442 This command is the same as running C<vgchange -a y|n>");
2444 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2446 "activate or deactivate some volume groups",
2448 This command activates or (if C<activate> is false) deactivates
2449 all logical volumes in the listed volume groups C<volgroups>.
2450 If activated, then they are made known to the
2451 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2452 then those devices disappear.
2454 This command is the same as running C<vgchange -a y|n volgroups...>
2456 Note that if C<volgroups> is an empty list then B<all> volume groups
2457 are activated or deactivated.");
2459 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2460 [InitNone, Always, TestOutput (
2461 [["sfdiskM"; "/dev/sda"; ","];
2462 ["pvcreate"; "/dev/sda1"];
2463 ["vgcreate"; "VG"; "/dev/sda1"];
2464 ["lvcreate"; "LV"; "VG"; "10"];
2465 ["mkfs"; "ext2"; "/dev/VG/LV"];
2466 ["mount"; "/dev/VG/LV"; "/"];
2467 ["write_file"; "/new"; "test content"; "0"];
2469 ["lvresize"; "/dev/VG/LV"; "20"];
2470 ["e2fsck_f"; "/dev/VG/LV"];
2471 ["resize2fs"; "/dev/VG/LV"];
2472 ["mount"; "/dev/VG/LV"; "/"];
2473 ["cat"; "/new"]], "test content")],
2474 "resize an LVM logical volume",
2476 This resizes (expands or shrinks) an existing LVM logical
2477 volume to C<mbytes>. When reducing, data in the reduced part
2480 ("resize2fs", (RErr, [Device "device"]), 106, [],
2481 [], (* lvresize tests this *)
2482 "resize an ext2/ext3 filesystem",
2484 This resizes an ext2 or ext3 filesystem to match the size of
2485 the underlying device.
2487 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2488 on the C<device> before calling this command. For unknown reasons
2489 C<resize2fs> sometimes gives an error about this and sometimes not.
2490 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2491 calling this function.");
2493 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2494 [InitBasicFS, Always, TestOutputList (
2495 [["find"; "/"]], ["lost+found"]);
2496 InitBasicFS, Always, TestOutputList (
2500 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2501 InitBasicFS, Always, TestOutputList (
2502 [["mkdir_p"; "/a/b/c"];
2503 ["touch"; "/a/b/c/d"];
2504 ["find"; "/a/b/"]], ["c"; "c/d"])],
2505 "find all files and directories",
2507 This command lists out all files and directories, recursively,
2508 starting at C<directory>. It is essentially equivalent to
2509 running the shell command C<find directory -print> but some
2510 post-processing happens on the output, described below.
2512 This returns a list of strings I<without any prefix>. Thus
2513 if the directory structure was:
2519 then the returned list from C<guestfs_find> C</tmp> would be
2527 If C<directory> is not a directory, then this command returns
2530 The returned list is sorted.
2532 See also C<guestfs_find0>.");
2534 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2535 [], (* lvresize tests this *)
2536 "check an ext2/ext3 filesystem",
2538 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2539 filesystem checker on C<device>, noninteractively (C<-p>),
2540 even if the filesystem appears to be clean (C<-f>).
2542 This command is only needed because of C<guestfs_resize2fs>
2543 (q.v.). Normally you should use C<guestfs_fsck>.");
2545 ("sleep", (RErr, [Int "secs"]), 109, [],
2546 [InitNone, Always, TestRun (
2548 "sleep for some seconds",
2550 Sleep for C<secs> seconds.");
2552 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2553 [InitNone, Always, TestOutputInt (
2554 [["sfdiskM"; "/dev/sda"; ","];
2555 ["mkfs"; "ntfs"; "/dev/sda1"];
2556 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2557 InitNone, Always, TestOutputInt (
2558 [["sfdiskM"; "/dev/sda"; ","];
2559 ["mkfs"; "ext2"; "/dev/sda1"];
2560 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2561 "probe NTFS volume",
2563 This command runs the L<ntfs-3g.probe(8)> command which probes
2564 an NTFS C<device> for mountability. (Not all NTFS volumes can
2565 be mounted read-write, and some cannot be mounted at all).
2567 C<rw> is a boolean flag. Set it to true if you want to test
2568 if the volume can be mounted read-write. Set it to false if
2569 you want to test if the volume can be mounted read-only.
2571 The return value is an integer which C<0> if the operation
2572 would succeed, or some non-zero value documented in the
2573 L<ntfs-3g.probe(8)> manual page.");
2575 ("sh", (RString "output", [String "command"]), 111, [],
2576 [], (* XXX needs tests *)
2577 "run a command via the shell",
2579 This call runs a command from the guest filesystem via the
2582 This is like C<guestfs_command>, but passes the command to:
2584 /bin/sh -c \"command\"
2586 Depending on the guest's shell, this usually results in
2587 wildcards being expanded, shell expressions being interpolated
2590 All the provisos about C<guestfs_command> apply to this call.");
2592 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2593 [], (* XXX needs tests *)
2594 "run a command via the shell returning lines",
2596 This is the same as C<guestfs_sh>, but splits the result
2597 into a list of lines.
2599 See also: C<guestfs_command_lines>");
2601 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2602 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2603 * code in stubs.c, since all valid glob patterns must start with "/".
2604 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2606 [InitBasicFS, Always, TestOutputList (
2607 [["mkdir_p"; "/a/b/c"];
2608 ["touch"; "/a/b/c/d"];
2609 ["touch"; "/a/b/c/e"];
2610 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2611 InitBasicFS, Always, TestOutputList (
2612 [["mkdir_p"; "/a/b/c"];
2613 ["touch"; "/a/b/c/d"];
2614 ["touch"; "/a/b/c/e"];
2615 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2616 InitBasicFS, Always, TestOutputList (
2617 [["mkdir_p"; "/a/b/c"];
2618 ["touch"; "/a/b/c/d"];
2619 ["touch"; "/a/b/c/e"];
2620 ["glob_expand"; "/a/*/x/*"]], [])],
2621 "expand a wildcard path",
2623 This command searches for all the pathnames matching
2624 C<pattern> according to the wildcard expansion rules
2627 If no paths match, then this returns an empty list
2628 (note: not an error).
2630 It is just a wrapper around the C L<glob(3)> function
2631 with flags C<GLOB_MARK|GLOB_BRACE>.
2632 See that manual page for more details.");
2634 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2635 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2636 [["scrub_device"; "/dev/sdc"]])],
2637 "scrub (securely wipe) a device",
2639 This command writes patterns over C<device> to make data retrieval
2642 It is an interface to the L<scrub(1)> program. See that
2643 manual page for more details.");
2645 ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2646 [InitBasicFS, Always, TestRun (
2647 [["write_file"; "/file"; "content"; "0"];
2648 ["scrub_file"; "/file"]])],
2649 "scrub (securely wipe) a file",
2651 This command writes patterns over a file to make data retrieval
2654 The file is I<removed> after scrubbing.
2656 It is an interface to the L<scrub(1)> program. See that
2657 manual page for more details.");
2659 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2660 [], (* XXX needs testing *)
2661 "scrub (securely wipe) free space",
2663 This command creates the directory C<dir> and then fills it
2664 with files until the filesystem is full, and scrubs the files
2665 as for C<guestfs_scrub_file>, and deletes them.
2666 The intention is to scrub any free space on the partition
2669 It is an interface to the L<scrub(1)> program. See that
2670 manual page for more details.");
2672 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2673 [InitBasicFS, Always, TestRun (
2675 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2676 "create a temporary directory",
2678 This command creates a temporary directory. The
2679 C<template> parameter should be a full pathname for the
2680 temporary directory name with the final six characters being
2683 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2684 the second one being suitable for Windows filesystems.
2686 The name of the temporary directory that was created
2689 The temporary directory is created with mode 0700
2690 and is owned by root.
2692 The caller is responsible for deleting the temporary
2693 directory and its contents after use.
2695 See also: L<mkdtemp(3)>");
2697 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2698 [InitISOFS, Always, TestOutputInt (
2699 [["wc_l"; "/10klines"]], 10000)],
2700 "count lines in a file",
2702 This command counts the lines in a file, using the
2703 C<wc -l> external command.");
2705 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2706 [InitISOFS, Always, TestOutputInt (
2707 [["wc_w"; "/10klines"]], 10000)],
2708 "count words in a file",
2710 This command counts the words in a file, using the
2711 C<wc -w> external command.");
2713 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2714 [InitISOFS, Always, TestOutputInt (
2715 [["wc_c"; "/100kallspaces"]], 102400)],
2716 "count characters in a file",
2718 This command counts the characters in a file, using the
2719 C<wc -c> external command.");
2721 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2722 [InitISOFS, Always, TestOutputList (
2723 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2724 "return first 10 lines of a file",
2726 This command returns up to the first 10 lines of a file as
2727 a list of strings.");
2729 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2730 [InitISOFS, Always, TestOutputList (
2731 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732 InitISOFS, Always, TestOutputList (
2733 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2734 InitISOFS, Always, TestOutputList (
2735 [["head_n"; "0"; "/10klines"]], [])],
2736 "return first N lines of a file",
2738 If the parameter C<nrlines> is a positive number, this returns the first
2739 C<nrlines> lines of the file C<path>.
2741 If the parameter C<nrlines> is a negative number, this returns lines
2742 from the file C<path>, excluding the last C<nrlines> lines.
2744 If the parameter C<nrlines> is zero, this returns an empty list.");
2746 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2747 [InitISOFS, Always, TestOutputList (
2748 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2749 "return last 10 lines of a file",
2751 This command returns up to the last 10 lines of a file as
2752 a list of strings.");
2754 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2755 [InitISOFS, Always, TestOutputList (
2756 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757 InitISOFS, Always, TestOutputList (
2758 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2759 InitISOFS, Always, TestOutputList (
2760 [["tail_n"; "0"; "/10klines"]], [])],
2761 "return last N lines of a file",
2763 If the parameter C<nrlines> is a positive number, this returns the last
2764 C<nrlines> lines of the file C<path>.
2766 If the parameter C<nrlines> is a negative number, this returns lines
2767 from the file C<path>, starting with the C<-nrlines>th line.
2769 If the parameter C<nrlines> is zero, this returns an empty list.");
2771 ("df", (RString "output", []), 125, [],
2772 [], (* XXX Tricky to test because it depends on the exact format
2773 * of the 'df' command and other imponderables.
2775 "report file system disk space usage",
2777 This command runs the C<df> command to report disk space used.
2779 This command is mostly useful for interactive sessions. It
2780 is I<not> intended that you try to parse the output string.
2781 Use C<statvfs> from programs.");
2783 ("df_h", (RString "output", []), 126, [],
2784 [], (* XXX Tricky to test because it depends on the exact format
2785 * of the 'df' command and other imponderables.
2787 "report file system disk space usage (human readable)",
2789 This command runs the C<df -h> command to report disk space used
2790 in human-readable format.
2792 This command is mostly useful for interactive sessions. It
2793 is I<not> intended that you try to parse the output string.
2794 Use C<statvfs> from programs.");
2796 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2797 [InitISOFS, Always, TestOutputInt (
2798 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2799 "estimate file space usage",
2801 This command runs the C<du -s> command to estimate file space
2804 C<path> can be a file or a directory. If C<path> is a directory
2805 then the estimate includes the contents of the directory and all
2806 subdirectories (recursively).
2808 The result is the estimated size in I<kilobytes>
2809 (ie. units of 1024 bytes).");
2811 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2812 [InitISOFS, Always, TestOutputList (
2813 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2814 "list files in an initrd",
2816 This command lists out files contained in an initrd.
2818 The files are listed without any initial C</> character. The
2819 files are listed in the order they appear (not necessarily
2820 alphabetical). Directory names are listed as separate items.
2822 Old Linux kernels (2.4 and earlier) used a compressed ext2
2823 filesystem as initrd. We I<only> support the newer initramfs
2824 format (compressed cpio files).");
2826 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2828 "mount a file using the loop device",
2830 This command lets you mount C<file> (a filesystem image
2831 in a file) on a mount point. It is entirely equivalent to
2832 the command C<mount -o loop file mountpoint>.");
2834 ("mkswap", (RErr, [Device "device"]), 130, [],
2835 [InitEmpty, Always, TestRun (
2836 [["sfdiskM"; "/dev/sda"; ","];
2837 ["mkswap"; "/dev/sda1"]])],
2838 "create a swap partition",
2840 Create a swap partition on C<device>.");
2842 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2843 [InitEmpty, Always, TestRun (
2844 [["sfdiskM"; "/dev/sda"; ","];
2845 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2846 "create a swap partition with a label",
2848 Create a swap partition on C<device> with label C<label>.
2850 Note that you cannot attach a swap label to a block device
2851 (eg. C</dev/sda>), just to a partition. This appears to be
2852 a limitation of the kernel or swap tools.");
2854 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2855 (let uuid = uuidgen () in
2856 [InitEmpty, Always, TestRun (
2857 [["sfdiskM"; "/dev/sda"; ","];
2858 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2859 "create a swap partition with an explicit UUID",
2861 Create a swap partition on C<device> with UUID C<uuid>.");
2863 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2864 [InitBasicFS, Always, TestOutputStruct (
2865 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2866 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2867 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2868 InitBasicFS, Always, TestOutputStruct (
2869 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2870 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2871 "make block, character or FIFO devices",
2873 This call creates block or character special devices, or
2874 named pipes (FIFOs).
2876 The C<mode> parameter should be the mode, using the standard
2877 constants. C<devmajor> and C<devminor> are the
2878 device major and minor numbers, only used when creating block
2879 and character special devices.");
2881 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2882 [InitBasicFS, Always, TestOutputStruct (
2883 [["mkfifo"; "0o777"; "/node"];
2884 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2885 "make FIFO (named pipe)",
2887 This call creates a FIFO (named pipe) called C<path> with
2888 mode C<mode>. It is just a convenient wrapper around
2889 C<guestfs_mknod>.");
2891 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2892 [InitBasicFS, Always, TestOutputStruct (
2893 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2894 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2895 "make block device node",
2897 This call creates a block device node called C<path> with
2898 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2899 It is just a convenient wrapper around C<guestfs_mknod>.");
2901 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2902 [InitBasicFS, Always, TestOutputStruct (
2903 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2904 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2905 "make char device node",
2907 This call creates a char device node called C<path> with
2908 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2909 It is just a convenient wrapper around C<guestfs_mknod>.");
2911 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2912 [], (* XXX umask is one of those stateful things that we should
2913 * reset between each test.
2915 "set file mode creation mask (umask)",
2917 This function sets the mask used for creating new files and
2918 device nodes to C<mask & 0777>.
2920 Typical umask values would be C<022> which creates new files
2921 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2922 C<002> which creates new files with permissions like
2923 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2925 The default umask is C<022>. This is important because it
2926 means that directories and device nodes will be created with
2927 C<0644> or C<0755> mode even if you specify C<0777>.
2929 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2931 This call returns the previous umask.");
2933 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2935 "read directories entries",
2937 This returns the list of directory entries in directory C<dir>.
2939 All entries in the directory are returned, including C<.> and
2940 C<..>. The entries are I<not> sorted, but returned in the same
2941 order as the underlying filesystem.
2943 Also this call returns basic file type information about each
2944 file. The C<ftyp> field will contain one of the following characters:
2982 The L<readdir(3)> returned a C<d_type> field with an
2987 This function is primarily intended for use by programs. To
2988 get a simple list of names, use C<guestfs_ls>. To get a printable
2989 directory for human consumption, use C<guestfs_ll>.");
2991 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2993 "create partitions on a block device",
2995 This is a simplified interface to the C<guestfs_sfdisk>
2996 command, where partition sizes are specified in megabytes
2997 only (rounded to the nearest cylinder) and you don't need
2998 to specify the cyls, heads and sectors parameters which
2999 were rarely if ever used anyway.
3001 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3003 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3005 "determine file type inside a compressed file",
3007 This command runs C<file> after first decompressing C<path>
3010 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3012 Since 1.0.63, use C<guestfs_file> instead which can now
3013 process compressed files.");
3015 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3017 "list extended attributes of a file or directory",
3019 This call lists the extended attributes of the file or directory
3022 At the system call level, this is a combination of the
3023 L<listxattr(2)> and L<getxattr(2)> calls.
3025 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3027 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3029 "list extended attributes of a file or directory",
3031 This is the same as C<guestfs_getxattrs>, but if C<path>
3032 is a symbolic link, then it returns the extended attributes
3033 of the link itself.");
3035 ("setxattr", (RErr, [String "xattr";
3036 String "val"; Int "vallen"; (* will be BufferIn *)
3037 Pathname "path"]), 143, [],
3039 "set extended attribute of a file or directory",
3041 This call sets the extended attribute named C<xattr>
3042 of the file C<path> to the value C<val> (of length C<vallen>).
3043 The value is arbitrary 8 bit data.
3045 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3047 ("lsetxattr", (RErr, [String "xattr";
3048 String "val"; Int "vallen"; (* will be BufferIn *)
3049 Pathname "path"]), 144, [],
3051 "set extended attribute of a file or directory",
3053 This is the same as C<guestfs_setxattr>, but if C<path>
3054 is a symbolic link, then it sets an extended attribute
3055 of the link itself.");
3057 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3059 "remove extended attribute of a file or directory",
3061 This call removes the extended attribute named C<xattr>
3062 of the file C<path>.
3064 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3066 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3068 "remove extended attribute of a file or directory",
3070 This is the same as C<guestfs_removexattr>, but if C<path>
3071 is a symbolic link, then it removes an extended attribute
3072 of the link itself.");
3074 ("mountpoints", (RHashtable "mps", []), 147, [],
3078 This call is similar to C<guestfs_mounts>. That call returns
3079 a list of devices. This one returns a hash table (map) of
3080 device name to directory where the device is mounted.");
3082 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3083 (* This is a special case: while you would expect a parameter
3084 * of type "Pathname", that doesn't work, because it implies
3085 * NEED_ROOT in the generated calling code in stubs.c, and
3086 * this function cannot use NEED_ROOT.
3089 "create a mountpoint",
3091 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3092 specialized calls that can be used to create extra mountpoints
3093 before mounting the first filesystem.
3095 These calls are I<only> necessary in some very limited circumstances,
3096 mainly the case where you want to mount a mix of unrelated and/or
3097 read-only filesystems together.
3099 For example, live CDs often contain a \"Russian doll\" nest of
3100 filesystems, an ISO outer layer, with a squashfs image inside, with
3101 an ext2/3 image inside that. You can unpack this as follows
3104 add-ro Fedora-11-i686-Live.iso
3107 mkmountpoint /squash
3110 mount-loop /cd/LiveOS/squashfs.img /squash
3111 mount-loop /squash/LiveOS/ext3fs.img /ext3
3113 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3115 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3117 "remove a mountpoint",
3119 This calls removes a mountpoint that was previously created
3120 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3121 for full details.");
3123 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3124 [InitISOFS, Always, TestOutputBuffer (
3125 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3128 This calls returns the contents of the file C<path> as a
3131 Unlike C<guestfs_cat>, this function can correctly
3132 handle files that contain embedded ASCII NUL characters.
3133 However unlike C<guestfs_download>, this function is limited
3134 in the total size of file that can be handled.");
3136 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3137 [InitISOFS, Always, TestOutputList (
3138 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3139 InitISOFS, Always, TestOutputList (
3140 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3141 "return lines matching a pattern",
3143 This calls the external C<grep> program and returns the
3146 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3147 [InitISOFS, Always, TestOutputList (
3148 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3149 "return lines matching a pattern",
3151 This calls the external C<egrep> program and returns the
3154 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3155 [InitISOFS, Always, TestOutputList (
3156 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3157 "return lines matching a pattern",
3159 This calls the external C<fgrep> program and returns the
3162 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3163 [InitISOFS, Always, TestOutputList (
3164 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3165 "return lines matching a pattern",
3167 This calls the external C<grep -i> program and returns the
3170 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3171 [InitISOFS, Always, TestOutputList (
3172 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3173 "return lines matching a pattern",
3175 This calls the external C<egrep -i> program and returns the
3178 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3179 [InitISOFS, Always, TestOutputList (
3180 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3181 "return lines matching a pattern",
3183 This calls the external C<fgrep -i> program and returns the
3186 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3187 [InitISOFS, Always, TestOutputList (
3188 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3189 "return lines matching a pattern",
3191 This calls the external C<zgrep> program and returns the
3194 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3195 [InitISOFS, Always, TestOutputList (
3196 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3197 "return lines matching a pattern",
3199 This calls the external C<zegrep> program and returns the
3202 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3203 [InitISOFS, Always, TestOutputList (
3204 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3205 "return lines matching a pattern",
3207 This calls the external C<zfgrep> program and returns the
3210 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3211 [InitISOFS, Always, TestOutputList (
3212 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3213 "return lines matching a pattern",
3215 This calls the external C<zgrep -i> program and returns the
3218 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3219 [InitISOFS, Always, TestOutputList (
3220 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3221 "return lines matching a pattern",
3223 This calls the external C<zegrep -i> program and returns the
3226 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3227 [InitISOFS, Always, TestOutputList (
3228 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3229 "return lines matching a pattern",
3231 This calls the external C<zfgrep -i> program and returns the
3234 ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3235 [InitISOFS, Always, TestOutput (
3236 [["realpath"; "/../directory"]], "/directory")],
3237 "canonicalized absolute pathname",
3239 Return the canonicalized absolute pathname of C<path>. The
3240 returned path has no C<.>, C<..> or symbolic link path elements.");
3242 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3243 [InitBasicFS, Always, TestOutputStruct (
3246 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3247 "create a hard link",
3249 This command creates a hard link using the C<ln> command.");
3251 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3252 [InitBasicFS, Always, TestOutputStruct (
3255 ["ln_f"; "/a"; "/b"];
3256 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3257 "create a hard link",
3259 This command creates a hard link using the C<ln -f> command.
3260 The C<-f> option removes the link (C<linkname>) if it exists already.");
3262 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3263 [InitBasicFS, Always, TestOutputStruct (
3265 ["ln_s"; "a"; "/b"];
3266 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3267 "create a symbolic link",
3269 This command creates a symbolic link using the C<ln -s> command.");
3271 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3272 [InitBasicFS, Always, TestOutput (
3273 [["mkdir_p"; "/a/b"];
3274 ["touch"; "/a/b/c"];
3275 ["ln_sf"; "../d"; "/a/b/c"];
3276 ["readlink"; "/a/b/c"]], "../d")],
3277 "create a symbolic link",
3279 This command creates a symbolic link using the C<ln -sf> command,
3280 The C<-f> option removes the link (C<linkname>) if it exists already.");
3282 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3283 [] (* XXX tested above *),
3284 "read the target of a symbolic link",
3286 This command reads the target of a symbolic link.");
3288 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3289 [InitBasicFS, Always, TestOutputStruct (
3290 [["fallocate"; "/a"; "1000000"];
3291 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3292 "preallocate a file in the guest filesystem",
3294 This command preallocates a file (containing zero bytes) named
3295 C<path> of size C<len> bytes. If the file exists already, it
3298 Do not confuse this with the guestfish-specific
3299 C<alloc> command which allocates a file in the host and
3300 attaches it as a device.");
3302 ("swapon_device", (RErr, [Device "device"]), 170, [],
3303 [InitPartition, Always, TestRun (
3304 [["mkswap"; "/dev/sda1"];
3305 ["swapon_device"; "/dev/sda1"];
3306 ["swapoff_device"; "/dev/sda1"]])],
3307 "enable swap on device",
3309 This command enables the libguestfs appliance to use the
3310 swap device or partition named C<device>. The increased
3311 memory is made available for all commands, for example
3312 those run using C<guestfs_command> or C<guestfs_sh>.
3314 Note that you should not swap to existing guest swap
3315 partitions unless you know what you are doing. They may
3316 contain hibernation information, or other information that
3317 the guest doesn't want you to trash. You also risk leaking
3318 information about the host to the guest this way. Instead,
3319 attach a new host device to the guest and swap on that.");
3321 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3322 [], (* XXX tested by swapon_device *)
3323 "disable swap on device",
3325 This command disables the libguestfs appliance swap
3326 device or partition named C<device>.
3327 See C<guestfs_swapon_device>.");
3329 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3330 [InitBasicFS, Always, TestRun (
3331 [["fallocate"; "/swap"; "8388608"];
3332 ["mkswap_file"; "/swap"];
3333 ["swapon_file"; "/swap"];
3334 ["swapoff_file"; "/swap"]])],
3335 "enable swap on file",
3337 This command enables swap to a file.
3338 See C<guestfs_swapon_device> for other notes.");
3340 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3341 [], (* XXX tested by swapon_file *)
3342 "disable swap on file",
3344 This command disables the libguestfs appliance swap on file.");
3346 ("swapon_label", (RErr, [String "label"]), 174, [],
3347 [InitEmpty, Always, TestRun (
3348 [["sfdiskM"; "/dev/sdb"; ","];
3349 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3350 ["swapon_label"; "swapit"];
3351 ["swapoff_label"; "swapit"];
3352 ["zero"; "/dev/sdb"];
3353 ["blockdev_rereadpt"; "/dev/sdb"]])],
3354 "enable swap on labeled swap partition",
3356 This command enables swap to a labeled swap partition.
3357 See C<guestfs_swapon_device> for other notes.");
3359 ("swapoff_label", (RErr, [String "label"]), 175, [],
3360 [], (* XXX tested by swapon_label *)
3361 "disable swap on labeled swap partition",
3363 This command disables the libguestfs appliance swap on
3364 labeled swap partition.");
3366 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3367 (let uuid = uuidgen () in
3368 [InitEmpty, Always, TestRun (
3369 [["mkswap_U"; uuid; "/dev/sdb"];
3370 ["swapon_uuid"; uuid];
3371 ["swapoff_uuid"; uuid]])]),
3372 "enable swap on swap partition by UUID",
3374 This command enables swap to a swap partition with the given UUID.
3375 See C<guestfs_swapon_device> for other notes.");
3377 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3378 [], (* XXX tested by swapon_uuid *)
3379 "disable swap on swap partition by UUID",
3381 This command disables the libguestfs appliance swap partition
3382 with the given UUID.");
3384 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3385 [InitBasicFS, Always, TestRun (
3386 [["fallocate"; "/swap"; "8388608"];
3387 ["mkswap_file"; "/swap"]])],
3388 "create a swap file",
3392 This command just writes a swap file signature to an existing
3393 file. To create the file itself, use something like C<guestfs_fallocate>.");
3395 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3396 [InitISOFS, Always, TestRun (
3397 [["inotify_init"; "0"]])],
3398 "create an inotify handle",
3400 This command creates a new inotify handle.
3401 The inotify subsystem can be used to notify events which happen to
3402 objects in the guest filesystem.
3404 C<maxevents> is the maximum number of events which will be
3405 queued up between calls to C<guestfs_inotify_read> or
3406 C<guestfs_inotify_files>.
3407 If this is passed as C<0>, then the kernel (or previously set)
3408 default is used. For Linux 2.6.29 the default was 16384 events.
3409 Beyond this limit, the kernel throws away events, but records
3410 the fact that it threw them away by setting a flag
3411 C<IN_Q_OVERFLOW> in the returned structure list (see
3412 C<guestfs_inotify_read>).
3414 Before any events are generated, you have to add some
3415 watches to the internal watch list. See:
3416 C<guestfs_inotify_add_watch>,
3417 C<guestfs_inotify_rm_watch> and
3418 C<guestfs_inotify_watch_all>.
3420 Queued up events should be read periodically by calling
3421 C<guestfs_inotify_read>
3422 (or C<guestfs_inotify_files> which is just a helpful
3423 wrapper around C<guestfs_inotify_read>). If you don't
3424 read the events out often enough then you risk the internal
3427 The handle should be closed after use by calling
3428 C<guestfs_inotify_close>. This also removes any
3429 watches automatically.
3431 See also L<inotify(7)> for an overview of the inotify interface
3432 as exposed by the Linux kernel, which is roughly what we expose
3433 via libguestfs. Note that there is one global inotify handle
3434 per libguestfs instance.");
3436 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3437 [InitBasicFS, Always, TestOutputList (
3438 [["inotify_init"; "0"];
3439 ["inotify_add_watch"; "/"; "1073741823"];
3442 ["inotify_files"]], ["a"; "b"])],
3443 "add an inotify watch",
3445 Watch C<path> for the events listed in C<mask>.
3447 Note that if C<path> is a directory then events within that
3448 directory are watched, but this does I<not> happen recursively
3449 (in subdirectories).
3451 Note for non-C or non-Linux callers: the inotify events are
3452 defined by the Linux kernel ABI and are listed in
3453 C</usr/include/sys/inotify.h>.");
3455 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3457 "remove an inotify watch",
3459 Remove a previously defined inotify watch.
3460 See C<guestfs_inotify_add_watch>.");
3462 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3464 "return list of inotify events",
3466 Return the complete queue of events that have happened
3467 since the previous read call.
3469 If no events have happened, this returns an empty list.
3471 I<Note>: In order to make sure that all events have been
3472 read, you must call this function repeatedly until it
3473 returns an empty list. The reason is that the call will
3474 read events up to the maximum appliance-to-host message
3475 size and leave remaining events in the queue.");
3477 ("inotify_files", (RStringList "paths", []), 183, [],
3479 "return list of watched files that had events",
3481 This function is a helpful wrapper around C<guestfs_inotify_read>
3482 which just returns a list of pathnames of objects that were
3483 touched. The returned pathnames are sorted and deduplicated.");
3485 ("inotify_close", (RErr, []), 184, [],
3487 "close the inotify handle",
3489 This closes the inotify handle which was previously
3490 opened by inotify_init. It removes all watches, throws
3491 away any pending events, and deallocates all resources.");
3493 ("setcon", (RErr, [String "context"]), 185, [],
3495 "set SELinux security context",
3497 This sets the SELinux security context of the daemon
3498 to the string C<context>.
3500 See the documentation about SELINUX in L<guestfs(3)>.");
3502 ("getcon", (RString "context", []), 186, [],
3504 "get SELinux security context",
3506 This gets the SELinux security context of the daemon.
3508 See the documentation about SELINUX in L<guestfs(3)>,
3509 and C<guestfs_setcon>");
3511 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3512 [InitEmpty, Always, TestOutput (
3513 [["sfdiskM"; "/dev/sda"; ","];
3514 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3515 ["mount"; "/dev/sda1"; "/"];
3516 ["write_file"; "/new"; "new file contents"; "0"];
3517 ["cat"; "/new"]], "new file contents")],
3518 "make a filesystem with block size",
3520 This call is similar to C<guestfs_mkfs>, but it allows you to
3521 control the block size of the resulting filesystem. Supported
3522 block sizes depend on the filesystem type, but typically they
3523 are C<1024>, C<2048> or C<4096> only.");
3525 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3526 [InitEmpty, Always, TestOutput (
3527 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3528 ["mke2journal"; "4096"; "/dev/sda1"];
3529 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3530 ["mount"; "/dev/sda2"; "/"];
3531 ["write_file"; "/new"; "new file contents"; "0"];
3532 ["cat"; "/new"]], "new file contents")],
3533 "make ext2/3/4 external journal",
3535 This creates an ext2 external journal on C<device>. It is equivalent
3538 mke2fs -O journal_dev -b blocksize device");
3540 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3541 [InitEmpty, Always, TestOutput (
3542 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3543 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3544 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3545 ["mount"; "/dev/sda2"; "/"];
3546 ["write_file"; "/new"; "new file contents"; "0"];
3547 ["cat"; "/new"]], "new file contents")],
3548 "make ext2/3/4 external journal with label",
3550 This creates an ext2 external journal on C<device> with label C<label>.");
3552 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3553 (let uuid = uuidgen () in
3554 [InitEmpty, Always, TestOutput (
3555 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3556 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3557 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3558 ["mount"; "/dev/sda2"; "/"];
3559 ["write_file"; "/new"; "new file contents"; "0"];
3560 ["cat"; "/new"]], "new file contents")]),
3561 "make ext2/3/4 external journal with UUID",
3563 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3565 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3567 "make ext2/3/4 filesystem with external journal",
3569 This creates an ext2/3/4 filesystem on C<device> with
3570 an external journal on C<journal>. It is equivalent
3573 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3575 See also C<guestfs_mke2journal>.");
3577 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3579 "make ext2/3/4 filesystem with external journal",
3581 This creates an ext2/3/4 filesystem on C<device> with
3582 an external journal on the journal labeled C<label>.
3584 See also C<guestfs_mke2journal_L>.");
3586 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3588 "make ext2/3/4 filesystem with external journal",
3590 This creates an ext2/3/4 filesystem on C<device> with
3591 an external journal on the journal with UUID C<uuid>.
3593 See also C<guestfs_mke2journal_U>.");
3595 ("modprobe", (RErr, [String "modulename"]), 194, [],
3596 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3597 "load a kernel module",
3599 This loads a kernel module in the appliance.
3601 The kernel module must have been whitelisted when libguestfs
3602 was built (see C<appliance/kmod.whitelist.in> in the source).");
3604 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3605 [InitNone, Always, TestOutput (
3606 [["echo_daemon"; "This is a test"]], "This is a test"
3608 "echo arguments back to the client",
3610 This command concatenate the list of C<words> passed with single spaces between
3611 them and returns the resulting string.
3613 You can use this command to test the connection through to the daemon.
3615 See also C<guestfs_ping_daemon>.");
3617 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3618 [], (* There is a regression test for this. *)
3619 "find all files and directories, returning NUL-separated list",
3621 This command lists out all files and directories, recursively,
3622 starting at C<directory>, placing the resulting list in the
3623 external file called C<files>.
3625 This command works the same way as C<guestfs_find> with the
3626 following exceptions:
3632 The resulting list is written to an external file.
3636 Items (filenames) in the result are separated
3637 by C<\\0> characters. See L<find(1)> option I<-print0>.
3641 This command is not limited in the number of names that it
3646 The result list is not sorted.
3650 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3651 [InitISOFS, Always, TestOutput (
3652 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3653 InitISOFS, Always, TestOutput (
3654 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3655 InitISOFS, Always, TestOutput (
3656 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3657 InitISOFS, Always, TestLastFail (
3658 [["case_sensitive_path"; "/Known-1/"]]);
3659 InitBasicFS, Always, TestOutput (
3661 ["mkdir"; "/a/bbb"];
3662 ["touch"; "/a/bbb/c"];
3663 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3664 InitBasicFS, Always, TestOutput (
3666 ["mkdir"; "/a/bbb"];
3667 ["touch"; "/a/bbb/c"];
3668 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3669 InitBasicFS, Always, TestLastFail (
3671 ["mkdir"; "/a/bbb"];
3672 ["touch"; "/a/bbb/c"];
3673 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3674 "return true path on case-insensitive filesystem",
3676 This can be used to resolve case insensitive paths on
3677 a filesystem which is case sensitive. The use case is
3678 to resolve paths which you have read from Windows configuration
3679 files or the Windows Registry, to the true path.
3681 The command handles a peculiarity of the Linux ntfs-3g
3682 filesystem driver (and probably others), which is that although
3683 the underlying filesystem is case-insensitive, the driver
3684 exports the filesystem to Linux as case-sensitive.
3686 One consequence of this is that special directories such
3687 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3688 (or other things) depending on the precise details of how
3689 they were created. In Windows itself this would not be
3692 Bug or feature? You decide:
3693 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3695 This function resolves the true case of each element in the
3696 path and returns the case-sensitive path.
3698 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3699 might return C<\"/WINDOWS/system32\"> (the exact return value
3700 would depend on details of how the directories were originally
3701 created under Windows).
3704 This function does not handle drive names, backslashes etc.
3706 See also C<guestfs_realpath>.");
3708 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3709 [InitBasicFS, Always, TestOutput (
3710 [["vfs_type"; "/dev/sda1"]], "ext2")],
3711 "get the Linux VFS type corresponding to a mounted device",
3713 This command gets the block device type corresponding to
3714 a mounted device called C<device>.
3716 Usually the result is the name of the Linux VFS module that
3717 is used to mount this device (probably determined automatically
3718 if you used the C<guestfs_mount> call).");
3720 ("truncate", (RErr, [Pathname "path"]), 199, [],
3721 [InitBasicFS, Always, TestOutputStruct (
3722 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3723 ["truncate"; "/test"];
3724 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3725 "truncate a file to zero size",
3727 This command truncates C<path> to a zero-length file. The
3728 file must exist already.");
3730 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3731 [InitBasicFS, Always, TestOutputStruct (
3732 [["touch"; "/test"];
3733 ["truncate_size"; "/test"; "1000"];
3734 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3735 "truncate a file to a particular size",
3737 This command truncates C<path> to size C<size> bytes. The file
3738 must exist already. If the file is smaller than C<size> then
3739 the file is extended to the required size with null bytes.");
3741 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3742 [InitBasicFS, Always, TestOutputStruct (
3743 [["touch"; "/test"];
3744 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3745 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3746 "set timestamp of a file with nanosecond precision",
3748 This command sets the timestamps of a file with nanosecond
3751 C<atsecs, atnsecs> are the last access time (atime) in secs and
3752 nanoseconds from the epoch.
3754 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3755 secs and nanoseconds from the epoch.
3757 If the C<*nsecs> field contains the special value C<-1> then
3758 the corresponding timestamp is set to the current time. (The
3759 C<*secs> field is ignored in this case).
3761 If the C<*nsecs> field contains the special value C<-2> then
3762 the corresponding timestamp is left unchanged. (The
3763 C<*secs> field is ignored in this case).");
3765 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3766 [InitBasicFS, Always, TestOutputStruct (
3767 [["mkdir_mode"; "/test"; "0o111"];
3768 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3769 "create a directory with a particular mode",
3771 This command creates a directory, setting the initial permissions
3772 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3774 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3776 "change file owner and group",
3778 Change the file owner to C<owner> and group to C<group>.
3779 This is like C<guestfs_chown> but if C<path> is a symlink then
3780 the link itself is changed, not the target.
3782 Only numeric uid and gid are supported. If you want to use
3783 names, you will need to locate and parse the password file
3784 yourself (Augeas support makes this relatively easy).");
3786 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3788 "lstat on multiple files",
3790 This call allows you to perform the C<guestfs_lstat> operation
3791 on multiple files, where all files are in the directory C<path>.
3792 C<names> is the list of files from this directory.
3794 On return you get a list of stat structs, with a one-to-one
3795 correspondence to the C<names> list. If any name did not exist
3796 or could not be lstat'd, then the C<ino> field of that structure
3799 This call is intended for programs that want to efficiently
3800 list a directory contents without making many round-trips.
3801 See also C<guestfs_lxattrlist> for a similarly efficient call
3802 for getting extended attributes. Very long directory listings
3803 might cause the protocol message size to be exceeded, causing
3804 this call to fail. The caller must split up such requests
3805 into smaller groups of names.");
3807 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
3809 "lgetxattr on multiple files",
3811 This call allows you to get the extended attributes
3812 of multiple files, where all files are in the directory C<path>.
3813 C<names> is the list of files from this directory.
3815 On return you get a flat list of xattr structs which must be
3816 interpreted sequentially. The first xattr struct always has a zero-length
3817 C<attrname>. C<attrval> in this struct is zero-length
3818 to indicate there was an error doing C<lgetxattr> for this
3819 file, I<or> is a C string which is a decimal number
3820 (the number of following attributes for this file, which could
3821 be C<\"0\">). Then after the first xattr struct are the
3822 zero or more attributes for the first named file.
3823 This repeats for the second and subsequent files.
3825 This call is intended for programs that want to efficiently
3826 list a directory contents without making many round-trips.
3827 See also C<guestfs_lstatlist> for a similarly efficient call
3828 for getting standard stats. Very long directory listings
3829 might cause the protocol message size to be exceeded, causing
3830 this call to fail. The caller must split up such requests
3831 into smaller groups of names.");
3833 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3835 "readlink on multiple files",
3837 This call allows you to do a C<readlink> operation
3838 on multiple files, where all files are in the directory C<path>.
3839 C<names> is the list of files from this directory.
3841 On return you get a list of strings, with a one-to-one
3842 correspondence to the C<names> list. Each string is the
3843 value of the symbol link.
3845 If the C<readlink(2)> operation fails on any name, then
3846 the corresponding result string is the empty string C<\"\">.
3847 However the whole operation is completed even if there
3848 were C<readlink(2)> errors, and so you can call this
3849 function with names where you don't know if they are
3850 symbolic links already (albeit slightly less efficient).
3852 This call is intended for programs that want to efficiently
3853 list a directory contents without making many round-trips.
3854 Very long directory listings might cause the protocol
3855 message size to be exceeded, causing
3856 this call to fail. The caller must split up such requests
3857 into smaller groups of names.");
3861 let all_functions = non_daemon_functions @ daemon_functions
3863 (* In some places we want the functions to be displayed sorted
3864 * alphabetically, so this is useful:
3866 let all_functions_sorted =
3867 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3868 compare n1 n2) all_functions
3870 (* Field types for structures. *)
3872 | FChar (* C 'char' (really, a 7 bit byte). *)
3873 | FString (* nul-terminated ASCII string, NOT NULL. *)
3874 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3879 | FBytes (* Any int measure that counts bytes. *)
3880 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3881 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3883 (* Because we generate extra parsing code for LVM command line tools,
3884 * we have to pull out the LVM columns separately here.
3894 "pv_attr", FString (* XXX *);
3895 "pv_pe_count", FInt64;
3896 "pv_pe_alloc_count", FInt64;
3899 "pv_mda_count", FInt64;
3900 "pv_mda_free", FBytes;
3901 (* Not in Fedora 10:
3902 "pv_mda_size", FBytes;
3909 "vg_attr", FString (* XXX *);
3912 "vg_sysid", FString;
3913 "vg_extent_size", FBytes;
3914 "vg_extent_count", FInt64;
3915 "vg_free_count", FInt64;
3920 "snap_count", FInt64;
3923 "vg_mda_count", FInt64;
3924 "vg_mda_free", FBytes;
3925 (* Not in Fedora 10:
3926 "vg_mda_size", FBytes;
3932 "lv_attr", FString (* XXX *);
3935 "lv_kernel_major", FInt64;
3936 "lv_kernel_minor", FInt64;
3938 "seg_count", FInt64;
3940 "snap_percent", FOptPercent;
3941 "copy_percent", FOptPercent;
3944 "mirror_log", FString;
3948 (* Names and fields in all structures (in RStruct and RStructList)
3952 (* The old RIntBool return type, only ever used for aug_defnode. Do
3953 * not use this struct in any new code.
3956 "i", FInt32; (* for historical compatibility *)
3957 "b", FInt32; (* for historical compatibility *)
3960 (* LVM PVs, VGs, LVs. *)
3961 "lvm_pv", lvm_pv_cols;
3962 "lvm_vg", lvm_vg_cols;
3963 "lvm_lv", lvm_lv_cols;
3965 (* Column names and types from stat structures.
3966 * NB. Can't use things like 'st_atime' because glibc header files
3967 * define some of these as macros. Ugh.
3998 (* Column names in dirent structure. *)
4001 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4006 (* Version numbers. *)
4014 (* Extended attribute. *)
4016 "attrname", FString;
4020 (* Inotify events. *)
4024 "in_cookie", FUInt32;
4027 ] (* end of structs *)
4029 (* Ugh, Java has to be different ..
4030 * These names are also used by the Haskell bindings.
4032 let java_structs = [
4033 "int_bool", "IntBool";
4038 "statvfs", "StatVFS";
4040 "version", "Version";
4042 "inotify_event", "INotifyEvent";
4045 (* What structs are actually returned. *)
4046 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4048 (* Returns a list of RStruct/RStructList structs that are returned
4049 * by any function. Each element of returned list is a pair:
4051 * (structname, RStructOnly)
4052 * == there exists function which returns RStruct (_, structname)
4053 * (structname, RStructListOnly)
4054 * == there exists function which returns RStructList (_, structname)
4055 * (structname, RStructAndList)
4056 * == there are functions returning both RStruct (_, structname)
4057 * and RStructList (_, structname)
4059 let rstructs_used_by functions =
4060 (* ||| is a "logical OR" for rstructs_used_t *)
4064 | _, RStructAndList -> RStructAndList
4065 | RStructOnly, RStructListOnly
4066 | RStructListOnly, RStructOnly -> RStructAndList
4067 | RStructOnly, RStructOnly -> RStructOnly
4068 | RStructListOnly, RStructListOnly -> RStructListOnly
4071 let h = Hashtbl.create 13 in
4073 (* if elem->oldv exists, update entry using ||| operator,
4074 * else just add elem->newv to the hash
4076 let update elem newv =
4077 try let oldv = Hashtbl.find h elem in
4078 Hashtbl.replace h elem (newv ||| oldv)
4079 with Not_found -> Hashtbl.add h elem newv
4083 fun (_, style, _, _, _, _, _) ->
4084 match fst style with
4085 | RStruct (_, structname) -> update structname RStructOnly
4086 | RStructList (_, structname) -> update structname RStructListOnly
4090 (* return key->values as a list of (key,value) *)
4091 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4093 (* Used for testing language bindings. *)
4095 | CallString of string
4096 | CallOptString of string option
4097 | CallStringList of string list
4099 | CallInt64 of int64
4102 (* Used to memoize the result of pod2text. *)
4103 let pod2text_memo_filename = "src/.pod2text.data"
4104 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4106 let chan = open_in pod2text_memo_filename in
4107 let v = input_value chan in
4111 _ -> Hashtbl.create 13
4112 let pod2text_memo_updated () =
4113 let chan = open_out pod2text_memo_filename in
4114 output_value chan pod2text_memo;
4117 (* Useful functions.
4118 * Note we don't want to use any external OCaml libraries which
4119 * makes this a bit harder than it should be.
4121 let failwithf fs = ksprintf failwith fs
4123 let replace_char s c1 c2 =
4124 let s2 = String.copy s in
4125 let r = ref false in
4126 for i = 0 to String.length s2 - 1 do
4127 if String.unsafe_get s2 i = c1 then (
4128 String.unsafe_set s2 i c2;
4132 if not !r then s else s2
4136 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4138 let triml ?(test = isspace) str =
4140 let n = ref (String.length str) in
4141 while !n > 0 && test str.[!i]; do
4146 else String.sub str !i !n
4148 let trimr ?(test = isspace) str =
4149 let n = ref (String.length str) in
4150 while !n > 0 && test str.[!n-1]; do
4153 if !n = String.length str then str
4154 else String.sub str 0 !n
4156 let trim ?(test = isspace) str =
4157 trimr ~test (triml ~test str)
4159 let rec find s sub =
4160 let len = String.length s in
4161 let sublen = String.length sub in
4163 if i <= len-sublen then (
4165 if j < sublen then (
4166 if s.[i+j] = sub.[j] then loop2 (j+1)
4172 if r = -1 then loop (i+1) else r
4178 let rec replace_str s s1 s2 =
4179 let len = String.length s in
4180 let sublen = String.length s1 in
4181 let i = find s s1 in
4184 let s' = String.sub s 0 i in
4185 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4186 s' ^ s2 ^ replace_str s'' s1 s2
4189 let rec string_split sep str =
4190 let len = String.length str in
4191 let seplen = String.length sep in
4192 let i = find str sep in
4193 if i = -1 then [str]
4195 let s' = String.sub str 0 i in
4196 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4197 s' :: string_split sep s''
4200 let files_equal n1 n2 =
4201 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4202 match Sys.command cmd with
4205 | i -> failwithf "%s: failed with error code %d" cmd i
4207 let rec filter_map f = function
4211 | Some y -> y :: filter_map f xs
4212 | None -> filter_map f xs
4214 let rec find_map f = function
4215 | [] -> raise Not_found
4219 | None -> find_map f xs
4222 let rec loop i = function
4224 | x :: xs -> f i x; loop (i+1) xs
4229 let rec loop i = function
4231 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4235 let name_of_argt = function
4236 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4237 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4238 | FileIn n | FileOut n -> n
4240 let java_name_of_struct typ =
4241 try List.assoc typ java_structs
4244 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4246 let cols_of_struct typ =
4247 try List.assoc typ structs
4249 failwithf "cols_of_struct: unknown struct %s" typ
4251 let seq_of_test = function
4252 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4253 | TestOutputListOfDevices (s, _)
4254 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4255 | TestOutputTrue s | TestOutputFalse s
4256 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4257 | TestOutputStruct (s, _)
4258 | TestLastFail s -> s
4260 (* Handling for function flags. *)
4261 let protocol_limit_warning =
4262 "Because of the message protocol, there is a transfer limit
4263 of somewhere between 2MB and 4MB. To transfer large files you should use
4266 let danger_will_robinson =
4267 "B<This command is dangerous. Without careful use you
4268 can easily destroy all your data>."
4270 let deprecation_notice flags =
4273 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4275 sprintf "This function is deprecated.
4276 In new code, use the C<%s> call instead.
4278 Deprecated functions will not be removed from the API, but the
4279 fact that they are deprecated indicates that there are problems
4280 with correct use of these functions." alt in
4285 (* Check function names etc. for consistency. *)
4286 let check_functions () =
4287 let contains_uppercase str =
4288 let len = String.length str in
4290 if i >= len then false
4293 if c >= 'A' && c <= 'Z' then true
4300 (* Check function names. *)
4302 fun (name, _, _, _, _, _, _) ->
4303 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4304 failwithf "function name %s does not need 'guestfs' prefix" name;
4306 failwithf "function name is empty";
4307 if name.[0] < 'a' || name.[0] > 'z' then
4308 failwithf "function name %s must start with lowercase a-z" name;
4309 if String.contains name '-' then
4310 failwithf "function name %s should not contain '-', use '_' instead."
4314 (* Check function parameter/return names. *)
4316 fun (name, style, _, _, _, _, _) ->
4317 let check_arg_ret_name n =
4318 if contains_uppercase n then
4319 failwithf "%s param/ret %s should not contain uppercase chars"
4321 if String.contains n '-' || String.contains n '_' then
4322 failwithf "%s param/ret %s should not contain '-' or '_'"
4325 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;
4326 if n = "int" || n = "char" || n = "short" || n = "long" then
4327 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4328 if n = "i" || n = "n" then
4329 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4330 if n = "argv" || n = "args" then
4331 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4333 (* List Haskell, OCaml and C keywords here.
4334 * http://www.haskell.org/haskellwiki/Keywords
4335 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4336 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4337 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4338 * |perl -pe 's/(.+)/"$1";/'|fmt -70
4339 * Omitting _-containing words, since they're handled above.
4340 * Omitting the OCaml reserved word, "val", is ok,
4341 * and saves us from renaming several parameters.
4344 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4345 "char"; "class"; "const"; "constraint"; "continue"; "data";
4346 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4347 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4348 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4349 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4350 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4351 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4352 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4353 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4354 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4355 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4356 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4357 "volatile"; "when"; "where"; "while";
4359 if List.mem n reserved then
4360 failwithf "%s has param/ret using reserved word %s" name n;
4363 (match fst style with
4365 | RInt n | RInt64 n | RBool n
4366 | RConstString n | RConstOptString n | RString n
4367 | RStringList n | RStruct (n, _) | RStructList (n, _)
4368 | RHashtable n | RBufferOut n ->
4369 check_arg_ret_name n
4371 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4374 (* Check short descriptions. *)
4376 fun (name, _, _, _, _, shortdesc, _) ->
4377 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4378 failwithf "short description of %s should begin with lowercase." name;
4379 let c = shortdesc.[String.length shortdesc-1] in
4380 if c = '\n' || c = '.' then
4381 failwithf "short description of %s should not end with . or \\n." name
4384 (* Check long dscriptions. *)
4386 fun (name, _, _, _, _, _, longdesc) ->
4387 if longdesc.[String.length longdesc-1] = '\n' then
4388 failwithf "long description of %s should not end with \\n." name
4391 (* Check proc_nrs. *)
4393 fun (name, _, proc_nr, _, _, _, _) ->
4394 if proc_nr <= 0 then
4395 failwithf "daemon function %s should have proc_nr > 0" name
4399 fun (name, _, proc_nr, _, _, _, _) ->
4400 if proc_nr <> -1 then
4401 failwithf "non-daemon function %s should have proc_nr -1" name
4402 ) non_daemon_functions;
4405 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4408 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4409 let rec loop = function
4412 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4414 | (name1,nr1) :: (name2,nr2) :: _ ->
4415 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4423 (* Ignore functions that have no tests. We generate a
4424 * warning when the user does 'make check' instead.
4426 | name, _, _, _, [], _, _ -> ()
4427 | name, _, _, _, tests, _, _ ->
4431 match seq_of_test test with
4433 failwithf "%s has a test containing an empty sequence" name
4434 | cmds -> List.map List.hd cmds
4436 let funcs = List.flatten funcs in
4438 let tested = List.mem name funcs in
4441 failwithf "function %s has tests but does not test itself" name
4444 (* 'pr' prints to the current output file. *)
4445 let chan = ref stdout
4446 let pr fs = ksprintf (output_string !chan) fs
4448 (* Generate a header block in a number of standard styles. *)
4449 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4450 type license = GPLv2 | LGPLv2
4452 let generate_header comment license =
4453 let c = match comment with
4454 | CStyle -> pr "/* "; " *"
4455 | HashStyle -> pr "# "; "#"
4456 | OCamlStyle -> pr "(* "; " *"
4457 | HaskellStyle -> pr "{- "; " " in
4458 pr "libguestfs generated file\n";
4459 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4460 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4462 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4466 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4467 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4468 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4469 pr "%s (at your option) any later version.\n" c;
4471 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4472 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4473 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4474 pr "%s GNU General Public License for more details.\n" c;
4476 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4477 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4478 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4481 pr "%s This library is free software; you can redistribute it and/or\n" c;
4482 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4483 pr "%s License as published by the Free Software Foundation; either\n" c;
4484 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4486 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4487 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4488 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4489 pr "%s Lesser General Public License for more details.\n" c;
4491 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4492 pr "%s License along with this library; if not, write to the Free Software\n" c;
4493 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4496 | CStyle -> pr " */\n"
4498 | OCamlStyle -> pr " *)\n"
4499 | HaskellStyle -> pr "-}\n"
4503 (* Start of main code generation functions below this line. *)
4505 (* Generate the pod documentation for the C API. *)
4506 let rec generate_actions_pod () =
4508 fun (shortname, style, _, flags, _, _, longdesc) ->
4509 if not (List.mem NotInDocs flags) then (
4510 let name = "guestfs_" ^ shortname in
4511 pr "=head2 %s\n\n" name;
4513 generate_prototype ~extern:false ~handle:"handle" name style;
4515 pr "%s\n\n" longdesc;
4516 (match fst style with
4518 pr "This function returns 0 on success or -1 on error.\n\n"
4520 pr "On error this function returns -1.\n\n"
4522 pr "On error this function returns -1.\n\n"
4524 pr "This function returns a C truth value on success or -1 on error.\n\n"
4526 pr "This function returns a string, or NULL on error.
4527 The string is owned by the guest handle and must I<not> be freed.\n\n"
4528 | RConstOptString _ ->
4529 pr "This function returns a string which may be NULL.
4530 There is way to return an error from this function.
4531 The string is owned by the guest handle and must I<not> be freed.\n\n"
4533 pr "This function returns a string, or NULL on error.
4534 I<The caller must free the returned string after use>.\n\n"
4536 pr "This function returns a NULL-terminated array of strings
4537 (like L<environ(3)>), or NULL if there was an error.
4538 I<The caller must free the strings and the array after use>.\n\n"
4539 | RStruct (_, typ) ->
4540 pr "This function returns a C<struct guestfs_%s *>,
4541 or NULL if there was an error.
4542 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4543 | RStructList (_, typ) ->
4544 pr "This function returns a C<struct guestfs_%s_list *>
4545 (see E<lt>guestfs-structs.hE<gt>),
4546 or NULL if there was an error.
4547 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4549 pr "This function returns a NULL-terminated array of
4550 strings, or NULL if there was an error.
4551 The array of strings will always have length C<2n+1>, where
4552 C<n> keys and values alternate, followed by the trailing NULL entry.
4553 I<The caller must free the strings and the array after use>.\n\n"
4555 pr "This function returns a buffer, or NULL on error.
4556 The size of the returned buffer is written to C<*size_r>.
4557 I<The caller must free the returned buffer after use>.\n\n"
4559 if List.mem ProtocolLimitWarning flags then
4560 pr "%s\n\n" protocol_limit_warning;
4561 if List.mem DangerWillRobinson flags then
4562 pr "%s\n\n" danger_will_robinson;
4563 match deprecation_notice flags with
4565 | Some txt -> pr "%s\n\n" txt
4567 ) all_functions_sorted
4569 and generate_structs_pod () =
4570 (* Structs documentation. *)
4573 pr "=head2 guestfs_%s\n" typ;
4575 pr " struct guestfs_%s {\n" typ;
4578 | name, FChar -> pr " char %s;\n" name
4579 | name, FUInt32 -> pr " uint32_t %s;\n" name
4580 | name, FInt32 -> pr " int32_t %s;\n" name
4581 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4582 | name, FInt64 -> pr " int64_t %s;\n" name
4583 | name, FString -> pr " char *%s;\n" name
4585 pr " /* The next two fields describe a byte array. */\n";
4586 pr " uint32_t %s_len;\n" name;
4587 pr " char *%s;\n" name
4589 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4590 pr " char %s[32];\n" name
4591 | name, FOptPercent ->
4592 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4593 pr " float %s;\n" name
4597 pr " struct guestfs_%s_list {\n" typ;
4598 pr " uint32_t len; /* Number of elements in list. */\n";
4599 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4602 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4603 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4608 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4609 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4611 * We have to use an underscore instead of a dash because otherwise
4612 * rpcgen generates incorrect code.
4614 * This header is NOT exported to clients, but see also generate_structs_h.
4616 and generate_xdr () =
4617 generate_header CStyle LGPLv2;
4619 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4620 pr "typedef string str<>;\n";
4623 (* Internal structures. *)
4627 pr "struct guestfs_int_%s {\n" typ;
4629 | name, FChar -> pr " char %s;\n" name
4630 | name, FString -> pr " string %s<>;\n" name
4631 | name, FBuffer -> pr " opaque %s<>;\n" name
4632 | name, FUUID -> pr " opaque %s[32];\n" name
4633 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4634 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4635 | name, FOptPercent -> pr " float %s;\n" name
4639 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4644 fun (shortname, style, _, _, _, _, _) ->
4645 let name = "guestfs_" ^ shortname in
4647 (match snd style with
4650 pr "struct %s_args {\n" name;
4653 | Pathname n | Device n | Dev_or_Path n | String n ->
4654 pr " string %s<>;\n" n
4655 | OptString n -> pr " str *%s;\n" n
4656 | StringList n | DeviceList n -> pr " str %s<>;\n" n
4657 | Bool n -> pr " bool %s;\n" n
4658 | Int n -> pr " int %s;\n" n
4659 | Int64 n -> pr " hyper %s;\n" n
4660 | FileIn _ | FileOut _ -> ()
4664 (match fst style with
4667 pr "struct %s_ret {\n" name;
4671 pr "struct %s_ret {\n" name;
4672 pr " hyper %s;\n" n;
4675 pr "struct %s_ret {\n" name;
4678 | RConstString _ | RConstOptString _ ->
4679 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4681 pr "struct %s_ret {\n" name;
4682 pr " string %s<>;\n" n;
4685 pr "struct %s_ret {\n" name;
4686 pr " str %s<>;\n" n;
4688 | RStruct (n, typ) ->
4689 pr "struct %s_ret {\n" name;
4690 pr " guestfs_int_%s %s;\n" typ n;
4692 | RStructList (n, typ) ->
4693 pr "struct %s_ret {\n" name;
4694 pr " guestfs_int_%s_list %s;\n" typ n;
4697 pr "struct %s_ret {\n" name;
4698 pr " str %s<>;\n" n;
4701 pr "struct %s_ret {\n" name;
4702 pr " opaque %s<>;\n" n;
4707 (* Table of procedure numbers. *)
4708 pr "enum guestfs_procedure {\n";
4710 fun (shortname, _, proc_nr, _, _, _, _) ->
4711 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4713 pr " GUESTFS_PROC_NR_PROCS\n";
4717 (* Having to choose a maximum message size is annoying for several
4718 * reasons (it limits what we can do in the API), but it (a) makes
4719 * the protocol a lot simpler, and (b) provides a bound on the size
4720 * of the daemon which operates in limited memory space. For large
4721 * file transfers you should use FTP.
4723 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4726 (* Message header, etc. *)
4728 /* The communication protocol is now documented in the guestfs(3)
4732 const GUESTFS_PROGRAM = 0x2000F5F5;
4733 const GUESTFS_PROTOCOL_VERSION = 1;
4735 /* These constants must be larger than any possible message length. */
4736 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4737 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4739 enum guestfs_message_direction {
4740 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4741 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4744 enum guestfs_message_status {
4745 GUESTFS_STATUS_OK = 0,
4746 GUESTFS_STATUS_ERROR = 1
4749 const GUESTFS_ERROR_LEN = 256;
4751 struct guestfs_message_error {
4752 string error_message<GUESTFS_ERROR_LEN>;
4755 struct guestfs_message_header {
4756 unsigned prog; /* GUESTFS_PROGRAM */
4757 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4758 guestfs_procedure proc; /* GUESTFS_PROC_x */
4759 guestfs_message_direction direction;
4760 unsigned serial; /* message serial number */
4761 guestfs_message_status status;
4764 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4766 struct guestfs_chunk {
4767 int cancel; /* if non-zero, transfer is cancelled */
4768 /* data size is 0 bytes if the transfer has finished successfully */
4769 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4773 (* Generate the guestfs-structs.h file. *)
4774 and generate_structs_h () =
4775 generate_header CStyle LGPLv2;
4777 (* This is a public exported header file containing various
4778 * structures. The structures are carefully written to have
4779 * exactly the same in-memory format as the XDR structures that
4780 * we use on the wire to the daemon. The reason for creating
4781 * copies of these structures here is just so we don't have to
4782 * export the whole of guestfs_protocol.h (which includes much
4783 * unrelated and XDR-dependent stuff that we don't want to be
4784 * public, or required by clients).
4786 * To reiterate, we will pass these structures to and from the
4787 * client with a simple assignment or memcpy, so the format
4788 * must be identical to what rpcgen / the RFC defines.
4791 (* Public structures. *)
4794 pr "struct guestfs_%s {\n" typ;
4797 | name, FChar -> pr " char %s;\n" name
4798 | name, FString -> pr " char *%s;\n" name
4800 pr " uint32_t %s_len;\n" name;
4801 pr " char *%s;\n" name
4802 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4803 | name, FUInt32 -> pr " uint32_t %s;\n" name
4804 | name, FInt32 -> pr " int32_t %s;\n" name
4805 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4806 | name, FInt64 -> pr " int64_t %s;\n" name
4807 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4811 pr "struct guestfs_%s_list {\n" typ;
4812 pr " uint32_t len;\n";
4813 pr " struct guestfs_%s *val;\n" typ;
4816 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4817 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4821 (* Generate the guestfs-actions.h file. *)
4822 and generate_actions_h () =
4823 generate_header CStyle LGPLv2;
4825 fun (shortname, style, _, _, _, _, _) ->
4826 let name = "guestfs_" ^ shortname in
4827 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4831 (* Generate the guestfs-internal-actions.h file. *)
4832 and generate_internal_actions_h () =
4833 generate_header CStyle LGPLv2;
4835 fun (shortname, style, _, _, _, _, _) ->
4836 let name = "guestfs__" ^ shortname in
4837 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4839 ) non_daemon_functions
4841 (* Generate the client-side dispatch stubs. *)
4842 and generate_client_actions () =
4843 generate_header CStyle LGPLv2;
4849 #include <inttypes.h>
4851 #include \"guestfs.h\"
4852 #include \"guestfs-internal-actions.h\"
4853 #include \"guestfs_protocol.h\"
4855 #define error guestfs_error
4856 //#define perrorf guestfs_perrorf
4857 //#define safe_malloc guestfs_safe_malloc
4858 #define safe_realloc guestfs_safe_realloc
4859 //#define safe_strdup guestfs_safe_strdup
4860 #define safe_memdup guestfs_safe_memdup
4862 /* Check the return message from a call for validity. */
4864 check_reply_header (guestfs_h *g,
4865 const struct guestfs_message_header *hdr,
4866 unsigned int proc_nr, unsigned int serial)
4868 if (hdr->prog != GUESTFS_PROGRAM) {
4869 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4872 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4873 error (g, \"wrong protocol version (%%d/%%d)\",
4874 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4877 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4878 error (g, \"unexpected message direction (%%d/%%d)\",
4879 hdr->direction, GUESTFS_DIRECTION_REPLY);
4882 if (hdr->proc != proc_nr) {
4883 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4886 if (hdr->serial != serial) {
4887 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4894 /* Check we are in the right state to run a high-level action. */
4896 check_state (guestfs_h *g, const char *caller)
4898 if (!guestfs__is_ready (g)) {
4899 if (guestfs__is_config (g) || guestfs__is_launching (g))
4900 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4903 error (g, \"%%s called from the wrong state, %%d != READY\",
4904 caller, guestfs__get_state (g));
4912 (* Generate code to generate guestfish call traces. *)
4913 let trace_call shortname style =
4914 pr " if (guestfs__get_trace (g)) {\n";
4917 List.exists (function
4918 | StringList _ | DeviceList _ -> true
4919 | _ -> false) (snd style) in
4925 pr " printf (\"%s\");\n" shortname;
4928 | String n (* strings *)
4934 (* guestfish doesn't support string escaping, so neither do we *)
4935 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
4936 | OptString n -> (* string option *)
4937 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4938 pr " else printf (\" null\");\n"
4940 | DeviceList n -> (* string list *)
4941 pr " putchar (' ');\n";
4942 pr " putchar ('\"');\n";
4943 pr " for (i = 0; %s[i]; ++i) {\n" n;
4944 pr " if (i > 0) putchar (' ');\n";
4945 pr " fputs (%s[i], stdout);\n" n;
4947 pr " putchar ('\"');\n";
4948 | Bool n -> (* boolean *)
4949 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
4950 | Int n -> (* int *)
4951 pr " printf (\" %%d\", %s);\n" n
4953 pr " printf (\" %%\" PRIi64, %s);\n" n
4955 pr " putchar ('\\n');\n";
4960 (* For non-daemon functions, generate a wrapper around each function. *)
4962 fun (shortname, style, _, _, _, _, _) ->
4963 let name = "guestfs_" ^ shortname in
4965 generate_prototype ~extern:false ~semicolon:false ~newline:true
4966 ~handle:"g" name style;
4968 trace_call shortname style;
4969 pr " return guestfs__%s " shortname;
4970 generate_c_call_args ~handle:"g" style;
4974 ) non_daemon_functions;
4976 (* Client-side stubs for each function. *)
4978 fun (shortname, style, _, _, _, _, _) ->
4979 let name = "guestfs_" ^ shortname in
4981 (* Generate the action stub. *)
4982 generate_prototype ~extern:false ~semicolon:false ~newline:true
4983 ~handle:"g" name style;
4986 match fst style with
4987 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4988 | RConstString _ | RConstOptString _ ->
4989 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4990 | RString _ | RStringList _
4991 | RStruct _ | RStructList _
4992 | RHashtable _ | RBufferOut _ ->
4997 (match snd style with
4999 | _ -> pr " struct %s_args args;\n" name
5002 pr " guestfs_message_header hdr;\n";
5003 pr " guestfs_message_error err;\n";
5005 match fst style with
5007 | RConstString _ | RConstOptString _ ->
5008 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5010 | RBool _ | RString _ | RStringList _
5011 | RStruct _ | RStructList _
5012 | RHashtable _ | RBufferOut _ ->
5013 pr " struct %s_ret ret;\n" name;
5016 pr " int serial;\n";
5019 trace_call shortname style;
5020 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5021 pr " guestfs___set_busy (g);\n";
5024 (* Send the main header and arguments. *)
5025 (match snd style with
5027 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5028 (String.uppercase shortname)
5032 | Pathname n | Device n | Dev_or_Path n | String n ->
5033 pr " args.%s = (char *) %s;\n" n n
5035 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5036 | StringList n | DeviceList n ->
5037 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5038 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5040 pr " args.%s = %s;\n" n n
5042 pr " args.%s = %s;\n" n n
5044 pr " args.%s = %s;\n" n n
5045 | FileIn _ | FileOut _ -> ()
5047 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5048 (String.uppercase shortname);
5049 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5052 pr " if (serial == -1) {\n";
5053 pr " guestfs___end_busy (g);\n";
5054 pr " return %s;\n" error_code;
5058 (* Send any additional files (FileIn) requested. *)
5059 let need_read_reply_label = ref false in
5063 pr " r = guestfs___send_file (g, %s);\n" n;
5064 pr " if (r == -1) {\n";
5065 pr " guestfs___end_busy (g);\n";
5066 pr " return %s;\n" error_code;
5068 pr " if (r == -2) /* daemon cancelled */\n";
5069 pr " goto read_reply;\n";
5070 need_read_reply_label := true;
5075 (* Wait for the reply from the remote end. *)
5076 if !need_read_reply_label then pr " read_reply:\n";
5077 pr " memset (&hdr, 0, sizeof hdr);\n";
5078 pr " memset (&err, 0, sizeof err);\n";
5079 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5081 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5085 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5088 pr " if (r == -1) {\n";
5089 pr " guestfs___end_busy (g);\n";
5090 pr " return %s;\n" error_code;
5094 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5095 (String.uppercase shortname);
5096 pr " guestfs___end_busy (g);\n";
5097 pr " return %s;\n" error_code;
5101 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5102 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5103 pr " free (err.error_message);\n";
5104 pr " guestfs___end_busy (g);\n";
5105 pr " return %s;\n" error_code;
5109 (* Expecting to receive further files (FileOut)? *)
5113 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5114 pr " guestfs___end_busy (g);\n";
5115 pr " return %s;\n" error_code;
5121 pr " guestfs___end_busy (g);\n";
5123 (match fst style with
5124 | RErr -> pr " return 0;\n"
5125 | RInt n | RInt64 n | RBool n ->
5126 pr " return ret.%s;\n" n
5127 | RConstString _ | RConstOptString _ ->
5128 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5130 pr " return ret.%s; /* caller will free */\n" n
5131 | RStringList n | RHashtable n ->
5132 pr " /* caller will free this, but we need to add a NULL entry */\n";
5133 pr " ret.%s.%s_val =\n" n n;
5134 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5135 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5137 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5138 pr " return ret.%s.%s_val;\n" n n
5140 pr " /* caller will free this */\n";
5141 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5142 | RStructList (n, _) ->
5143 pr " /* caller will free this */\n";
5144 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5146 pr " *size_r = ret.%s.%s_len;\n" n n;
5147 pr " return ret.%s.%s_val; /* caller will free */\n" n n
5153 (* Functions to free structures. *)
5154 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5155 pr " * structure format is identical to the XDR format. See note in\n";
5156 pr " * generator.ml.\n";
5163 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5165 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5171 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5173 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5180 (* Generate daemon/actions.h. *)
5181 and generate_daemon_actions_h () =
5182 generate_header CStyle GPLv2;
5184 pr "#include \"../src/guestfs_protocol.h\"\n";
5188 fun (name, style, _, _, _, _, _) ->
5190 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5194 (* Generate the server-side stubs. *)
5195 and generate_daemon_actions () =
5196 generate_header CStyle GPLv2;
5198 pr "#include <config.h>\n";
5200 pr "#include <stdio.h>\n";
5201 pr "#include <stdlib.h>\n";
5202 pr "#include <string.h>\n";
5203 pr "#include <inttypes.h>\n";
5204 pr "#include <rpc/types.h>\n";
5205 pr "#include <rpc/xdr.h>\n";
5207 pr "#include \"daemon.h\"\n";
5208 pr "#include \"c-ctype.h\"\n";
5209 pr "#include \"../src/guestfs_protocol.h\"\n";
5210 pr "#include \"actions.h\"\n";
5214 fun (name, style, _, _, _, _, _) ->
5215 (* Generate server-side stubs. *)
5216 pr "static void %s_stub (XDR *xdr_in)\n" name;
5219 match fst style with
5220 | RErr | RInt _ -> pr " int r;\n"; "-1"
5221 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5222 | RBool _ -> pr " int r;\n"; "-1"
5223 | RConstString _ | RConstOptString _ ->
5224 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5225 | RString _ -> pr " char *r;\n"; "NULL"
5226 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5227 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5228 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5230 pr " size_t size;\n";
5234 (match snd style with
5237 pr " struct guestfs_%s_args args;\n" name;
5240 | Device n | Dev_or_Path n
5243 | OptString n -> pr " char *%s;\n" n
5244 | StringList n | DeviceList n -> pr " char **%s;\n" n
5245 | Bool n -> pr " int %s;\n" n
5246 | Int n -> pr " int %s;\n" n
5247 | Int64 n -> pr " int64_t %s;\n" n
5248 | FileIn _ | FileOut _ -> ()
5253 (match snd style with
5256 pr " memset (&args, 0, sizeof args);\n";
5258 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5259 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5263 pr " char *%s = args.%s;\n" n n
5265 let pr_list_handling_code n =
5266 pr " %s = realloc (args.%s.%s_val,\n" n n n;
5267 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5268 pr " if (%s == NULL) {\n" n;
5269 pr " reply_with_perror (\"realloc\");\n";
5272 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
5273 pr " args.%s.%s_val = %s;\n" n n n;
5279 pr " ABS_PATH (%s, goto done);\n" n;
5282 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
5285 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5286 | String n -> pr_args n
5287 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
5289 pr_list_handling_code n;
5291 pr_list_handling_code n;
5292 pr " /* Ensure that each is a device,\n";
5293 pr " * and perform device name translation. */\n";
5294 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5295 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5297 | Bool n -> pr " %s = args.%s;\n" n n
5298 | Int n -> pr " %s = args.%s;\n" n n
5299 | Int64 n -> pr " %s = args.%s;\n" n n
5300 | FileIn _ | FileOut _ -> ()
5306 (* this is used at least for do_equal *)
5307 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5308 (* Emit NEED_ROOT just once, even when there are two or
5309 more Pathname args *)
5310 pr " NEED_ROOT (goto done);\n";
5313 (* Don't want to call the impl with any FileIn or FileOut
5314 * parameters, since these go "outside" the RPC protocol.
5317 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5319 pr " r = do_%s " name;
5320 generate_c_call_args (fst style, args');
5323 pr " if (r == %s)\n" error_code;
5324 pr " /* do_%s has already called reply_with_error */\n" name;
5328 (* If there are any FileOut parameters, then the impl must
5329 * send its own reply.
5332 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5334 pr " /* do_%s has already sent a reply */\n" name
5336 match fst style with
5337 | RErr -> pr " reply (NULL, NULL);\n"
5338 | RInt n | RInt64 n | RBool n ->
5339 pr " struct guestfs_%s_ret ret;\n" name;
5340 pr " ret.%s = r;\n" n;
5341 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5343 | RConstString _ | RConstOptString _ ->
5344 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5346 pr " struct guestfs_%s_ret ret;\n" name;
5347 pr " ret.%s = r;\n" n;
5348 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5351 | RStringList n | RHashtable n ->
5352 pr " struct guestfs_%s_ret ret;\n" name;
5353 pr " ret.%s.%s_len = count_strings (r);\n" n n;
5354 pr " ret.%s.%s_val = r;\n" n n;
5355 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5357 pr " free_strings (r);\n"
5359 pr " struct guestfs_%s_ret ret;\n" name;
5360 pr " ret.%s = *r;\n" n;
5361 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5363 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5365 | RStructList (n, _) ->
5366 pr " struct guestfs_%s_ret ret;\n" name;
5367 pr " ret.%s = *r;\n" n;
5368 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5370 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5373 pr " struct guestfs_%s_ret ret;\n" name;
5374 pr " ret.%s.%s_val = r;\n" n n;
5375 pr " ret.%s.%s_len = size;\n" n n;
5376 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5381 (* Free the args. *)
5382 (match snd style with
5387 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5394 (* Dispatch function. *)
5395 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5397 pr " switch (proc_nr) {\n";
5400 fun (name, style, _, _, _, _, _) ->
5401 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5402 pr " %s_stub (xdr_in);\n" name;
5407 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";
5412 (* LVM columns and tokenization functions. *)
5413 (* XXX This generates crap code. We should rethink how we
5419 pr "static const char *lvm_%s_cols = \"%s\";\n"
5420 typ (String.concat "," (List.map fst cols));
5423 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5425 pr " char *tok, *p, *next;\n";
5429 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5432 pr " if (!str) {\n";
5433 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5436 pr " if (!*str || c_isspace (*str)) {\n";
5437 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5442 fun (name, coltype) ->
5443 pr " if (!tok) {\n";
5444 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5447 pr " p = strchrnul (tok, ',');\n";
5448 pr " if (*p) next = p+1; else next = NULL;\n";
5449 pr " *p = '\\0';\n";
5452 pr " r->%s = strdup (tok);\n" name;
5453 pr " if (r->%s == NULL) {\n" name;
5454 pr " perror (\"strdup\");\n";
5458 pr " for (i = j = 0; i < 32; ++j) {\n";
5459 pr " if (tok[j] == '\\0') {\n";
5460 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5462 pr " } else if (tok[j] != '-')\n";
5463 pr " r->%s[i++] = tok[j];\n" name;
5466 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5467 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5471 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5472 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5476 pr " if (tok[0] == '\\0')\n";
5477 pr " r->%s = -1;\n" name;
5478 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5479 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5482 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5483 assert false (* can never be an LVM column *)
5485 pr " tok = next;\n";
5488 pr " if (tok != NULL) {\n";
5489 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5496 pr "guestfs_int_lvm_%s_list *\n" typ;
5497 pr "parse_command_line_%ss (void)\n" typ;
5499 pr " char *out, *err;\n";
5500 pr " char *p, *pend;\n";
5502 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
5503 pr " void *newp;\n";
5505 pr " ret = malloc (sizeof *ret);\n";
5506 pr " if (!ret) {\n";
5507 pr " reply_with_perror (\"malloc\");\n";
5508 pr " return NULL;\n";
5511 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5512 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5514 pr " r = command (&out, &err,\n";
5515 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
5516 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5517 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5518 pr " if (r == -1) {\n";
5519 pr " reply_with_error (\"%%s\", err);\n";
5520 pr " free (out);\n";
5521 pr " free (err);\n";
5522 pr " free (ret);\n";
5523 pr " return NULL;\n";
5526 pr " free (err);\n";
5528 pr " /* Tokenize each line of the output. */\n";
5531 pr " while (p) {\n";
5532 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
5533 pr " if (pend) {\n";
5534 pr " *pend = '\\0';\n";
5538 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
5541 pr " if (!*p) { /* Empty line? Skip it. */\n";
5546 pr " /* Allocate some space to store this next entry. */\n";
5547 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5548 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5549 pr " if (newp == NULL) {\n";
5550 pr " reply_with_perror (\"realloc\");\n";
5551 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5552 pr " free (ret);\n";
5553 pr " free (out);\n";
5554 pr " return NULL;\n";
5556 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5558 pr " /* Tokenize the next entry. */\n";
5559 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5560 pr " if (r == -1) {\n";
5561 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5562 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5563 pr " free (ret);\n";
5564 pr " free (out);\n";
5565 pr " return NULL;\n";
5572 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5574 pr " free (out);\n";
5575 pr " return ret;\n";
5578 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5580 (* Generate a list of function names, for debugging in the daemon.. *)
5581 and generate_daemon_names () =
5582 generate_header CStyle GPLv2;
5584 pr "#include <config.h>\n";
5586 pr "#include \"daemon.h\"\n";
5589 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5590 pr "const char *function_names[] = {\n";
5592 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5596 (* Generate the tests. *)
5597 and generate_tests () =
5598 generate_header CStyle GPLv2;
5605 #include <sys/types.h>
5608 #include \"guestfs.h\"
5610 static guestfs_h *g;
5611 static int suppress_error = 0;
5613 static void print_error (guestfs_h *g, void *data, const char *msg)
5615 if (!suppress_error)
5616 fprintf (stderr, \"%%s\\n\", msg);
5619 /* FIXME: nearly identical code appears in fish.c */
5620 static void print_strings (char *const *argv)
5624 for (argc = 0; argv[argc] != NULL; ++argc)
5625 printf (\"\\t%%s\\n\", argv[argc]);
5629 static void print_table (char const *const *argv)
5633 for (i = 0; argv[i] != NULL; i += 2)
5634 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5640 (* Generate a list of commands which are not tested anywhere. *)
5641 pr "static void no_test_warnings (void)\n";
5644 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5646 fun (_, _, _, _, tests, _, _) ->
5647 let tests = filter_map (
5649 | (_, (Always|If _|Unless _), test) -> Some test
5650 | (_, Disabled, _) -> None
5652 let seq = List.concat (List.map seq_of_test tests) in
5653 let cmds_tested = List.map List.hd seq in
5654 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5658 fun (name, _, _, _, _, _, _) ->
5659 if not (Hashtbl.mem hash name) then
5660 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5666 (* Generate the actual tests. Note that we generate the tests
5667 * in reverse order, deliberately, so that (in general) the
5668 * newest tests run first. This makes it quicker and easier to
5673 fun (name, _, _, _, tests, _, _) ->
5674 mapi (generate_one_test name) tests
5675 ) (List.rev all_functions) in
5676 let test_names = List.concat test_names in
5677 let nr_tests = List.length test_names in
5680 int main (int argc, char *argv[])
5683 unsigned long int n_failed = 0;
5684 const char *filename;
5686 int nr_tests, test_num = 0;
5688 setbuf (stdout, NULL);
5690 no_test_warnings ();
5692 g = guestfs_create ();
5694 printf (\"guestfs_create FAILED\\n\");
5698 guestfs_set_error_handler (g, print_error, NULL);
5700 guestfs_set_path (g, \"../appliance\");
5702 filename = \"test1.img\";
5703 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5708 if (lseek (fd, %d, SEEK_SET) == -1) {
5714 if (write (fd, &c, 1) == -1) {
5720 if (close (fd) == -1) {
5725 if (guestfs_add_drive (g, filename) == -1) {
5726 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5730 filename = \"test2.img\";
5731 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5736 if (lseek (fd, %d, SEEK_SET) == -1) {
5742 if (write (fd, &c, 1) == -1) {
5748 if (close (fd) == -1) {
5753 if (guestfs_add_drive (g, filename) == -1) {
5754 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5758 filename = \"test3.img\";
5759 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5764 if (lseek (fd, %d, SEEK_SET) == -1) {
5770 if (write (fd, &c, 1) == -1) {
5776 if (close (fd) == -1) {
5781 if (guestfs_add_drive (g, filename) == -1) {
5782 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5786 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5787 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5791 if (guestfs_launch (g) == -1) {
5792 printf (\"guestfs_launch FAILED\\n\");
5796 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5799 /* Cancel previous alarm. */
5804 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5808 pr " test_num++;\n";
5809 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5810 pr " if (%s () == -1) {\n" test_name;
5811 pr " printf (\"%s FAILED\\n\");\n" test_name;
5812 pr " n_failed++;\n";
5817 pr " guestfs_close (g);\n";
5818 pr " unlink (\"test1.img\");\n";
5819 pr " unlink (\"test2.img\");\n";
5820 pr " unlink (\"test3.img\");\n";
5823 pr " if (n_failed > 0) {\n";
5824 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5832 and generate_one_test name i (init, prereq, test) =
5833 let test_name = sprintf "test_%s_%d" name i in
5836 static int %s_skip (void)
5840 str = getenv (\"TEST_ONLY\");
5842 return strstr (str, \"%s\") == NULL;
5843 str = getenv (\"SKIP_%s\");
5844 if (str && strcmp (str, \"1\") == 0) return 1;
5845 str = getenv (\"SKIP_TEST_%s\");
5846 if (str && strcmp (str, \"1\") == 0) return 1;
5850 " test_name name (String.uppercase test_name) (String.uppercase name);
5853 | Disabled | Always -> ()
5854 | If code | Unless code ->
5855 pr "static int %s_prereq (void)\n" test_name;
5863 static int %s (void)
5866 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5870 " test_name test_name test_name;
5874 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5876 pr " if (! %s_prereq ()) {\n" test_name;
5877 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5881 generate_one_test_body name i test_name init test;
5883 pr " if (%s_prereq ()) {\n" test_name;
5884 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5888 generate_one_test_body name i test_name init test;
5890 generate_one_test_body name i test_name init test
5898 and generate_one_test_body name i test_name init test =
5900 | InitNone (* XXX at some point, InitNone and InitEmpty became
5901 * folded together as the same thing. Really we should
5902 * make InitNone do nothing at all, but the tests may
5903 * need to be checked to make sure this is OK.
5906 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5907 List.iter (generate_test_command_call test_name)
5908 [["blockdev_setrw"; "/dev/sda"];
5912 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5913 List.iter (generate_test_command_call test_name)
5914 [["blockdev_setrw"; "/dev/sda"];
5917 ["sfdiskM"; "/dev/sda"; ","]]
5919 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5920 List.iter (generate_test_command_call test_name)
5921 [["blockdev_setrw"; "/dev/sda"];
5924 ["sfdiskM"; "/dev/sda"; ","];
5925 ["mkfs"; "ext2"; "/dev/sda1"];
5926 ["mount"; "/dev/sda1"; "/"]]
5927 | InitBasicFSonLVM ->
5928 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5930 List.iter (generate_test_command_call test_name)
5931 [["blockdev_setrw"; "/dev/sda"];
5934 ["sfdiskM"; "/dev/sda"; ","];
5935 ["pvcreate"; "/dev/sda1"];
5936 ["vgcreate"; "VG"; "/dev/sda1"];
5937 ["lvcreate"; "LV"; "VG"; "8"];
5938 ["mkfs"; "ext2"; "/dev/VG/LV"];
5939 ["mount"; "/dev/VG/LV"; "/"]]
5941 pr " /* InitISOFS for %s */\n" test_name;
5942 List.iter (generate_test_command_call test_name)
5943 [["blockdev_setrw"; "/dev/sda"];
5946 ["mount_ro"; "/dev/sdd"; "/"]]
5949 let get_seq_last = function
5951 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5954 let seq = List.rev seq in
5955 List.rev (List.tl seq), List.hd seq
5960 pr " /* TestRun for %s (%d) */\n" name i;
5961 List.iter (generate_test_command_call test_name) seq
5962 | TestOutput (seq, expected) ->
5963 pr " /* TestOutput for %s (%d) */\n" name i;
5964 pr " const char *expected = \"%s\";\n" (c_quote expected);
5965 let seq, last = get_seq_last seq in
5967 pr " if (strcmp (r, expected) != 0) {\n";
5968 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5972 List.iter (generate_test_command_call test_name) seq;
5973 generate_test_command_call ~test test_name last
5974 | TestOutputList (seq, expected) ->
5975 pr " /* TestOutputList for %s (%d) */\n" name i;
5976 let seq, last = get_seq_last seq in
5980 pr " if (!r[%d]) {\n" i;
5981 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5982 pr " print_strings (r);\n";
5986 pr " const char *expected = \"%s\";\n" (c_quote str);
5987 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5988 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5993 pr " if (r[%d] != NULL) {\n" (List.length expected);
5994 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5996 pr " print_strings (r);\n";
6000 List.iter (generate_test_command_call test_name) seq;
6001 generate_test_command_call ~test test_name last
6002 | TestOutputListOfDevices (seq, expected) ->
6003 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6004 let seq, last = get_seq_last seq in
6008 pr " if (!r[%d]) {\n" i;
6009 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6010 pr " print_strings (r);\n";
6014 pr " const char *expected = \"%s\";\n" (c_quote str);
6015 pr " r[%d][5] = 's';\n" i;
6016 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
6017 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6022 pr " if (r[%d] != NULL) {\n" (List.length expected);
6023 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6025 pr " print_strings (r);\n";
6029 List.iter (generate_test_command_call test_name) seq;
6030 generate_test_command_call ~test test_name last
6031 | TestOutputInt (seq, expected) ->
6032 pr " /* TestOutputInt for %s (%d) */\n" name i;
6033 let seq, last = get_seq_last seq in
6035 pr " if (r != %d) {\n" expected;
6036 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6042 List.iter (generate_test_command_call test_name) seq;
6043 generate_test_command_call ~test test_name last
6044 | TestOutputIntOp (seq, op, expected) ->
6045 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6046 let seq, last = get_seq_last seq in
6048 pr " if (! (r %s %d)) {\n" op expected;
6049 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6050 test_name op expected;
6055 List.iter (generate_test_command_call test_name) seq;
6056 generate_test_command_call ~test test_name last
6057 | TestOutputTrue seq ->
6058 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6059 let seq, last = get_seq_last seq in
6062 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6067 List.iter (generate_test_command_call test_name) seq;
6068 generate_test_command_call ~test test_name last
6069 | TestOutputFalse seq ->
6070 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6071 let seq, last = get_seq_last seq in
6074 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6079 List.iter (generate_test_command_call test_name) seq;
6080 generate_test_command_call ~test test_name last
6081 | TestOutputLength (seq, expected) ->
6082 pr " /* TestOutputLength for %s (%d) */\n" name i;
6083 let seq, last = get_seq_last seq in
6086 pr " for (j = 0; j < %d; ++j)\n" expected;
6087 pr " if (r[j] == NULL) {\n";
6088 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6090 pr " print_strings (r);\n";
6093 pr " if (r[j] != NULL) {\n";
6094 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6096 pr " print_strings (r);\n";
6100 List.iter (generate_test_command_call test_name) seq;
6101 generate_test_command_call ~test test_name last
6102 | TestOutputBuffer (seq, expected) ->
6103 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6104 pr " const char *expected = \"%s\";\n" (c_quote expected);
6105 let seq, last = get_seq_last seq in
6106 let len = String.length expected in
6108 pr " if (size != %d) {\n" len;
6109 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6112 pr " if (strncmp (r, expected, size) != 0) {\n";
6113 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6117 List.iter (generate_test_command_call test_name) seq;
6118 generate_test_command_call ~test test_name last
6119 | TestOutputStruct (seq, checks) ->
6120 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6121 let seq, last = get_seq_last seq in
6125 | CompareWithInt (field, expected) ->
6126 pr " if (r->%s != %d) {\n" field expected;
6127 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6128 test_name field expected;
6129 pr " (int) r->%s);\n" field;
6132 | CompareWithIntOp (field, op, expected) ->
6133 pr " if (!(r->%s %s %d)) {\n" field op expected;
6134 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6135 test_name field op expected;
6136 pr " (int) r->%s);\n" field;
6139 | CompareWithString (field, expected) ->
6140 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
6141 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6142 test_name field expected;
6143 pr " r->%s);\n" field;
6146 | CompareFieldsIntEq (field1, field2) ->
6147 pr " if (r->%s != r->%s) {\n" field1 field2;
6148 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6149 test_name field1 field2;
6150 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6153 | CompareFieldsStrEq (field1, field2) ->
6154 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
6155 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6156 test_name field1 field2;
6157 pr " r->%s, r->%s);\n" field1 field2;
6162 List.iter (generate_test_command_call test_name) seq;
6163 generate_test_command_call ~test test_name last
6164 | TestLastFail seq ->
6165 pr " /* TestLastFail for %s (%d) */\n" name i;
6166 let seq, last = get_seq_last seq in
6167 List.iter (generate_test_command_call test_name) seq;
6168 generate_test_command_call test_name ~expect_error:true last
6170 (* Generate the code to run a command, leaving the result in 'r'.
6171 * If you expect to get an error then you should set expect_error:true.
6173 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6175 | [] -> assert false
6177 (* Look up the command to find out what args/ret it has. *)
6180 let _, style, _, _, _, _, _ =
6181 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6184 failwithf "%s: in test, command %s was not found" test_name name in
6186 if List.length (snd style) <> List.length args then
6187 failwithf "%s: in test, wrong number of args given to %s"
6194 | OptString n, "NULL" -> ()
6197 | Dev_or_Path n, arg
6199 | OptString n, arg ->
6200 pr " const char *%s = \"%s\";\n" n (c_quote arg);
6204 | FileIn _, _ | FileOut _, _ -> ()
6205 | StringList n, arg | DeviceList n, arg ->
6206 let strs = string_split " " arg in
6209 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
6211 pr " const char *const %s[] = {\n" n;
6213 fun i _ -> pr " %s_%d,\n" n i
6217 ) (List.combine (snd style) args);
6220 match fst style with
6221 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
6222 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6223 | RConstString _ | RConstOptString _ ->
6224 pr " const char *r;\n"; "NULL"
6225 | RString _ -> pr " char *r;\n"; "NULL"
6226 | RStringList _ | RHashtable _ ->
6230 | RStruct (_, typ) ->
6231 pr " struct guestfs_%s *r;\n" typ; "NULL"
6232 | RStructList (_, typ) ->
6233 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6236 pr " size_t size;\n";
6239 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
6240 pr " r = guestfs_%s (g" name;
6242 (* Generate the parameters. *)
6245 | OptString _, "NULL" -> pr ", NULL"
6247 | Device n, _ | Dev_or_Path n, _
6251 | FileIn _, arg | FileOut _, arg ->
6252 pr ", \"%s\"" (c_quote arg)
6253 | StringList n, _ | DeviceList n, _ ->
6254 pr ", (char **) %s" n
6257 try int_of_string arg
6258 with Failure "int_of_string" ->
6259 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6263 try Int64.of_string arg
6264 with Failure "int_of_string" ->
6265 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6268 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6269 ) (List.combine (snd style) args);
6271 (match fst style with
6272 | RBufferOut _ -> pr ", &size"
6278 if not expect_error then
6279 pr " if (r == %s)\n" error_code
6281 pr " if (r != %s)\n" error_code;
6284 (* Insert the test code. *)
6290 (match fst style with
6291 | RErr | RInt _ | RInt64 _ | RBool _
6292 | RConstString _ | RConstOptString _ -> ()
6293 | RString _ | RBufferOut _ -> pr " free (r);\n"
6294 | RStringList _ | RHashtable _ ->
6295 pr " for (i = 0; r[i] != NULL; ++i)\n";
6296 pr " free (r[i]);\n";
6298 | RStruct (_, typ) ->
6299 pr " guestfs_free_%s (r);\n" typ
6300 | RStructList (_, typ) ->
6301 pr " guestfs_free_%s_list (r);\n" typ
6307 let str = replace_str str "\r" "\\r" in
6308 let str = replace_str str "\n" "\\n" in
6309 let str = replace_str str "\t" "\\t" in
6310 let str = replace_str str "\000" "\\0" in
6313 (* Generate a lot of different functions for guestfish. *)
6314 and generate_fish_cmds () =
6315 generate_header CStyle GPLv2;
6319 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6321 let all_functions_sorted =
6323 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6324 ) all_functions_sorted in
6326 pr "#include <stdio.h>\n";
6327 pr "#include <stdlib.h>\n";
6328 pr "#include <string.h>\n";
6329 pr "#include <inttypes.h>\n";
6331 pr "#include <guestfs.h>\n";
6332 pr "#include \"c-ctype.h\"\n";
6333 pr "#include \"fish.h\"\n";
6336 (* list_commands function, which implements guestfish -h *)
6337 pr "void list_commands (void)\n";
6339 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6340 pr " list_builtin_commands ();\n";
6342 fun (name, _, _, flags, _, shortdesc, _) ->
6343 let name = replace_char name '_' '-' in
6344 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6346 ) all_functions_sorted;
6347 pr " printf (\" %%s\\n\",";
6348 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6352 (* display_command function, which implements guestfish -h cmd *)
6353 pr "void display_command (const char *cmd)\n";
6356 fun (name, style, _, flags, _, shortdesc, longdesc) ->
6357 let name2 = replace_char name '_' '-' in
6359 try find_map (function FishAlias n -> Some n | _ -> None) flags
6360 with Not_found -> name in
6361 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6363 match snd style with
6367 name2 (String.concat "> <" (List.map name_of_argt args)) in
6370 if List.mem ProtocolLimitWarning flags then
6371 ("\n\n" ^ protocol_limit_warning)
6374 (* For DangerWillRobinson commands, we should probably have
6375 * guestfish prompt before allowing you to use them (especially
6376 * in interactive mode). XXX
6380 if List.mem DangerWillRobinson flags then
6381 ("\n\n" ^ danger_will_robinson)
6386 match deprecation_notice flags with
6388 | Some txt -> "\n\n" ^ txt in
6390 let describe_alias =
6391 if name <> alias then
6392 sprintf "\n\nYou can use '%s' as an alias for this command." alias
6396 pr "strcasecmp (cmd, \"%s\") == 0" name;
6397 if name <> name2 then
6398 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6399 if name <> alias then
6400 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6402 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
6404 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6407 pr " display_builtin_command (cmd);\n";
6411 let emit_print_list_function typ =
6412 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6415 pr " unsigned int i;\n";
6417 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6418 pr " printf (\"[%%d] = {\\n\", i);\n";
6419 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
6420 pr " printf (\"}\\n\");\n";
6426 (* print_* functions *)
6430 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6432 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6435 pr " unsigned int i;\n";
6441 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6443 pr " printf (\"%%s%s: \", indent);\n" name;
6444 pr " for (i = 0; i < 32; ++i)\n";
6445 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
6446 pr " printf (\"\\n\");\n"
6448 pr " printf (\"%%s%s: \", indent);\n" name;
6449 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6450 pr " if (c_isprint (%s->%s[i]))\n" typ name;
6451 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
6453 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6454 pr " printf (\"\\n\");\n"
6455 | name, (FUInt64|FBytes) ->
6456 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6459 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6462 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6465 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6468 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6470 | name, FOptPercent ->
6471 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6472 typ name name typ name;
6473 pr " else printf (\"%%s%s: \\n\", indent);\n" name
6479 (* Emit a print_TYPE_list function definition only if that function is used. *)
6482 | typ, (RStructListOnly | RStructAndList) ->
6483 (* generate the function for typ *)
6484 emit_print_list_function typ
6485 | typ, _ -> () (* empty *)
6486 ) (rstructs_used_by all_functions);
6488 (* Emit a print_TYPE function definition only if that function is used. *)
6491 | typ, (RStructOnly | RStructAndList) ->
6492 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6494 pr " print_%s_indent (%s, \"\");\n" typ typ;
6497 | typ, _ -> () (* empty *)
6498 ) (rstructs_used_by all_functions);
6500 (* run_<action> actions *)
6502 fun (name, style, _, flags, _, _, _) ->
6503 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6505 (match fst style with
6508 | RBool _ -> pr " int r;\n"
6509 | RInt64 _ -> pr " int64_t r;\n"
6510 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
6511 | RString _ -> pr " char *r;\n"
6512 | RStringList _ | RHashtable _ -> pr " char **r;\n"
6513 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
6514 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
6517 pr " size_t size;\n";
6525 | FileOut n -> pr " const char *%s;\n" n
6527 | Dev_or_Path n -> pr " char *%s;\n" n
6528 | StringList n | DeviceList n -> pr " char **%s;\n" n
6529 | Bool n -> pr " int %s;\n" n
6530 | Int n -> pr " int %s;\n" n
6531 | Int64 n -> pr " int64_t %s;\n" n
6534 (* Check and convert parameters. *)
6535 let argc_expected = List.length (snd style) in
6536 pr " if (argc != %d) {\n" argc_expected;
6537 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6539 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6547 pr " %s = argv[%d];\n" name i
6549 | Dev_or_Path name ->
6550 pr " %s = resolve_win_path (argv[%d]);\n" name i;
6551 pr " if (%s == NULL) return -1;\n" name
6553 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6556 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6559 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6561 | StringList name | DeviceList name ->
6562 pr " %s = parse_string_list (argv[%d]);\n" name i;
6563 pr " if (%s == NULL) return -1;\n" name;
6565 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6567 pr " %s = atoi (argv[%d]);\n" name i
6569 pr " %s = atoll (argv[%d]);\n" name i
6572 (* Call C API function. *)
6574 try find_map (function FishAction n -> Some n | _ -> None) flags
6575 with Not_found -> sprintf "guestfs_%s" name in
6577 generate_c_call_args ~handle:"g" style;
6582 | Device name | String name
6583 | OptString name | FileIn name | FileOut name | Bool name
6584 | Int name | Int64 name -> ()
6585 | Pathname name | Dev_or_Path name ->
6586 pr " free (%s);\n" name
6587 | StringList name | DeviceList name ->
6588 pr " free_strings (%s);\n" name
6591 (* Check return value for errors and display command results. *)
6592 (match fst style with
6593 | RErr -> pr " return r;\n"
6595 pr " if (r == -1) return -1;\n";
6596 pr " printf (\"%%d\\n\", r);\n";
6599 pr " if (r == -1) return -1;\n";
6600 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6603 pr " if (r == -1) return -1;\n";
6604 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6607 pr " if (r == NULL) return -1;\n";
6608 pr " printf (\"%%s\\n\", r);\n";
6610 | RConstOptString _ ->
6611 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6614 pr " if (r == NULL) return -1;\n";
6615 pr " printf (\"%%s\\n\", r);\n";
6619 pr " if (r == NULL) return -1;\n";
6620 pr " print_strings (r);\n";
6621 pr " free_strings (r);\n";
6623 | RStruct (_, typ) ->
6624 pr " if (r == NULL) return -1;\n";
6625 pr " print_%s (r);\n" typ;
6626 pr " guestfs_free_%s (r);\n" typ;
6628 | RStructList (_, typ) ->
6629 pr " if (r == NULL) return -1;\n";
6630 pr " print_%s_list (r);\n" typ;
6631 pr " guestfs_free_%s_list (r);\n" typ;
6634 pr " if (r == NULL) return -1;\n";
6635 pr " print_table (r);\n";
6636 pr " free_strings (r);\n";
6639 pr " if (r == NULL) return -1;\n";
6640 pr " fwrite (r, size, 1, stdout);\n";
6648 (* run_action function *)
6649 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6652 fun (name, _, _, flags, _, _, _) ->
6653 let name2 = replace_char name '_' '-' in
6655 try find_map (function FishAlias n -> Some n | _ -> None) flags
6656 with Not_found -> name in
6658 pr "strcasecmp (cmd, \"%s\") == 0" name;
6659 if name <> name2 then
6660 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6661 if name <> alias then
6662 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6664 pr " return run_%s (cmd, argc, argv);\n" name;
6668 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6675 (* Readline completion for guestfish. *)
6676 and generate_fish_completion () =
6677 generate_header CStyle GPLv2;
6681 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6691 #ifdef HAVE_LIBREADLINE
6692 #include <readline/readline.h>
6697 #ifdef HAVE_LIBREADLINE
6699 static const char *const commands[] = {
6700 BUILTIN_COMMANDS_FOR_COMPLETION,
6703 (* Get the commands, including the aliases. They don't need to be
6704 * sorted - the generator() function just does a dumb linear search.
6708 fun (name, _, _, flags, _, _, _) ->
6709 let name2 = replace_char name '_' '-' in
6711 try find_map (function FishAlias n -> Some n | _ -> None) flags
6712 with Not_found -> name in
6714 if name <> alias then [name2; alias] else [name2]
6716 let commands = List.flatten commands in
6718 List.iter (pr " \"%s\",\n") commands;
6724 generator (const char *text, int state)
6726 static int index, len;
6731 len = strlen (text);
6734 rl_attempted_completion_over = 1;
6736 while ((name = commands[index]) != NULL) {
6738 if (strncasecmp (name, text, len) == 0)
6739 return strdup (name);
6745 #endif /* HAVE_LIBREADLINE */
6747 char **do_completion (const char *text, int start, int end)
6749 char **matches = NULL;
6751 #ifdef HAVE_LIBREADLINE
6752 rl_completion_append_character = ' ';
6755 matches = rl_completion_matches (text, generator);
6756 else if (complete_dest_paths)
6757 matches = rl_completion_matches (text, complete_dest_paths_generator);
6764 (* Generate the POD documentation for guestfish. *)
6765 and generate_fish_actions_pod () =
6766 let all_functions_sorted =
6768 fun (_, _, _, flags, _, _, _) ->
6769 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6770 ) all_functions_sorted in
6772 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6775 fun (name, style, _, flags, _, _, longdesc) ->
6777 Str.global_substitute rex (
6780 try Str.matched_group 1 s
6782 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6783 "C<" ^ replace_char sub '_' '-' ^ ">"
6785 let name = replace_char name '_' '-' in
6787 try find_map (function FishAlias n -> Some n | _ -> None) flags
6788 with Not_found -> name in
6790 pr "=head2 %s" name;
6791 if name <> alias then
6798 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6799 | OptString n -> pr " %s" n
6800 | StringList n | DeviceList n -> pr " '%s ...'" n
6801 | Bool _ -> pr " true|false"
6802 | Int n -> pr " %s" n
6803 | Int64 n -> pr " %s" n
6804 | FileIn n | FileOut n -> pr " (%s|-)" n
6808 pr "%s\n\n" longdesc;
6810 if List.exists (function FileIn _ | FileOut _ -> true
6811 | _ -> false) (snd style) then
6812 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6814 if List.mem ProtocolLimitWarning flags then
6815 pr "%s\n\n" protocol_limit_warning;
6817 if List.mem DangerWillRobinson flags then
6818 pr "%s\n\n" danger_will_robinson;
6820 match deprecation_notice flags with
6822 | Some txt -> pr "%s\n\n" txt
6823 ) all_functions_sorted
6825 (* Generate a C function prototype. *)
6826 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6827 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6829 ?handle name style =
6830 if extern then pr "extern ";
6831 if static then pr "static ";
6832 (match fst style with
6834 | RInt _ -> pr "int "
6835 | RInt64 _ -> pr "int64_t "
6836 | RBool _ -> pr "int "
6837 | RConstString _ | RConstOptString _ -> pr "const char *"
6838 | RString _ | RBufferOut _ -> pr "char *"
6839 | RStringList _ | RHashtable _ -> pr "char **"
6840 | RStruct (_, typ) ->
6841 if not in_daemon then pr "struct guestfs_%s *" typ
6842 else pr "guestfs_int_%s *" typ
6843 | RStructList (_, typ) ->
6844 if not in_daemon then pr "struct guestfs_%s_list *" typ
6845 else pr "guestfs_int_%s_list *" typ
6847 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6848 pr "%s%s (" prefix name;
6849 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6852 let comma = ref false in
6855 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6859 if single_line then pr ", " else pr ",\n\t\t"
6866 | Device n | Dev_or_Path n
6870 pr "const char *%s" n
6871 | StringList n | DeviceList n ->
6873 pr "char *const *%s" n
6874 | Bool n -> next (); pr "int %s" n
6875 | Int n -> next (); pr "int %s" n
6876 | Int64 n -> next (); pr "int64_t %s" n
6879 if not in_daemon then (next (); pr "const char *%s" n)
6881 if is_RBufferOut then (next (); pr "size_t *size_r");
6884 if semicolon then pr ";";
6885 if newline then pr "\n"
6887 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6888 and generate_c_call_args ?handle ?(decl = false) style =
6890 let comma = ref false in
6892 if !comma then pr ", ";
6897 | Some handle -> pr "%s" handle; comma := true
6902 pr "%s" (name_of_argt arg)
6904 (* For RBufferOut calls, add implicit &size parameter. *)
6906 match fst style with
6914 (* Generate the OCaml bindings interface. *)
6915 and generate_ocaml_mli () =
6916 generate_header OCamlStyle LGPLv2;
6919 (** For API documentation you should refer to the C API
6920 in the guestfs(3) manual page. The OCaml API uses almost
6921 exactly the same calls. *)
6924 (** A [guestfs_h] handle. *)
6926 exception Error of string
6927 (** This exception is raised when there is an error. *)
6929 val create : unit -> t
6931 val close : t -> unit
6932 (** Handles are closed by the garbage collector when they become
6933 unreferenced, but callers can also call this in order to
6934 provide predictable cleanup. *)
6937 generate_ocaml_structure_decls ();
6941 fun (name, style, _, _, _, shortdesc, _) ->
6942 generate_ocaml_prototype name style;
6943 pr "(** %s *)\n" shortdesc;
6947 (* Generate the OCaml bindings implementation. *)
6948 and generate_ocaml_ml () =
6949 generate_header OCamlStyle LGPLv2;
6953 exception Error of string
6954 external create : unit -> t = \"ocaml_guestfs_create\"
6955 external close : t -> unit = \"ocaml_guestfs_close\"
6958 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6962 generate_ocaml_structure_decls ();
6966 fun (name, style, _, _, _, shortdesc, _) ->
6967 generate_ocaml_prototype ~is_external:true name style;
6970 (* Generate the OCaml bindings C implementation. *)
6971 and generate_ocaml_c () =
6972 generate_header CStyle LGPLv2;
6979 #include <caml/config.h>
6980 #include <caml/alloc.h>
6981 #include <caml/callback.h>
6982 #include <caml/fail.h>
6983 #include <caml/memory.h>
6984 #include <caml/mlvalues.h>
6985 #include <caml/signals.h>
6987 #include <guestfs.h>
6989 #include \"guestfs_c.h\"
6991 /* Copy a hashtable of string pairs into an assoc-list. We return
6992 * the list in reverse order, but hashtables aren't supposed to be
6995 static CAMLprim value
6996 copy_table (char * const * argv)
6999 CAMLlocal5 (rv, pairv, kv, vv, cons);
7003 for (i = 0; argv[i] != NULL; i += 2) {
7004 kv = caml_copy_string (argv[i]);
7005 vv = caml_copy_string (argv[i+1]);
7006 pairv = caml_alloc (2, 0);
7007 Store_field (pairv, 0, kv);
7008 Store_field (pairv, 1, vv);
7009 cons = caml_alloc (2, 0);
7010 Store_field (cons, 1, rv);
7012 Store_field (cons, 0, pairv);
7020 (* Struct copy functions. *)
7022 let emit_ocaml_copy_list_function typ =
7023 pr "static CAMLprim value\n";
7024 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7026 pr " CAMLparam0 ();\n";
7027 pr " CAMLlocal2 (rv, v);\n";
7028 pr " unsigned int i;\n";
7030 pr " if (%ss->len == 0)\n" typ;
7031 pr " CAMLreturn (Atom (0));\n";
7033 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7034 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7035 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7036 pr " caml_modify (&Field (rv, i), v);\n";
7038 pr " CAMLreturn (rv);\n";
7046 let has_optpercent_col =
7047 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7049 pr "static CAMLprim value\n";
7050 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7052 pr " CAMLparam0 ();\n";
7053 if has_optpercent_col then
7054 pr " CAMLlocal3 (rv, v, v2);\n"
7056 pr " CAMLlocal2 (rv, v);\n";
7058 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7063 pr " v = caml_copy_string (%s->%s);\n" typ name
7065 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7066 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7069 pr " v = caml_alloc_string (32);\n";
7070 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7071 | name, (FBytes|FInt64|FUInt64) ->
7072 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7073 | name, (FInt32|FUInt32) ->
7074 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7075 | name, FOptPercent ->
7076 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7077 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7078 pr " v = caml_alloc (1, 0);\n";
7079 pr " Store_field (v, 0, v2);\n";
7080 pr " } else /* None */\n";
7081 pr " v = Val_int (0);\n";
7083 pr " v = Val_int (%s->%s);\n" typ name
7085 pr " Store_field (rv, %d, v);\n" i
7087 pr " CAMLreturn (rv);\n";
7092 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7095 | typ, (RStructListOnly | RStructAndList) ->
7096 (* generate the function for typ *)
7097 emit_ocaml_copy_list_function typ
7098 | typ, _ -> () (* empty *)
7099 ) (rstructs_used_by all_functions);
7103 fun (name, style, _, _, _, _, _) ->
7105 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7107 let needs_extra_vs =
7108 match fst style with RConstOptString _ -> true | _ -> false in
7110 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7111 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7112 List.iter (pr ", value %s") (List.tl params); pr ");\n";
7114 pr "CAMLprim value\n";
7115 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7116 List.iter (pr ", value %s") (List.tl params);
7121 | [p1; p2; p3; p4; p5] ->
7122 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
7123 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7124 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7125 pr " CAMLxparam%d (%s);\n"
7126 (List.length rest) (String.concat ", " rest)
7128 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7130 if not needs_extra_vs then
7131 pr " CAMLlocal1 (rv);\n"
7133 pr " CAMLlocal3 (rv, v, v2);\n";
7136 pr " guestfs_h *g = Guestfs_val (gv);\n";
7137 pr " if (g == NULL)\n";
7138 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
7144 | Device n | Dev_or_Path n
7148 pr " const char *%s = String_val (%sv);\n" n n
7150 pr " const char *%s =\n" n;
7151 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7153 | StringList n | DeviceList n ->
7154 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7156 pr " int %s = Bool_val (%sv);\n" n n
7158 pr " int %s = Int_val (%sv);\n" n n
7160 pr " int64_t %s = Int64_val (%sv);\n" n n
7163 match fst style with
7164 | RErr -> pr " int r;\n"; "-1"
7165 | RInt _ -> pr " int r;\n"; "-1"
7166 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7167 | RBool _ -> pr " int r;\n"; "-1"
7168 | RConstString _ | RConstOptString _ ->
7169 pr " const char *r;\n"; "NULL"
7170 | RString _ -> pr " char *r;\n"; "NULL"
7175 | RStruct (_, typ) ->
7176 pr " struct guestfs_%s *r;\n" typ; "NULL"
7177 | RStructList (_, typ) ->
7178 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7185 pr " size_t size;\n";
7189 pr " caml_enter_blocking_section ();\n";
7190 pr " r = guestfs_%s " name;
7191 generate_c_call_args ~handle:"g" style;
7193 pr " caml_leave_blocking_section ();\n";
7197 | StringList n | DeviceList n ->
7198 pr " ocaml_guestfs_free_strings (%s);\n" n;
7199 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7200 | Bool _ | Int _ | Int64 _
7201 | FileIn _ | FileOut _ -> ()
7204 pr " if (r == %s)\n" error_code;
7205 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7208 (match fst style with
7209 | RErr -> pr " rv = Val_unit;\n"
7210 | RInt _ -> pr " rv = Val_int (r);\n"
7212 pr " rv = caml_copy_int64 (r);\n"
7213 | RBool _ -> pr " rv = Val_bool (r);\n"
7215 pr " rv = caml_copy_string (r);\n"
7216 | RConstOptString _ ->
7217 pr " if (r) { /* Some string */\n";
7218 pr " v = caml_alloc (1, 0);\n";
7219 pr " v2 = caml_copy_string (r);\n";
7220 pr " Store_field (v, 0, v2);\n";
7221 pr " } else /* None */\n";
7222 pr " v = Val_int (0);\n";
7224 pr " rv = caml_copy_string (r);\n";
7227 pr " rv = caml_copy_string_array ((const char **) r);\n";
7228 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7230 | RStruct (_, typ) ->
7231 pr " rv = copy_%s (r);\n" typ;
7232 pr " guestfs_free_%s (r);\n" typ;
7233 | RStructList (_, typ) ->
7234 pr " rv = copy_%s_list (r);\n" typ;
7235 pr " guestfs_free_%s_list (r);\n" typ;
7237 pr " rv = copy_table (r);\n";
7238 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7241 pr " rv = caml_alloc_string (size);\n";
7242 pr " memcpy (String_val (rv), r, size);\n";
7245 pr " CAMLreturn (rv);\n";
7249 if List.length params > 5 then (
7250 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7251 pr "CAMLprim value ";
7252 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7253 pr "CAMLprim value\n";
7254 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7256 pr " return ocaml_guestfs_%s (argv[0]" name;
7257 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7264 and generate_ocaml_structure_decls () =
7267 pr "type %s = {\n" typ;
7270 | name, FString -> pr " %s : string;\n" name
7271 | name, FBuffer -> pr " %s : string;\n" name
7272 | name, FUUID -> pr " %s : string;\n" name
7273 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
7274 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
7275 | name, FChar -> pr " %s : char;\n" name
7276 | name, FOptPercent -> pr " %s : float option;\n" name
7282 and generate_ocaml_prototype ?(is_external = false) name style =
7283 if is_external then pr "external " else pr "val ";
7284 pr "%s : t -> " name;
7287 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7288 | OptString _ -> pr "string option -> "
7289 | StringList _ | DeviceList _ -> pr "string array -> "
7290 | Bool _ -> pr "bool -> "
7291 | Int _ -> pr "int -> "
7292 | Int64 _ -> pr "int64 -> "
7294 (match fst style with
7295 | RErr -> pr "unit" (* all errors are turned into exceptions *)
7296 | RInt _ -> pr "int"
7297 | RInt64 _ -> pr "int64"
7298 | RBool _ -> pr "bool"
7299 | RConstString _ -> pr "string"
7300 | RConstOptString _ -> pr "string option"
7301 | RString _ | RBufferOut _ -> pr "string"
7302 | RStringList _ -> pr "string array"
7303 | RStruct (_, typ) -> pr "%s" typ
7304 | RStructList (_, typ) -> pr "%s array" typ
7305 | RHashtable _ -> pr "(string * string) list"
7307 if is_external then (
7309 if List.length (snd style) + 1 > 5 then
7310 pr "\"ocaml_guestfs_%s_byte\" " name;
7311 pr "\"ocaml_guestfs_%s\"" name
7315 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7316 and generate_perl_xs () =
7317 generate_header CStyle LGPLv2;
7320 #include \"EXTERN.h\"
7324 #include <guestfs.h>
7327 #define PRId64 \"lld\"
7331 my_newSVll(long long val) {
7332 #ifdef USE_64_BIT_ALL
7333 return newSViv(val);
7337 len = snprintf(buf, 100, \"%%\" PRId64, val);
7338 return newSVpv(buf, len);
7343 #define PRIu64 \"llu\"
7347 my_newSVull(unsigned long long val) {
7348 #ifdef USE_64_BIT_ALL
7349 return newSVuv(val);
7353 len = snprintf(buf, 100, \"%%\" PRIu64, val);
7354 return newSVpv(buf, len);
7358 /* http://www.perlmonks.org/?node_id=680842 */
7360 XS_unpack_charPtrPtr (SV *arg) {
7365 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7366 croak (\"array reference expected\");
7368 av = (AV *)SvRV (arg);
7369 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7371 croak (\"malloc failed\");
7373 for (i = 0; i <= av_len (av); i++) {
7374 SV **elem = av_fetch (av, i, 0);
7376 if (!elem || !*elem)
7377 croak (\"missing element in list\");
7379 ret[i] = SvPV_nolen (*elem);
7387 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
7394 RETVAL = guestfs_create ();
7396 croak (\"could not create guestfs handle\");
7397 guestfs_set_error_handler (RETVAL, NULL, NULL);
7410 fun (name, style, _, _, _, _, _) ->
7411 (match fst style with
7412 | RErr -> pr "void\n"
7413 | RInt _ -> pr "SV *\n"
7414 | RInt64 _ -> pr "SV *\n"
7415 | RBool _ -> pr "SV *\n"
7416 | RConstString _ -> pr "SV *\n"
7417 | RConstOptString _ -> pr "SV *\n"
7418 | RString _ -> pr "SV *\n"
7419 | RBufferOut _ -> pr "SV *\n"
7421 | RStruct _ | RStructList _
7423 pr "void\n" (* all lists returned implictly on the stack *)
7425 (* Call and arguments. *)
7427 generate_c_call_args ~handle:"g" ~decl:true style;
7429 pr " guestfs_h *g;\n";
7433 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7436 (* http://www.perlmonks.org/?node_id=554277
7437 * Note that the implicit handle argument means we have
7438 * to add 1 to the ST(x) operator.
7440 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7441 | StringList n | DeviceList n -> pr " char **%s;\n" n
7442 | Bool n -> pr " int %s;\n" n
7443 | Int n -> pr " int %s;\n" n
7444 | Int64 n -> pr " int64_t %s;\n" n
7447 let do_cleanups () =
7450 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7451 | Bool _ | Int _ | Int64 _
7452 | FileIn _ | FileOut _ -> ()
7453 | StringList n | DeviceList n -> pr " free (%s);\n" n
7458 (match fst style with
7463 pr " r = guestfs_%s " name;
7464 generate_c_call_args ~handle:"g" style;
7467 pr " if (r == -1)\n";
7468 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7474 pr " %s = guestfs_%s " n name;
7475 generate_c_call_args ~handle:"g" style;
7478 pr " if (%s == -1)\n" n;
7479 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7480 pr " RETVAL = newSViv (%s);\n" n;
7485 pr " int64_t %s;\n" n;
7487 pr " %s = guestfs_%s " n name;
7488 generate_c_call_args ~handle:"g" style;
7491 pr " if (%s == -1)\n" n;
7492 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7493 pr " RETVAL = my_newSVll (%s);\n" n;
7498 pr " const char *%s;\n" n;
7500 pr " %s = guestfs_%s " n name;
7501 generate_c_call_args ~handle:"g" style;
7504 pr " if (%s == NULL)\n" n;
7505 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7506 pr " RETVAL = newSVpv (%s, 0);\n" n;
7509 | RConstOptString n ->
7511 pr " const char *%s;\n" n;
7513 pr " %s = guestfs_%s " n name;
7514 generate_c_call_args ~handle:"g" style;
7517 pr " if (%s == NULL)\n" n;
7518 pr " RETVAL = &PL_sv_undef;\n";
7520 pr " RETVAL = newSVpv (%s, 0);\n" n;
7525 pr " char *%s;\n" n;
7527 pr " %s = guestfs_%s " n name;
7528 generate_c_call_args ~handle:"g" style;
7531 pr " if (%s == NULL)\n" n;
7532 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7533 pr " RETVAL = newSVpv (%s, 0);\n" n;
7534 pr " free (%s);\n" n;
7537 | RStringList n | RHashtable n ->
7539 pr " char **%s;\n" n;
7542 pr " %s = guestfs_%s " n name;
7543 generate_c_call_args ~handle:"g" style;
7546 pr " if (%s == NULL)\n" n;
7547 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7548 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7549 pr " EXTEND (SP, n);\n";
7550 pr " for (i = 0; i < n; ++i) {\n";
7551 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7552 pr " free (%s[i]);\n" n;
7554 pr " free (%s);\n" n;
7555 | RStruct (n, typ) ->
7556 let cols = cols_of_struct typ in
7557 generate_perl_struct_code typ cols name style n do_cleanups
7558 | RStructList (n, typ) ->
7559 let cols = cols_of_struct typ in
7560 generate_perl_struct_list_code typ cols name style n do_cleanups
7563 pr " char *%s;\n" n;
7564 pr " size_t size;\n";
7566 pr " %s = guestfs_%s " n name;
7567 generate_c_call_args ~handle:"g" style;
7570 pr " if (%s == NULL)\n" n;
7571 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7572 pr " RETVAL = newSVpv (%s, size);\n" n;
7573 pr " free (%s);\n" n;
7581 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7583 pr " struct guestfs_%s_list *%s;\n" typ n;
7587 pr " %s = guestfs_%s " n name;
7588 generate_c_call_args ~handle:"g" style;
7591 pr " if (%s == NULL)\n" n;
7592 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7593 pr " EXTEND (SP, %s->len);\n" n;
7594 pr " for (i = 0; i < %s->len; ++i) {\n" n;
7595 pr " hv = newHV ();\n";
7599 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7600 name (String.length name) n name
7602 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7603 name (String.length name) n name
7605 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7606 name (String.length name) n name n name
7607 | name, (FBytes|FUInt64) ->
7608 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7609 name (String.length name) n name
7611 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7612 name (String.length name) n name
7613 | name, (FInt32|FUInt32) ->
7614 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7615 name (String.length name) n name
7617 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7618 name (String.length name) n name
7619 | name, FOptPercent ->
7620 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7621 name (String.length name) n name
7623 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7625 pr " guestfs_free_%s_list (%s);\n" typ n
7627 and generate_perl_struct_code typ cols name style n do_cleanups =
7629 pr " struct guestfs_%s *%s;\n" typ n;
7631 pr " %s = guestfs_%s " n name;
7632 generate_c_call_args ~handle:"g" style;
7635 pr " if (%s == NULL)\n" n;
7636 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7637 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7639 fun ((name, _) as col) ->
7640 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7644 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7647 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7650 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7652 | name, (FBytes|FUInt64) ->
7653 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7656 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7658 | name, (FInt32|FUInt32) ->
7659 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7662 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7664 | name, FOptPercent ->
7665 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7668 pr " free (%s);\n" n
7670 (* Generate Sys/Guestfs.pm. *)
7671 and generate_perl_pm () =
7672 generate_header HashStyle LGPLv2;
7679 Sys::Guestfs - Perl bindings for libguestfs
7685 my $h = Sys::Guestfs->new ();
7686 $h->add_drive ('guest.img');
7688 $h->mount ('/dev/sda1', '/');
7689 $h->touch ('/hello');
7694 The C<Sys::Guestfs> module provides a Perl XS binding to the
7695 libguestfs API for examining and modifying virtual machine
7698 Amongst the things this is good for: making batch configuration
7699 changes to guests, getting disk used/free statistics (see also:
7700 virt-df), migrating between virtualization systems (see also:
7701 virt-p2v), performing partial backups, performing partial guest
7702 clones, cloning guests and changing registry/UUID/hostname info, and
7705 Libguestfs uses Linux kernel and qemu code, and can access any type of
7706 guest filesystem that Linux and qemu can, including but not limited
7707 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7708 schemes, qcow, qcow2, vmdk.
7710 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7711 LVs, what filesystem is in each LV, etc.). It can also run commands
7712 in the context of the guest. Also you can access filesystems over FTP.
7714 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7715 functions for using libguestfs from Perl, including integration
7720 All errors turn into calls to C<croak> (see L<Carp(3)>).
7728 package Sys::Guestfs;
7734 XSLoader::load ('Sys::Guestfs');
7736 =item $h = Sys::Guestfs->new ();
7738 Create a new guestfs handle.
7744 my $class = ref ($proto) || $proto;
7746 my $self = Sys::Guestfs::_create ();
7747 bless $self, $class;
7753 (* Actions. We only need to print documentation for these as
7754 * they are pulled in from the XS code automatically.
7757 fun (name, style, _, flags, _, _, longdesc) ->
7758 if not (List.mem NotInDocs flags) then (
7759 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7761 generate_perl_prototype name style;
7763 pr "%s\n\n" longdesc;
7764 if List.mem ProtocolLimitWarning flags then
7765 pr "%s\n\n" protocol_limit_warning;
7766 if List.mem DangerWillRobinson flags then
7767 pr "%s\n\n" danger_will_robinson;
7768 match deprecation_notice flags with
7770 | Some txt -> pr "%s\n\n" txt
7772 ) all_functions_sorted;
7784 Copyright (C) 2009 Red Hat Inc.
7788 Please see the file COPYING.LIB for the full license.
7794 L<http://libguestfs.org>,
7795 L<Sys::Guestfs::Lib(3)>.
7800 and generate_perl_prototype name style =
7801 (match fst style with
7809 | RBufferOut n -> pr "$%s = " n
7811 | RHashtable n -> pr "%%%s = " n
7813 | RStructList (n,_) -> pr "@%s = " n
7816 let comma = ref false in
7819 if !comma then pr ", ";
7822 | Pathname n | Device n | Dev_or_Path n | String n
7823 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
7825 | StringList n | DeviceList n ->
7830 (* Generate Python C module. *)
7831 and generate_python_c () =
7832 generate_header CStyle LGPLv2;
7841 #include \"guestfs.h\"
7849 get_handle (PyObject *obj)
7852 assert (obj != Py_None);
7853 return ((Pyguestfs_Object *) obj)->g;
7857 put_handle (guestfs_h *g)
7861 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7864 /* This list should be freed (but not the strings) after use. */
7866 get_string_list (PyObject *obj)
7873 if (!PyList_Check (obj)) {
7874 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7878 len = PyList_Size (obj);
7879 r = malloc (sizeof (char *) * (len+1));
7881 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7885 for (i = 0; i < len; ++i)
7886 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7893 put_string_list (char * const * const argv)
7898 for (argc = 0; argv[argc] != NULL; ++argc)
7901 list = PyList_New (argc);
7902 for (i = 0; i < argc; ++i)
7903 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7909 put_table (char * const * const argv)
7911 PyObject *list, *item;
7914 for (argc = 0; argv[argc] != NULL; ++argc)
7917 list = PyList_New (argc >> 1);
7918 for (i = 0; i < argc; i += 2) {
7919 item = PyTuple_New (2);
7920 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7921 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7922 PyList_SetItem (list, i >> 1, item);
7929 free_strings (char **argv)
7933 for (argc = 0; argv[argc] != NULL; ++argc)
7939 py_guestfs_create (PyObject *self, PyObject *args)
7943 g = guestfs_create ();
7945 PyErr_SetString (PyExc_RuntimeError,
7946 \"guestfs.create: failed to allocate handle\");
7949 guestfs_set_error_handler (g, NULL, NULL);
7950 return put_handle (g);
7954 py_guestfs_close (PyObject *self, PyObject *args)
7959 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7961 g = get_handle (py_g);
7965 Py_INCREF (Py_None);
7971 let emit_put_list_function typ =
7972 pr "static PyObject *\n";
7973 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7975 pr " PyObject *list;\n";
7978 pr " list = PyList_New (%ss->len);\n" typ;
7979 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7980 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7981 pr " return list;\n";
7986 (* Structures, turned into Python dictionaries. *)
7989 pr "static PyObject *\n";
7990 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7992 pr " PyObject *dict;\n";
7994 pr " dict = PyDict_New ();\n";
7998 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7999 pr " PyString_FromString (%s->%s));\n"
8002 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8003 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8006 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8007 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8009 | name, (FBytes|FUInt64) ->
8010 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8011 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8014 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8015 pr " PyLong_FromLongLong (%s->%s));\n"
8018 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8019 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8022 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8023 pr " PyLong_FromLong (%s->%s));\n"
8025 | name, FOptPercent ->
8026 pr " if (%s->%s >= 0)\n" typ name;
8027 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8028 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8031 pr " Py_INCREF (Py_None);\n";
8032 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8035 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8036 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8038 pr " return dict;\n";
8044 (* Emit a put_TYPE_list function definition only if that function is used. *)
8047 | typ, (RStructListOnly | RStructAndList) ->
8048 (* generate the function for typ *)
8049 emit_put_list_function typ
8050 | typ, _ -> () (* empty *)
8051 ) (rstructs_used_by all_functions);
8053 (* Python wrapper functions. *)
8055 fun (name, style, _, _, _, _, _) ->
8056 pr "static PyObject *\n";
8057 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8060 pr " PyObject *py_g;\n";
8061 pr " guestfs_h *g;\n";
8062 pr " PyObject *py_r;\n";
8065 match fst style with
8066 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8067 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8068 | RConstString _ | RConstOptString _ ->
8069 pr " const char *r;\n"; "NULL"
8070 | RString _ -> pr " char *r;\n"; "NULL"
8071 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8072 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8073 | RStructList (_, typ) ->
8074 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8077 pr " size_t size;\n";
8082 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8083 pr " const char *%s;\n" n
8084 | OptString n -> pr " const char *%s;\n" n
8085 | StringList n | DeviceList n ->
8086 pr " PyObject *py_%s;\n" n;
8087 pr " char **%s;\n" n
8088 | Bool n -> pr " int %s;\n" n
8089 | Int n -> pr " int %s;\n" n
8090 | Int64 n -> pr " long long %s;\n" n
8095 (* Convert the parameters. *)
8096 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8099 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8100 | OptString _ -> pr "z"
8101 | StringList _ | DeviceList _ -> pr "O"
8102 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8104 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8105 * emulate C's int/long/long long in Python?
8108 pr ":guestfs_%s\",\n" name;
8112 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8113 | OptString n -> pr ", &%s" n
8114 | StringList n | DeviceList n -> pr ", &py_%s" n
8115 | Bool n -> pr ", &%s" n
8116 | Int n -> pr ", &%s" n
8117 | Int64 n -> pr ", &%s" n
8121 pr " return NULL;\n";
8123 pr " g = get_handle (py_g);\n";
8126 | Pathname _ | Device _ | Dev_or_Path _ | String _
8127 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8128 | StringList n | DeviceList n ->
8129 pr " %s = get_string_list (py_%s);\n" n n;
8130 pr " if (!%s) return NULL;\n" n
8135 pr " r = guestfs_%s " name;
8136 generate_c_call_args ~handle:"g" style;
8141 | Pathname _ | Device _ | Dev_or_Path _ | String _
8142 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8143 | StringList n | DeviceList n ->
8144 pr " free (%s);\n" n
8147 pr " if (r == %s) {\n" error_code;
8148 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8149 pr " return NULL;\n";
8153 (match fst style with
8155 pr " Py_INCREF (Py_None);\n";
8156 pr " py_r = Py_None;\n"
8158 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
8159 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
8160 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
8161 | RConstOptString _ ->
8163 pr " py_r = PyString_FromString (r);\n";
8165 pr " Py_INCREF (Py_None);\n";
8166 pr " py_r = Py_None;\n";
8169 pr " py_r = PyString_FromString (r);\n";
8172 pr " py_r = put_string_list (r);\n";
8173 pr " free_strings (r);\n"
8174 | RStruct (_, typ) ->
8175 pr " py_r = put_%s (r);\n" typ;
8176 pr " guestfs_free_%s (r);\n" typ
8177 | RStructList (_, typ) ->
8178 pr " py_r = put_%s_list (r);\n" typ;
8179 pr " guestfs_free_%s_list (r);\n" typ
8181 pr " py_r = put_table (r);\n";
8182 pr " free_strings (r);\n"
8184 pr " py_r = PyString_FromStringAndSize (r, size);\n";
8188 pr " return py_r;\n";
8193 (* Table of functions. *)
8194 pr "static PyMethodDef methods[] = {\n";
8195 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8196 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8198 fun (name, _, _, _, _, _, _) ->
8199 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8202 pr " { NULL, NULL, 0, NULL }\n";
8206 (* Init function. *)
8209 initlibguestfsmod (void)
8211 static int initialized = 0;
8213 if (initialized) return;
8214 Py_InitModule ((char *) \"libguestfsmod\", methods);
8219 (* Generate Python module. *)
8220 and generate_python_py () =
8221 generate_header HashStyle LGPLv2;
8224 u\"\"\"Python bindings for libguestfs
8227 g = guestfs.GuestFS ()
8228 g.add_drive (\"guest.img\")
8230 parts = g.list_partitions ()
8232 The guestfs module provides a Python binding to the libguestfs API
8233 for examining and modifying virtual machine disk images.
8235 Amongst the things this is good for: making batch configuration
8236 changes to guests, getting disk used/free statistics (see also:
8237 virt-df), migrating between virtualization systems (see also:
8238 virt-p2v), performing partial backups, performing partial guest
8239 clones, cloning guests and changing registry/UUID/hostname info, and
8242 Libguestfs uses Linux kernel and qemu code, and can access any type of
8243 guest filesystem that Linux and qemu can, including but not limited
8244 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8245 schemes, qcow, qcow2, vmdk.
8247 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8248 LVs, what filesystem is in each LV, etc.). It can also run commands
8249 in the context of the guest. Also you can access filesystems over FTP.
8251 Errors which happen while using the API are turned into Python
8252 RuntimeError exceptions.
8254 To create a guestfs handle you usually have to perform the following
8257 # Create the handle, call add_drive at least once, and possibly
8258 # several times if the guest has multiple block devices:
8259 g = guestfs.GuestFS ()
8260 g.add_drive (\"guest.img\")
8262 # Launch the qemu subprocess and wait for it to become ready:
8265 # Now you can issue commands, for example:
8270 import libguestfsmod
8273 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8275 def __init__ (self):
8276 \"\"\"Create a new libguestfs handle.\"\"\"
8277 self._o = libguestfsmod.create ()
8280 libguestfsmod.close (self._o)
8285 fun (name, style, _, flags, _, _, longdesc) ->
8287 generate_py_call_args ~handle:"self" (snd style);
8290 if not (List.mem NotInDocs flags) then (
8291 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8293 match fst style with
8294 | RErr | RInt _ | RInt64 _ | RBool _
8295 | RConstOptString _ | RConstString _
8296 | RString _ | RBufferOut _ -> doc
8298 doc ^ "\n\nThis function returns a list of strings."
8299 | RStruct (_, typ) ->
8300 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8301 | RStructList (_, typ) ->
8302 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
8304 doc ^ "\n\nThis function returns a dictionary." in
8306 if List.mem ProtocolLimitWarning flags then
8307 doc ^ "\n\n" ^ protocol_limit_warning
8310 if List.mem DangerWillRobinson flags then
8311 doc ^ "\n\n" ^ danger_will_robinson
8314 match deprecation_notice flags with
8316 | Some txt -> doc ^ "\n\n" ^ txt in
8317 let doc = pod2text ~width:60 name doc in
8318 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8319 let doc = String.concat "\n " doc in
8320 pr " u\"\"\"%s\"\"\"\n" doc;
8322 pr " return libguestfsmod.%s " name;
8323 generate_py_call_args ~handle:"self._o" (snd style);
8328 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8329 and generate_py_call_args ~handle args =
8331 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8334 (* Useful if you need the longdesc POD text as plain text. Returns a
8337 * Because this is very slow (the slowest part of autogeneration),
8338 * we memoize the results.
8340 and pod2text ~width name longdesc =
8341 let key = width, name, longdesc in
8342 try Hashtbl.find pod2text_memo key
8344 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8345 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8347 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8348 let chan = Unix.open_process_in cmd in
8349 let lines = ref [] in
8351 let line = input_line chan in
8352 if i = 1 then (* discard the first line of output *)
8355 let line = triml line in
8356 lines := line :: !lines;
8359 let lines = try loop 1 with End_of_file -> List.rev !lines in
8360 Unix.unlink filename;
8361 (match Unix.close_process_in chan with
8362 | Unix.WEXITED 0 -> ()
8364 failwithf "pod2text: process exited with non-zero status (%d)" i
8365 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8366 failwithf "pod2text: process signalled or stopped by signal %d" i
8368 Hashtbl.add pod2text_memo key lines;
8369 pod2text_memo_updated ();
8372 (* Generate ruby bindings. *)
8373 and generate_ruby_c () =
8374 generate_header CStyle LGPLv2;
8382 #include \"guestfs.h\"
8384 #include \"extconf.h\"
8386 /* For Ruby < 1.9 */
8388 #define RARRAY_LEN(r) (RARRAY((r))->len)
8391 static VALUE m_guestfs; /* guestfs module */
8392 static VALUE c_guestfs; /* guestfs_h handle */
8393 static VALUE e_Error; /* used for all errors */
8395 static void ruby_guestfs_free (void *p)
8398 guestfs_close ((guestfs_h *) p);
8401 static VALUE ruby_guestfs_create (VALUE m)
8405 g = guestfs_create ();
8407 rb_raise (e_Error, \"failed to create guestfs handle\");
8409 /* Don't print error messages to stderr by default. */
8410 guestfs_set_error_handler (g, NULL, NULL);
8412 /* Wrap it, and make sure the close function is called when the
8415 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8418 static VALUE ruby_guestfs_close (VALUE gv)
8421 Data_Get_Struct (gv, guestfs_h, g);
8423 ruby_guestfs_free (g);
8424 DATA_PTR (gv) = NULL;
8432 fun (name, style, _, _, _, _, _) ->
8433 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8434 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8437 pr " guestfs_h *g;\n";
8438 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
8440 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8446 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8447 pr " Check_Type (%sv, T_STRING);\n" n;
8448 pr " const char *%s = StringValueCStr (%sv);\n" n n;
8450 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8451 pr " \"%s\", \"%s\");\n" n name
8453 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8454 | StringList n | DeviceList n ->
8455 pr " char **%s;\n" n;
8456 pr " Check_Type (%sv, T_ARRAY);\n" n;
8458 pr " int i, len;\n";
8459 pr " len = RARRAY_LEN (%sv);\n" n;
8460 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8462 pr " for (i = 0; i < len; ++i) {\n";
8463 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
8464 pr " %s[i] = StringValueCStr (v);\n" n;
8466 pr " %s[len] = NULL;\n" n;
8469 pr " int %s = RTEST (%sv);\n" n n
8471 pr " int %s = NUM2INT (%sv);\n" n n
8473 pr " long long %s = NUM2LL (%sv);\n" n n
8478 match fst style with
8479 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8480 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8481 | RConstString _ | RConstOptString _ ->
8482 pr " const char *r;\n"; "NULL"
8483 | RString _ -> pr " char *r;\n"; "NULL"
8484 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8485 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8486 | RStructList (_, typ) ->
8487 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8490 pr " size_t size;\n";
8494 pr " r = guestfs_%s " name;
8495 generate_c_call_args ~handle:"g" style;
8500 | Pathname _ | Device _ | Dev_or_Path _ | String _
8501 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8502 | StringList n | DeviceList n ->
8503 pr " free (%s);\n" n
8506 pr " if (r == %s)\n" error_code;
8507 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8510 (match fst style with
8512 pr " return Qnil;\n"
8513 | RInt _ | RBool _ ->
8514 pr " return INT2NUM (r);\n"
8516 pr " return ULL2NUM (r);\n"
8518 pr " return rb_str_new2 (r);\n";
8519 | RConstOptString _ ->
8521 pr " return rb_str_new2 (r);\n";
8523 pr " return Qnil;\n";
8525 pr " VALUE rv = rb_str_new2 (r);\n";
8529 pr " int i, len = 0;\n";
8530 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
8531 pr " VALUE rv = rb_ary_new2 (len);\n";
8532 pr " for (i = 0; r[i] != NULL; ++i) {\n";
8533 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8534 pr " free (r[i]);\n";
8538 | RStruct (_, typ) ->
8539 let cols = cols_of_struct typ in
8540 generate_ruby_struct_code typ cols
8541 | RStructList (_, typ) ->
8542 let cols = cols_of_struct typ in
8543 generate_ruby_struct_list_code typ cols
8545 pr " VALUE rv = rb_hash_new ();\n";
8547 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
8548 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8549 pr " free (r[i]);\n";
8550 pr " free (r[i+1]);\n";
8555 pr " VALUE rv = rb_str_new (r, size);\n";
8565 /* Initialize the module. */
8566 void Init__guestfs ()
8568 m_guestfs = rb_define_module (\"Guestfs\");
8569 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8570 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8572 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8573 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8576 (* Define the rest of the methods. *)
8578 fun (name, style, _, _, _, _, _) ->
8579 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
8580 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8585 (* Ruby code to return a struct. *)
8586 and generate_ruby_struct_code typ cols =
8587 pr " VALUE rv = rb_hash_new ();\n";
8591 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8593 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8595 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8596 | name, (FBytes|FUInt64) ->
8597 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8599 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8601 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8603 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8604 | name, FOptPercent ->
8605 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8606 | name, FChar -> (* XXX wrong? *)
8607 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8609 pr " guestfs_free_%s (r);\n" typ;
8612 (* Ruby code to return a struct list. *)
8613 and generate_ruby_struct_list_code typ cols =
8614 pr " VALUE rv = rb_ary_new2 (r->len);\n";
8616 pr " for (i = 0; i < r->len; ++i) {\n";
8617 pr " VALUE hv = rb_hash_new ();\n";
8621 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8623 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
8625 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8626 | name, (FBytes|FUInt64) ->
8627 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8629 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8631 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8633 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8634 | name, FOptPercent ->
8635 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8636 | name, FChar -> (* XXX wrong? *)
8637 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8639 pr " rb_ary_push (rv, hv);\n";
8641 pr " guestfs_free_%s_list (r);\n" typ;
8644 (* Generate Java bindings GuestFS.java file. *)
8645 and generate_java_java () =
8646 generate_header CStyle LGPLv2;
8649 package com.redhat.et.libguestfs;
8651 import java.util.HashMap;
8652 import com.redhat.et.libguestfs.LibGuestFSException;
8653 import com.redhat.et.libguestfs.PV;
8654 import com.redhat.et.libguestfs.VG;
8655 import com.redhat.et.libguestfs.LV;
8656 import com.redhat.et.libguestfs.Stat;
8657 import com.redhat.et.libguestfs.StatVFS;
8658 import com.redhat.et.libguestfs.IntBool;
8659 import com.redhat.et.libguestfs.Dirent;
8662 * The GuestFS object is a libguestfs handle.
8666 public class GuestFS {
8667 // Load the native code.
8669 System.loadLibrary (\"guestfs_jni\");
8673 * The native guestfs_h pointer.
8678 * Create a libguestfs handle.
8680 * @throws LibGuestFSException
8682 public GuestFS () throws LibGuestFSException
8686 private native long _create () throws LibGuestFSException;
8689 * Close a libguestfs handle.
8691 * You can also leave handles to be collected by the garbage
8692 * collector, but this method ensures that the resources used
8693 * by the handle are freed up immediately. If you call any
8694 * other methods after closing the handle, you will get an
8697 * @throws LibGuestFSException
8699 public void close () throws LibGuestFSException
8705 private native void _close (long g) throws LibGuestFSException;
8707 public void finalize () throws LibGuestFSException
8715 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8716 if not (List.mem NotInDocs flags); then (
8717 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8719 if List.mem ProtocolLimitWarning flags then
8720 doc ^ "\n\n" ^ protocol_limit_warning
8723 if List.mem DangerWillRobinson flags then
8724 doc ^ "\n\n" ^ danger_will_robinson
8727 match deprecation_notice flags with
8729 | Some txt -> doc ^ "\n\n" ^ txt in
8730 let doc = pod2text ~width:60 name doc in
8731 let doc = List.map ( (* RHBZ#501883 *)
8734 | nonempty -> nonempty
8736 let doc = String.concat "\n * " doc in
8739 pr " * %s\n" shortdesc;
8742 pr " * @throws LibGuestFSException\n";
8746 generate_java_prototype ~public:true ~semicolon:false name style;
8749 pr " if (g == 0)\n";
8750 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8753 if fst style <> RErr then pr "return ";
8755 generate_java_call_args ~handle:"g" (snd style);
8759 generate_java_prototype ~privat:true ~native:true name style;
8766 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8767 and generate_java_call_args ~handle args =
8769 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8772 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8773 ?(semicolon=true) name style =
8774 if privat then pr "private ";
8775 if public then pr "public ";
8776 if native then pr "native ";
8779 (match fst style with
8780 | RErr -> pr "void ";
8781 | RInt _ -> pr "int ";
8782 | RInt64 _ -> pr "long ";
8783 | RBool _ -> pr "boolean ";
8784 | RConstString _ | RConstOptString _ | RString _
8785 | RBufferOut _ -> pr "String ";
8786 | RStringList _ -> pr "String[] ";
8787 | RStruct (_, typ) ->
8788 let name = java_name_of_struct typ in
8790 | RStructList (_, typ) ->
8791 let name = java_name_of_struct typ in
8793 | RHashtable _ -> pr "HashMap<String,String> ";
8796 if native then pr "_%s " name else pr "%s " name;
8798 let needs_comma = ref false in
8807 if !needs_comma then pr ", ";
8808 needs_comma := true;
8812 | Device n | Dev_or_Path n
8818 | StringList n | DeviceList n ->
8829 pr " throws LibGuestFSException";
8830 if semicolon then pr ";"
8832 and generate_java_struct jtyp cols =
8833 generate_header CStyle LGPLv2;
8836 package com.redhat.et.libguestfs;
8839 * Libguestfs %s structure.
8851 | name, FBuffer -> pr " public String %s;\n" name
8852 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8853 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8854 | name, FChar -> pr " public char %s;\n" name
8855 | name, FOptPercent ->
8856 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8857 pr " public float %s;\n" name
8862 and generate_java_c () =
8863 generate_header CStyle LGPLv2;
8870 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8871 #include \"guestfs.h\"
8873 /* Note that this function returns. The exception is not thrown
8874 * until after the wrapper function returns.
8877 throw_exception (JNIEnv *env, const char *msg)
8880 cl = (*env)->FindClass (env,
8881 \"com/redhat/et/libguestfs/LibGuestFSException\");
8882 (*env)->ThrowNew (env, cl, msg);
8885 JNIEXPORT jlong JNICALL
8886 Java_com_redhat_et_libguestfs_GuestFS__1create
8887 (JNIEnv *env, jobject obj)
8891 g = guestfs_create ();
8893 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8896 guestfs_set_error_handler (g, NULL, NULL);
8897 return (jlong) (long) g;
8900 JNIEXPORT void JNICALL
8901 Java_com_redhat_et_libguestfs_GuestFS__1close
8902 (JNIEnv *env, jobject obj, jlong jg)
8904 guestfs_h *g = (guestfs_h *) (long) jg;
8911 fun (name, style, _, _, _, _, _) ->
8913 (match fst style with
8914 | RErr -> pr "void ";
8915 | RInt _ -> pr "jint ";
8916 | RInt64 _ -> pr "jlong ";
8917 | RBool _ -> pr "jboolean ";
8918 | RConstString _ | RConstOptString _ | RString _
8919 | RBufferOut _ -> pr "jstring ";
8920 | RStruct _ | RHashtable _ ->
8922 | RStringList _ | RStructList _ ->
8926 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8927 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8929 pr " (JNIEnv *env, jobject obj, jlong jg";
8933 | Device n | Dev_or_Path n
8938 pr ", jstring j%s" n
8939 | StringList n | DeviceList n ->
8940 pr ", jobjectArray j%s" n
8942 pr ", jboolean j%s" n
8950 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8951 let error_code, no_ret =
8952 match fst style with
8953 | RErr -> pr " int r;\n"; "-1", ""
8955 | RInt _ -> pr " int r;\n"; "-1", "0"
8956 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8957 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8958 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8960 pr " jstring jr;\n";
8961 pr " char *r;\n"; "NULL", "NULL"
8963 pr " jobjectArray jr;\n";
8966 pr " jstring jstr;\n";
8967 pr " char **r;\n"; "NULL", "NULL"
8968 | RStruct (_, typ) ->
8969 pr " jobject jr;\n";
8971 pr " jfieldID fl;\n";
8972 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8973 | RStructList (_, typ) ->
8974 pr " jobjectArray jr;\n";
8976 pr " jfieldID fl;\n";
8977 pr " jobject jfl;\n";
8978 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8979 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8981 pr " jstring jr;\n";
8983 pr " size_t size;\n";
8988 | Device n | Dev_or_Path n
8993 pr " const char *%s;\n" n
8994 | StringList n | DeviceList n ->
8995 pr " int %s_len;\n" n;
8996 pr " const char **%s;\n" n
9001 pr " int64_t %s;\n" n
9005 (match fst style with
9006 | RStringList _ | RStructList _ -> true
9007 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9009 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9010 List.exists (function
9011 | StringList _ -> true
9012 | DeviceList _ -> true
9013 | _ -> false) (snd style) in
9019 (* Get the parameters. *)
9023 | Device n | Dev_or_Path n
9027 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9029 (* This is completely undocumented, but Java null becomes
9032 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9033 | StringList n | DeviceList n ->
9034 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9035 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9036 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9037 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9039 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9041 pr " %s[%s_len] = NULL;\n" n n;
9045 pr " %s = j%s;\n" n n
9048 (* Make the call. *)
9049 pr " r = guestfs_%s " name;
9050 generate_c_call_args ~handle:"g" style;
9053 (* Release the parameters. *)
9057 | Device n | Dev_or_Path n
9061 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9064 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9065 | StringList n | DeviceList n ->
9066 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9067 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9069 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9071 pr " free (%s);\n" n
9077 (* Check for errors. *)
9078 pr " if (r == %s) {\n" error_code;
9079 pr " throw_exception (env, guestfs_last_error (g));\n";
9080 pr " return %s;\n" no_ret;
9084 (match fst style with
9086 | RInt _ -> pr " return (jint) r;\n"
9087 | RBool _ -> pr " return (jboolean) r;\n"
9088 | RInt64 _ -> pr " return (jlong) r;\n"
9089 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9090 | RConstOptString _ ->
9091 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9093 pr " jr = (*env)->NewStringUTF (env, r);\n";
9097 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9098 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9099 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9100 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9101 pr " for (i = 0; i < r_len; ++i) {\n";
9102 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9103 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9104 pr " free (r[i]);\n";
9108 | RStruct (_, typ) ->
9109 let jtyp = java_name_of_struct typ in
9110 let cols = cols_of_struct typ in
9111 generate_java_struct_return typ jtyp cols
9112 | RStructList (_, typ) ->
9113 let jtyp = java_name_of_struct typ in
9114 let cols = cols_of_struct typ in
9115 generate_java_struct_list_return typ jtyp cols
9118 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9119 pr " return NULL;\n"
9121 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9130 and generate_java_struct_return typ jtyp cols =
9131 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9132 pr " jr = (*env)->AllocObject (env, cl);\n";
9136 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9137 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9140 pr " char s[33];\n";
9141 pr " memcpy (s, r->%s, 32);\n" name;
9143 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9144 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9148 pr " int len = r->%s_len;\n" name;
9149 pr " char s[len+1];\n";
9150 pr " memcpy (s, r->%s, len);\n" name;
9151 pr " s[len] = 0;\n";
9152 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9153 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9155 | name, (FBytes|FUInt64|FInt64) ->
9156 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9157 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9158 | name, (FUInt32|FInt32) ->
9159 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9160 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9161 | name, FOptPercent ->
9162 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9163 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9165 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9166 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9171 and generate_java_struct_list_return typ jtyp cols =
9172 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9173 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9174 pr " for (i = 0; i < r->len; ++i) {\n";
9175 pr " jfl = (*env)->AllocObject (env, cl);\n";
9179 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9180 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9183 pr " char s[33];\n";
9184 pr " memcpy (s, r->val[i].%s, 32);\n" name;
9186 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9187 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9191 pr " int len = r->val[i].%s_len;\n" name;
9192 pr " char s[len+1];\n";
9193 pr " memcpy (s, r->val[i].%s, len);\n" name;
9194 pr " s[len] = 0;\n";
9195 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9196 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9198 | name, (FBytes|FUInt64|FInt64) ->
9199 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9200 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9201 | name, (FUInt32|FInt32) ->
9202 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9203 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9204 | name, FOptPercent ->
9205 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9206 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9208 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9209 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9211 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9213 pr " guestfs_free_%s_list (r);\n" typ;
9216 and generate_java_makefile_inc () =
9217 generate_header HashStyle GPLv2;
9219 pr "java_built_sources = \\\n";
9222 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9224 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9226 and generate_haskell_hs () =
9227 generate_header HaskellStyle LGPLv2;
9229 (* XXX We only know how to generate partial FFI for Haskell
9230 * at the moment. Please help out!
9232 let can_generate style =
9236 | RInt64 _, _ -> true
9239 | RConstOptString _, _
9245 | RBufferOut _, _ -> false in
9248 {-# INCLUDE <guestfs.h> #-}
9249 {-# LANGUAGE ForeignFunctionInterface #-}
9254 (* List out the names of the actions we want to export. *)
9256 fun (name, style, _, _, _, _, _) ->
9257 if can_generate style then pr ",\n %s" name
9264 import Foreign.C.Types
9266 import Control.Exception
9267 import Data.Typeable
9269 data GuestfsS = GuestfsS -- represents the opaque C struct
9270 type GuestfsP = Ptr GuestfsS -- guestfs_h *
9271 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9273 -- XXX define properly later XXX
9277 data IntBool = IntBool
9279 data StatVFS = StatVFS
9280 data Hashtable = Hashtable
9282 foreign import ccall unsafe \"guestfs_create\" c_create
9284 foreign import ccall unsafe \"&guestfs_close\" c_close
9285 :: FunPtr (GuestfsP -> IO ())
9286 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9287 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9289 create :: IO GuestfsH
9292 c_set_error_handler p nullPtr nullPtr
9293 h <- newForeignPtr c_close p
9296 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9297 :: GuestfsP -> IO CString
9299 -- last_error :: GuestfsH -> IO (Maybe String)
9300 -- last_error h = do
9301 -- str <- withForeignPtr h (\\p -> c_last_error p)
9302 -- maybePeek peekCString str
9304 last_error :: GuestfsH -> IO (String)
9306 str <- withForeignPtr h (\\p -> c_last_error p)
9308 then return \"no error\"
9309 else peekCString str
9313 (* Generate wrappers for each foreign function. *)
9315 fun (name, style, _, _, _, _, _) ->
9316 if can_generate style then (
9317 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9319 generate_haskell_prototype ~handle:"GuestfsP" style;
9323 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9325 pr "%s %s = do\n" name
9326 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9328 (* Convert pointer arguments using with* functions. *)
9333 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9334 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9335 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9336 | Bool _ | Int _ | Int64 _ -> ()
9338 (* Convert integer arguments. *)
9342 | Bool n -> sprintf "(fromBool %s)" n
9343 | Int n -> sprintf "(fromIntegral %s)" n
9344 | Int64 n -> sprintf "(fromIntegral %s)" n
9345 | FileIn n | FileOut n
9346 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9348 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9349 (String.concat " " ("p" :: args));
9350 (match fst style with
9351 | RErr | RInt _ | RInt64 _ | RBool _ ->
9352 pr " if (r == -1)\n";
9354 pr " err <- last_error h\n";
9356 | RConstString _ | RConstOptString _ | RString _
9357 | RStringList _ | RStruct _
9358 | RStructList _ | RHashtable _ | RBufferOut _ ->
9359 pr " if (r == nullPtr)\n";
9361 pr " err <- last_error h\n";
9364 (match fst style with
9366 pr " else return ()\n"
9368 pr " else return (fromIntegral r)\n"
9370 pr " else return (fromIntegral r)\n"
9372 pr " else return (toBool r)\n"
9381 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9387 and generate_haskell_prototype ~handle ?(hs = false) style =
9389 let string = if hs then "String" else "CString" in
9390 let int = if hs then "Int" else "CInt" in
9391 let bool = if hs then "Bool" else "CInt" in
9392 let int64 = if hs then "Integer" else "Int64" in
9396 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9397 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9398 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9399 | Bool _ -> pr "%s" bool
9400 | Int _ -> pr "%s" int
9401 | Int64 _ -> pr "%s" int
9402 | FileIn _ -> pr "%s" string
9403 | FileOut _ -> pr "%s" string
9408 (match fst style with
9409 | RErr -> if not hs then pr "CInt"
9410 | RInt _ -> pr "%s" int
9411 | RInt64 _ -> pr "%s" int64
9412 | RBool _ -> pr "%s" bool
9413 | RConstString _ -> pr "%s" string
9414 | RConstOptString _ -> pr "Maybe %s" string
9415 | RString _ -> pr "%s" string
9416 | RStringList _ -> pr "[%s]" string
9417 | RStruct (_, typ) ->
9418 let name = java_name_of_struct typ in
9420 | RStructList (_, typ) ->
9421 let name = java_name_of_struct typ in
9423 | RHashtable _ -> pr "Hashtable"
9424 | RBufferOut _ -> pr "%s" string
9428 and generate_bindtests () =
9429 generate_header CStyle LGPLv2;
9434 #include <inttypes.h>
9437 #include \"guestfs.h\"
9438 #include \"guestfs-internal-actions.h\"
9439 #include \"guestfs_protocol.h\"
9441 #define error guestfs_error
9442 #define safe_calloc guestfs_safe_calloc
9443 #define safe_malloc guestfs_safe_malloc
9446 print_strings (char *const *argv)
9451 for (argc = 0; argv[argc] != NULL; ++argc) {
9452 if (argc > 0) printf (\", \");
9453 printf (\"\\\"%%s\\\"\", argv[argc]);
9458 /* The test0 function prints its parameters to stdout. */
9462 match test_functions with
9463 | [] -> assert false
9464 | test0 :: tests -> test0, tests in
9467 let (name, style, _, _, _, _, _) = test0 in
9468 generate_prototype ~extern:false ~semicolon:false ~newline:true
9469 ~handle:"g" ~prefix:"guestfs__" name style;
9474 | Device n | Dev_or_Path n
9477 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
9478 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9479 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
9480 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9481 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
9482 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9484 pr " /* Java changes stdout line buffering so we need this: */\n";
9485 pr " fflush (stdout);\n";
9491 fun (name, style, _, _, _, _, _) ->
9492 if String.sub name (String.length name - 3) 3 <> "err" then (
9493 pr "/* Test normal return. */\n";
9494 generate_prototype ~extern:false ~semicolon:false ~newline:true
9495 ~handle:"g" ~prefix:"guestfs__" name style;
9497 (match fst style with
9502 pr " sscanf (val, \"%%d\", &r);\n";
9506 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
9509 pr " return strcmp (val, \"true\") == 0;\n"
9511 | RConstOptString _ ->
9512 (* Can't return the input string here. Return a static
9513 * string so we ensure we get a segfault if the caller
9516 pr " return \"static string\";\n"
9518 pr " return strdup (val);\n"
9520 pr " char **strs;\n";
9522 pr " sscanf (val, \"%%d\", &n);\n";
9523 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9524 pr " for (i = 0; i < n; ++i) {\n";
9525 pr " strs[i] = safe_malloc (g, 16);\n";
9526 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
9528 pr " strs[n] = NULL;\n";
9529 pr " return strs;\n"
9530 | RStruct (_, typ) ->
9531 pr " struct guestfs_%s *r;\n" typ;
9532 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9534 | RStructList (_, typ) ->
9535 pr " struct guestfs_%s_list *r;\n" typ;
9536 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9537 pr " sscanf (val, \"%%d\", &r->len);\n";
9538 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9541 pr " char **strs;\n";
9543 pr " sscanf (val, \"%%d\", &n);\n";
9544 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9545 pr " for (i = 0; i < n; ++i) {\n";
9546 pr " strs[i*2] = safe_malloc (g, 16);\n";
9547 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
9548 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
9549 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9551 pr " strs[n*2] = NULL;\n";
9552 pr " return strs;\n"
9554 pr " return strdup (val);\n"
9559 pr "/* Test error return. */\n";
9560 generate_prototype ~extern:false ~semicolon:false ~newline:true
9561 ~handle:"g" ~prefix:"guestfs__" name style;
9563 pr " error (g, \"error\");\n";
9564 (match fst style with
9565 | RErr | RInt _ | RInt64 _ | RBool _ ->
9567 | RConstString _ | RConstOptString _
9568 | RString _ | RStringList _ | RStruct _
9572 pr " return NULL;\n"
9579 and generate_ocaml_bindtests () =
9580 generate_header OCamlStyle GPLv2;
9584 let g = Guestfs.create () in
9591 | CallString s -> "\"" ^ s ^ "\""
9592 | CallOptString None -> "None"
9593 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9594 | CallStringList xs ->
9595 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9596 | CallInt i when i >= 0 -> string_of_int i
9597 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9598 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9599 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9600 | CallBool b -> string_of_bool b
9605 generate_lang_bindtests (
9606 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
9609 pr "print_endline \"EOF\"\n"
9611 and generate_perl_bindtests () =
9612 pr "#!/usr/bin/perl -w\n";
9613 generate_header HashStyle GPLv2;
9620 my $g = Sys::Guestfs->new ();
9624 String.concat ", " (
9627 | CallString s -> "\"" ^ s ^ "\""
9628 | CallOptString None -> "undef"
9629 | CallOptString (Some s) -> sprintf "\"%s\"" s
9630 | CallStringList xs ->
9631 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9632 | CallInt i -> string_of_int i
9633 | CallInt64 i -> Int64.to_string i
9634 | CallBool b -> if b then "1" else "0"
9639 generate_lang_bindtests (
9640 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9643 pr "print \"EOF\\n\"\n"
9645 and generate_python_bindtests () =
9646 generate_header HashStyle GPLv2;
9651 g = guestfs.GuestFS ()
9655 String.concat ", " (
9658 | CallString s -> "\"" ^ s ^ "\""
9659 | CallOptString None -> "None"
9660 | CallOptString (Some s) -> sprintf "\"%s\"" s
9661 | CallStringList xs ->
9662 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9663 | CallInt i -> string_of_int i
9664 | CallInt64 i -> Int64.to_string i
9665 | CallBool b -> if b then "1" else "0"
9670 generate_lang_bindtests (
9671 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9674 pr "print \"EOF\"\n"
9676 and generate_ruby_bindtests () =
9677 generate_header HashStyle GPLv2;
9682 g = Guestfs::create()
9686 String.concat ", " (
9689 | CallString s -> "\"" ^ s ^ "\""
9690 | CallOptString None -> "nil"
9691 | CallOptString (Some s) -> sprintf "\"%s\"" s
9692 | CallStringList xs ->
9693 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9694 | CallInt i -> string_of_int i
9695 | CallInt64 i -> Int64.to_string i
9696 | CallBool b -> string_of_bool b
9701 generate_lang_bindtests (
9702 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9705 pr "print \"EOF\\n\"\n"
9707 and generate_java_bindtests () =
9708 generate_header CStyle GPLv2;
9711 import com.redhat.et.libguestfs.*;
9713 public class Bindtests {
9714 public static void main (String[] argv)
9717 GuestFS g = new GuestFS ();
9721 String.concat ", " (
9724 | CallString s -> "\"" ^ s ^ "\""
9725 | CallOptString None -> "null"
9726 | CallOptString (Some s) -> sprintf "\"%s\"" s
9727 | CallStringList xs ->
9729 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9730 | CallInt i -> string_of_int i
9731 | CallInt64 i -> Int64.to_string i
9732 | CallBool b -> string_of_bool b
9737 generate_lang_bindtests (
9738 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9742 System.out.println (\"EOF\");
9744 catch (Exception exn) {
9745 System.err.println (exn);
9752 and generate_haskell_bindtests () =
9753 generate_header HaskellStyle GPLv2;
9756 module Bindtests where
9757 import qualified Guestfs
9767 | CallString s -> "\"" ^ s ^ "\""
9768 | CallOptString None -> "Nothing"
9769 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9770 | CallStringList xs ->
9771 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9772 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9773 | CallInt i -> string_of_int i
9774 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
9775 | CallInt64 i -> Int64.to_string i
9776 | CallBool true -> "True"
9777 | CallBool false -> "False"
9782 generate_lang_bindtests (
9783 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9786 pr " putStrLn \"EOF\"\n"
9788 (* Language-independent bindings tests - we do it this way to
9789 * ensure there is parity in testing bindings across all languages.
9791 and generate_lang_bindtests call =
9792 call "test0" [CallString "abc"; CallOptString (Some "def");
9793 CallStringList []; CallBool false;
9794 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9795 call "test0" [CallString "abc"; CallOptString None;
9796 CallStringList []; CallBool false;
9797 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9798 call "test0" [CallString ""; CallOptString (Some "def");
9799 CallStringList []; CallBool false;
9800 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9801 call "test0" [CallString ""; CallOptString (Some "");
9802 CallStringList []; CallBool false;
9803 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9804 call "test0" [CallString "abc"; CallOptString (Some "def");
9805 CallStringList ["1"]; CallBool false;
9806 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9807 call "test0" [CallString "abc"; CallOptString (Some "def");
9808 CallStringList ["1"; "2"]; CallBool false;
9809 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9810 call "test0" [CallString "abc"; CallOptString (Some "def");
9811 CallStringList ["1"]; CallBool true;
9812 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9813 call "test0" [CallString "abc"; CallOptString (Some "def");
9814 CallStringList ["1"]; CallBool false;
9815 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
9816 call "test0" [CallString "abc"; CallOptString (Some "def");
9817 CallStringList ["1"]; CallBool false;
9818 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
9819 call "test0" [CallString "abc"; CallOptString (Some "def");
9820 CallStringList ["1"]; CallBool false;
9821 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
9822 call "test0" [CallString "abc"; CallOptString (Some "def");
9823 CallStringList ["1"]; CallBool false;
9824 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
9825 call "test0" [CallString "abc"; CallOptString (Some "def");
9826 CallStringList ["1"]; CallBool false;
9827 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
9828 call "test0" [CallString "abc"; CallOptString (Some "def");
9829 CallStringList ["1"]; CallBool false;
9830 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
9832 (* XXX Add here tests of the return and error functions. *)
9834 (* This is used to generate the src/MAX_PROC_NR file which
9835 * contains the maximum procedure number, a surrogate for the
9836 * ABI version number. See src/Makefile.am for the details.
9838 and generate_max_proc_nr () =
9839 let proc_nrs = List.map (
9840 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9841 ) daemon_functions in
9843 let max_proc_nr = List.fold_left max 0 proc_nrs in
9845 pr "%d\n" max_proc_nr
9847 let output_to filename =
9848 let filename_new = filename ^ ".new" in
9849 chan := open_out filename_new;
9854 (* Is the new file different from the current file? *)
9855 if Sys.file_exists filename && files_equal filename filename_new then
9856 Unix.unlink filename_new (* same, so skip it *)
9858 (* different, overwrite old one *)
9859 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9860 Unix.rename filename_new filename;
9861 Unix.chmod filename 0o444;
9862 printf "written %s\n%!" filename;
9871 if not (Sys.file_exists "HACKING") then (
9873 You are probably running this from the wrong directory.
9874 Run it from the top source directory using the command
9880 let close = output_to "src/guestfs_protocol.x" in
9884 let close = output_to "src/guestfs-structs.h" in
9885 generate_structs_h ();
9888 let close = output_to "src/guestfs-actions.h" in
9889 generate_actions_h ();
9892 let close = output_to "src/guestfs-internal-actions.h" in
9893 generate_internal_actions_h ();
9896 let close = output_to "src/guestfs-actions.c" in
9897 generate_client_actions ();
9900 let close = output_to "daemon/actions.h" in
9901 generate_daemon_actions_h ();
9904 let close = output_to "daemon/stubs.c" in
9905 generate_daemon_actions ();
9908 let close = output_to "daemon/names.c" in
9909 generate_daemon_names ();
9912 let close = output_to "capitests/tests.c" in
9916 let close = output_to "src/guestfs-bindtests.c" in
9917 generate_bindtests ();
9920 let close = output_to "fish/cmds.c" in
9921 generate_fish_cmds ();
9924 let close = output_to "fish/completion.c" in
9925 generate_fish_completion ();
9928 let close = output_to "guestfs-structs.pod" in
9929 generate_structs_pod ();
9932 let close = output_to "guestfs-actions.pod" in
9933 generate_actions_pod ();
9936 let close = output_to "guestfish-actions.pod" in
9937 generate_fish_actions_pod ();
9940 let close = output_to "ocaml/guestfs.mli" in
9941 generate_ocaml_mli ();
9944 let close = output_to "ocaml/guestfs.ml" in
9945 generate_ocaml_ml ();
9948 let close = output_to "ocaml/guestfs_c_actions.c" in
9949 generate_ocaml_c ();
9952 let close = output_to "ocaml/bindtests.ml" in
9953 generate_ocaml_bindtests ();
9956 let close = output_to "perl/Guestfs.xs" in
9957 generate_perl_xs ();
9960 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9961 generate_perl_pm ();
9964 let close = output_to "perl/bindtests.pl" in
9965 generate_perl_bindtests ();
9968 let close = output_to "python/guestfs-py.c" in
9969 generate_python_c ();
9972 let close = output_to "python/guestfs.py" in
9973 generate_python_py ();
9976 let close = output_to "python/bindtests.py" in
9977 generate_python_bindtests ();
9980 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9984 let close = output_to "ruby/bindtests.rb" in
9985 generate_ruby_bindtests ();
9988 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9989 generate_java_java ();
9994 let cols = cols_of_struct typ in
9995 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9996 let close = output_to filename in
9997 generate_java_struct jtyp cols;
10001 let close = output_to "java/Makefile.inc" in
10002 generate_java_makefile_inc ();
10005 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10006 generate_java_c ();
10009 let close = output_to "java/Bindtests.java" in
10010 generate_java_bindtests ();
10013 let close = output_to "haskell/Guestfs.hs" in
10014 generate_haskell_hs ();
10017 let close = output_to "haskell/Bindtests.hs" in
10018 generate_haskell_bindtests ();
10021 let close = output_to "src/MAX_PROC_NR" in
10022 generate_max_proc_nr ();
10025 (* Always generate this file last, and unconditionally. It's used
10026 * by the Makefile to know when we must re-run the generator.
10028 let chan = open_out "src/stamp-generator" in
10029 fprintf chan "1\n";