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 | Bool of string (* boolean *)
143 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
144 (* These are treated as filenames (simple string parameters) in
145 * the C API and bindings. But in the RPC protocol, we transfer
146 * the actual file content up to or down from the daemon.
147 * FileIn: local machine -> daemon (in request)
148 * FileOut: daemon -> local machine (in reply)
149 * In guestfish (only), the special name "-" means read from
150 * stdin or write to stdout.
155 (* Opaque buffer which can contain arbitrary 8 bit data.
156 * In the C API, this is expressed as <char *, int> pair.
157 * Most other languages have a string type which can contain
158 * ASCII NUL. We use whatever type is appropriate for each
160 * Buffers are limited by the total message size. To transfer
161 * large blocks of data, use FileIn/FileOut parameters instead.
162 * To return an arbitrary buffer, use RBufferOut.
168 | ProtocolLimitWarning (* display warning about protocol size limits *)
169 | DangerWillRobinson (* flags particularly dangerous commands *)
170 | FishAlias of string (* provide an alias for this cmd in guestfish *)
171 | FishAction of string (* call this function in guestfish *)
172 | NotInFish (* do not export via guestfish *)
173 | NotInDocs (* do not add this function to documentation *)
174 | DeprecatedBy of string (* function is deprecated, use .. instead *)
176 (* You can supply zero or as many tests as you want per API call.
178 * Note that the test environment has 3 block devices, of size 500MB,
179 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
180 * a fourth squashfs block device with some known files on it (/dev/sdd).
182 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
183 * Number of cylinders was 63 for IDE emulated disks with precisely
184 * the same size. How exactly this is calculated is a mystery.
186 * The squashfs block device (/dev/sdd) comes from images/test.sqsh.
188 * To be able to run the tests in a reasonable amount of time,
189 * the virtual machine and block devices are reused between tests.
190 * So don't try testing kill_subprocess :-x
192 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194 * Don't assume anything about the previous contents of the block
195 * devices. Use 'Init*' to create some initial scenarios.
197 * You can add a prerequisite clause to any individual test. This
198 * is a run-time check, which, if it fails, causes the test to be
199 * skipped. Useful if testing a command which might not work on
200 * all variations of libguestfs builds. A test that has prerequisite
201 * of 'Always' is run unconditionally.
203 * In addition, packagers can skip individual tests by setting the
204 * environment variables: eg:
205 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
206 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
208 type tests = (test_init * test_prereq * test) list
210 (* Run the command sequence and just expect nothing to fail. *)
213 (* Run the command sequence and expect the output of the final
214 * command to be the string.
216 | TestOutput of seq * string
218 (* Run the command sequence and expect the output of the final
219 * command to be the list of strings.
221 | TestOutputList of seq * string list
223 (* Run the command sequence and expect the output of the final
224 * command to be the list of block devices (could be either
225 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
226 * character of each string).
228 | TestOutputListOfDevices of seq * string list
230 (* Run the command sequence and expect the output of the final
231 * command to be the integer.
233 | TestOutputInt of seq * int
235 (* Run the command sequence and expect the output of the final
236 * command to be <op> <int>, eg. ">=", "1".
238 | TestOutputIntOp of seq * string * int
240 (* Run the command sequence and expect the output of the final
241 * command to be a true value (!= 0 or != NULL).
243 | TestOutputTrue of seq
245 (* Run the command sequence and expect the output of the final
246 * command to be a false value (== 0 or == NULL, but not an error).
248 | TestOutputFalse of seq
250 (* Run the command sequence and expect the output of the final
251 * command to be a list of the given length (but don't care about
254 | TestOutputLength of seq * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a buffer (RBufferOut), ie. string + size.
259 | TestOutputBuffer of seq * string
261 (* Run the command sequence and expect the output of the final
262 * command to be a structure.
264 | TestOutputStruct of seq * test_field_compare list
266 (* Run the command sequence and expect the final command (only)
269 | TestLastFail of seq
271 and test_field_compare =
272 | CompareWithInt of string * int
273 | CompareWithIntOp of string * string * int
274 | CompareWithString of string * string
275 | CompareFieldsIntEq of string * string
276 | CompareFieldsStrEq of string * string
278 (* Test prerequisites. *)
280 (* Test always runs. *)
283 (* Test is currently disabled - eg. it fails, or it tests some
284 * unimplemented feature.
288 (* 'string' is some C code (a function body) that should return
289 * true or false. The test will run if the code returns true.
293 (* As for 'If' but the test runs _unless_ the code returns true. *)
296 (* Some initial scenarios for testing. *)
298 (* Do nothing, block devices could contain random stuff including
299 * LVM PVs, and some filesystems might be mounted. This is usually
304 (* Block devices are empty and no filesystems are mounted. *)
307 (* /dev/sda contains a single partition /dev/sda1, with random
308 * content. /dev/sdb and /dev/sdc may have random content.
313 (* /dev/sda contains a single partition /dev/sda1, which is formatted
314 * as ext2, empty [except for lost+found] and mounted on /.
315 * /dev/sdb and /dev/sdc may have random content.
321 * /dev/sda1 (is a PV):
322 * /dev/VG/LV (size 8MB):
323 * formatted as ext2, empty [except for lost+found], mounted on /
324 * /dev/sdb and /dev/sdc may have random content.
328 (* /dev/sdd (the squashfs, see images/ directory in source)
333 (* Sequence of commands for testing. *)
335 and cmd = string list
337 (* Note about long descriptions: When referring to another
338 * action, use the format C<guestfs_other> (ie. the full name of
339 * the C function). This will be replaced as appropriate in other
342 * Apart from that, long descriptions are just perldoc paragraphs.
345 (* Generate a random UUID (used in tests). *)
347 let chan = Unix.open_process_in "uuidgen" in
348 let uuid = input_line chan in
349 (match Unix.close_process_in chan with
350 | Unix.WEXITED 0 -> ()
352 failwith "uuidgen: process exited with non-zero status"
353 | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
354 failwith "uuidgen: process signalled or stopped by signal"
358 (* These test functions are used in the language binding tests. *)
360 let test_all_args = [
363 StringList "strlist";
370 let test_all_rets = [
371 (* except for RErr, which is tested thoroughly elsewhere *)
372 "test0rint", RInt "valout";
373 "test0rint64", RInt64 "valout";
374 "test0rbool", RBool "valout";
375 "test0rconststring", RConstString "valout";
376 "test0rconstoptstring", RConstOptString "valout";
377 "test0rstring", RString "valout";
378 "test0rstringlist", RStringList "valout";
379 "test0rstruct", RStruct ("valout", "lvm_pv");
380 "test0rstructlist", RStructList ("valout", "lvm_pv");
381 "test0rhashtable", RHashtable "valout";
384 let test_functions = [
385 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387 "internal test function - do not use",
389 This is an internal test function which is used to test whether
390 the automatically generated bindings can handle every possible
391 parameter type correctly.
393 It echos the contents of each parameter to stdout.
395 You probably don't want to call this function.");
399 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401 "internal test function - do not use",
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 return type correctly.
407 It converts string C<val> to the return type.
409 You probably don't want to call this function.");
410 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412 "internal test function - do not use",
414 This is an internal test function which is used to test whether
415 the automatically generated bindings can handle every possible
416 return type correctly.
418 This function always returns an error.
420 You probably don't want to call this function.")]
424 (* non_daemon_functions are any functions which don't get processed
425 * in the daemon, eg. functions for setting and getting local
426 * configuration values.
429 let non_daemon_functions = test_functions @ [
430 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432 "launch the qemu subprocess",
434 Internally libguestfs is implemented by running a virtual machine
437 You should call this after configuring the handle
438 (eg. adding drives) but before performing any actions.");
440 ("wait_ready", (RErr, []), -1, [NotInFish],
442 "wait until the qemu subprocess launches",
444 Internally libguestfs is implemented by running a virtual machine
447 You should call this after C<guestfs_launch> to wait for the launch
450 ("kill_subprocess", (RErr, []), -1, [],
452 "kill the qemu subprocess",
454 This kills the qemu subprocess. You should never need to call this.");
456 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
458 "add an image to examine or modify",
460 This function adds a virtual machine disk image C<filename> to the
461 guest. The first time you call this function, the disk appears as IDE
462 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
465 You don't necessarily need to be root when using libguestfs. However
466 you obviously do need sufficient permissions to access the filename
467 for whatever operations you want to perform (ie. read access if you
468 just want to read the image or write access if you want to modify the
471 This is equivalent to the qemu parameter
472 C<-drive file=filename,cache=off,if=...>.
473 C<cache=off> is omitted in cases where it is not supported by
474 the underlying filesystem.
476 Note that this call checks for the existence of C<filename>. This
477 stops you from specifying other types of drive which are supported
478 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
479 the general C<guestfs_config> call instead.");
481 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
483 "add a CD-ROM disk image to examine",
485 This function adds a virtual CD-ROM disk image to the guest.
487 This is equivalent to the qemu parameter C<-cdrom filename>.
489 Note that this call checks for the existence of C<filename>. This
490 stops you from specifying other types of drive which are supported
491 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
492 the general C<guestfs_config> call instead.");
494 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
496 "add a drive in snapshot mode (read-only)",
498 This adds a drive in snapshot mode, making it effectively
501 Note that writes to the device are allowed, and will be seen for
502 the duration of the guestfs handle, but they are written
503 to a temporary file which is discarded as soon as the guestfs
504 handle is closed. We don't currently have any method to enable
505 changes to be committed, although qemu can support this.
507 This is equivalent to the qemu parameter
508 C<-drive file=filename,snapshot=on,if=...>.
510 Note that this call checks for the existence of C<filename>. This
511 stops you from specifying other types of drive which are supported
512 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
513 the general C<guestfs_config> call instead.");
515 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
517 "add qemu parameters",
519 This can be used to add arbitrary qemu command line parameters
520 of the form C<-param value>. Actually it's not quite arbitrary - we
521 prevent you from setting some parameters which would interfere with
522 parameters that we use.
524 The first character of C<param> string must be a C<-> (dash).
526 C<value> can be NULL.");
528 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
530 "set the qemu binary",
532 Set the qemu binary that we will use.
534 The default is chosen when the library was compiled by the
537 You can also override this by setting the C<LIBGUESTFS_QEMU>
538 environment variable.
540 Setting C<qemu> to C<NULL> restores the default qemu binary.");
542 ("get_qemu", (RConstString "qemu", []), -1, [],
543 [InitNone, Always, TestRun (
545 "get the qemu binary",
547 Return the current qemu binary.
549 This is always non-NULL. If it wasn't set already, then this will
550 return the default qemu binary name.");
552 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
554 "set the search path",
556 Set the path that libguestfs searches for kernel and initrd.img.
558 The default is C<$libdir/guestfs> unless overridden by setting
559 C<LIBGUESTFS_PATH> environment variable.
561 Setting C<path> to C<NULL> restores the default path.");
563 ("get_path", (RConstString "path", []), -1, [],
564 [InitNone, Always, TestRun (
566 "get the search path",
568 Return the current search path.
570 This is always non-NULL. If it wasn't set already, then this will
571 return the default path.");
573 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
575 "add options to kernel command line",
577 This function is used to add additional options to the
578 guest kernel command line.
580 The default is C<NULL> unless overridden by setting
581 C<LIBGUESTFS_APPEND> environment variable.
583 Setting C<append> to C<NULL> means I<no> additional options
584 are passed (libguestfs always adds a few of its own).");
586 ("get_append", (RConstOptString "append", []), -1, [],
587 (* This cannot be tested with the current framework. The
588 * function can return NULL in normal operations, which the
589 * test framework interprets as an error.
592 "get the additional kernel options",
594 Return the additional kernel options which are added to the
595 guest kernel command line.
597 If C<NULL> then no options are added.");
599 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
603 If C<autosync> is true, this enables autosync. Libguestfs will make a
604 best effort attempt to run C<guestfs_umount_all> followed by
605 C<guestfs_sync> when the handle is closed
606 (also if the program exits without closing handles).
608 This is disabled by default (except in guestfish where it is
609 enabled by default).");
611 ("get_autosync", (RBool "autosync", []), -1, [],
612 [InitNone, Always, TestRun (
613 [["get_autosync"]])],
616 Get the autosync flag.");
618 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
622 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
624 Verbose messages are disabled unless the environment variable
625 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
627 ("get_verbose", (RBool "verbose", []), -1, [],
631 This returns the verbose messages flag.");
633 ("is_ready", (RBool "ready", []), -1, [],
634 [InitNone, Always, TestOutputTrue (
636 "is ready to accept commands",
638 This returns true iff this handle is ready to accept commands
639 (in the C<READY> state).
641 For more information on states, see L<guestfs(3)>.");
643 ("is_config", (RBool "config", []), -1, [],
644 [InitNone, Always, TestOutputFalse (
646 "is in configuration state",
648 This returns true iff this handle is being configured
649 (in the C<CONFIG> state).
651 For more information on states, see L<guestfs(3)>.");
653 ("is_launching", (RBool "launching", []), -1, [],
654 [InitNone, Always, TestOutputFalse (
655 [["is_launching"]])],
656 "is launching subprocess",
658 This returns true iff this handle is launching the subprocess
659 (in the C<LAUNCHING> state).
661 For more information on states, see L<guestfs(3)>.");
663 ("is_busy", (RBool "busy", []), -1, [],
664 [InitNone, Always, TestOutputFalse (
666 "is busy processing a command",
668 This returns true iff this handle is busy processing a command
669 (in the C<BUSY> state).
671 For more information on states, see L<guestfs(3)>.");
673 ("get_state", (RInt "state", []), -1, [],
675 "get the current state",
677 This returns the current state as an opaque integer. This is
678 only useful for printing debug and internal error messages.
680 For more information on states, see L<guestfs(3)>.");
682 ("set_busy", (RErr, []), -1, [NotInFish],
686 This sets the state to C<BUSY>. This is only used when implementing
687 actions using the low-level API.
689 For more information on states, see L<guestfs(3)>.");
691 ("set_ready", (RErr, []), -1, [NotInFish],
693 "set state to ready",
695 This sets the state to C<READY>. This is only used when implementing
696 actions using the low-level API.
698 For more information on states, see L<guestfs(3)>.");
700 ("end_busy", (RErr, []), -1, [NotInFish],
702 "leave the busy state",
704 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
705 state as is. This is only used when implementing
706 actions using the low-level API.
708 For more information on states, see L<guestfs(3)>.");
710 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
711 [InitNone, Always, TestOutputInt (
712 [["set_memsize"; "500"];
713 ["get_memsize"]], 500)],
714 "set memory allocated to the qemu subprocess",
716 This sets the memory size in megabytes allocated to the
717 qemu subprocess. This only has any effect if called before
720 You can also change this by setting the environment
721 variable C<LIBGUESTFS_MEMSIZE> before the handle is
724 For more information on the architecture of libguestfs,
725 see L<guestfs(3)>.");
727 ("get_memsize", (RInt "memsize", []), -1, [],
728 [InitNone, Always, TestOutputIntOp (
729 [["get_memsize"]], ">=", 256)],
730 "get memory allocated to the qemu subprocess",
732 This gets the memory size in megabytes allocated to the
735 If C<guestfs_set_memsize> was not called
736 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
737 then this returns the compiled-in default value for memsize.
739 For more information on the architecture of libguestfs,
740 see L<guestfs(3)>.");
742 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
743 [InitNone, Always, TestOutputIntOp (
744 [["get_pid"]], ">=", 1)],
745 "get PID of qemu subprocess",
747 Return the process ID of the qemu subprocess. If there is no
748 qemu subprocess, then this will return an error.
750 This is an internal call used for debugging and testing.");
752 ("version", (RStruct ("version", "version"), []), -1, [],
753 [InitNone, Always, TestOutputStruct (
754 [["version"]], [CompareWithInt ("major", 1)])],
755 "get the library version number",
757 Return the libguestfs version number that the program is linked
760 Note that because of dynamic linking this is not necessarily
761 the version of libguestfs that you compiled against. You can
762 compile the program, and then at runtime dynamically link
763 against a completely different C<libguestfs.so> library.
765 This call was added in version C<1.0.58>. In previous
766 versions of libguestfs there was no way to get the version
767 number. From C code you can use ELF weak linking tricks to find out if
768 this symbol exists (if it doesn't, then it's an earlier version).
770 The call returns a structure with four elements. The first
771 three (C<major>, C<minor> and C<release>) are numbers and
772 correspond to the usual version triplet. The fourth element
773 (C<extra>) is a string and is normally empty, but may be
774 used for distro-specific information.
776 To construct the original version string:
777 C<$major.$minor.$release$extra>
779 I<Note:> Don't use this call to test for availability
780 of features. Distro backports makes this unreliable.");
782 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
783 [InitNone, Always, TestOutputTrue (
784 [["set_selinux"; "true"];
786 "set SELinux enabled or disabled at appliance boot",
788 This sets the selinux flag that is passed to the appliance
789 at boot time. The default is C<selinux=0> (disabled).
791 Note that if SELinux is enabled, it is always in
792 Permissive mode (C<enforcing=0>).
794 For more information on the architecture of libguestfs,
795 see L<guestfs(3)>.");
797 ("get_selinux", (RBool "selinux", []), -1, [],
799 "get SELinux enabled flag",
801 This returns the current setting of the selinux flag which
802 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
804 For more information on the architecture of libguestfs,
805 see L<guestfs(3)>.");
809 (* daemon_functions are any functions which cause some action
810 * to take place in the daemon.
813 let daemon_functions = [
814 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
815 [InitEmpty, Always, TestOutput (
816 [["sfdiskM"; "/dev/sda"; ","];
817 ["mkfs"; "ext2"; "/dev/sda1"];
818 ["mount"; "/dev/sda1"; "/"];
819 ["write_file"; "/new"; "new file contents"; "0"];
820 ["cat"; "/new"]], "new file contents")],
821 "mount a guest disk at a position in the filesystem",
823 Mount a guest disk at a position in the filesystem. Block devices
824 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
825 the guest. If those block devices contain partitions, they will have
826 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
829 The rules are the same as for L<mount(2)>: A filesystem must
830 first be mounted on C</> before others can be mounted. Other
831 filesystems can only be mounted on directories which already
834 The mounted filesystem is writable, if we have sufficient permissions
835 on the underlying device.
837 The filesystem options C<sync> and C<noatime> are set with this
838 call, in order to improve reliability.");
840 ("sync", (RErr, []), 2, [],
841 [ InitEmpty, Always, TestRun [["sync"]]],
842 "sync disks, writes are flushed through to the disk image",
844 This syncs the disk, so that any writes are flushed through to the
845 underlying disk image.
847 You should always call this if you have modified a disk image, before
848 closing the handle.");
850 ("touch", (RErr, [Pathname "path"]), 3, [],
851 [InitBasicFS, Always, TestOutputTrue (
853 ["exists"; "/new"]])],
854 "update file timestamps or create a new file",
856 Touch acts like the L<touch(1)> command. It can be used to
857 update the timestamps on a file, or, if the file does not exist,
858 to create a new zero-length file.");
860 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
861 [InitSquashFS, Always, TestOutput (
862 [["cat"; "/known-2"]], "abcdef\n")],
863 "list the contents of a file",
865 Return the contents of the file named C<path>.
867 Note that this function cannot correctly handle binary files
868 (specifically, files containing C<\\0> character which is treated
869 as end of string). For those you need to use the C<guestfs_read_file>
870 or C<guestfs_download> functions which have a more complex interface.");
872 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
873 [], (* XXX Tricky to test because it depends on the exact format
874 * of the 'ls -l' command, which changes between F10 and F11.
876 "list the files in a directory (long format)",
878 List the files in C<directory> (relative to the root directory,
879 there is no cwd) in the format of 'ls -la'.
881 This command is mostly useful for interactive sessions. It
882 is I<not> intended that you try to parse the output string.");
884 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
885 [InitBasicFS, Always, TestOutputList (
888 ["touch"; "/newest"];
889 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
890 "list the files in a directory",
892 List the files in C<directory> (relative to the root directory,
893 there is no cwd). The '.' and '..' entries are not returned, but
894 hidden files are shown.
896 This command is mostly useful for interactive sessions. Programs
897 should probably use C<guestfs_readdir> instead.");
899 ("list_devices", (RStringList "devices", []), 7, [],
900 [InitEmpty, Always, TestOutputListOfDevices (
901 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
902 "list the block devices",
904 List all the block devices.
906 The full block device names are returned, eg. C</dev/sda>");
908 ("list_partitions", (RStringList "partitions", []), 8, [],
909 [InitBasicFS, Always, TestOutputListOfDevices (
910 [["list_partitions"]], ["/dev/sda1"]);
911 InitEmpty, Always, TestOutputListOfDevices (
912 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
913 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
914 "list the partitions",
916 List all the partitions detected on all block devices.
918 The full partition device names are returned, eg. C</dev/sda1>
920 This does not return logical volumes. For that you will need to
921 call C<guestfs_lvs>.");
923 ("pvs", (RStringList "physvols", []), 9, [],
924 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
925 [["pvs"]], ["/dev/sda1"]);
926 InitEmpty, Always, TestOutputListOfDevices (
927 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
928 ["pvcreate"; "/dev/sda1"];
929 ["pvcreate"; "/dev/sda2"];
930 ["pvcreate"; "/dev/sda3"];
931 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
932 "list the LVM physical volumes (PVs)",
934 List all the physical volumes detected. This is the equivalent
935 of the L<pvs(8)> command.
937 This returns a list of just the device names that contain
938 PVs (eg. C</dev/sda2>).
940 See also C<guestfs_pvs_full>.");
942 ("vgs", (RStringList "volgroups", []), 10, [],
943 [InitBasicFSonLVM, Always, TestOutputList (
945 InitEmpty, Always, TestOutputList (
946 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
947 ["pvcreate"; "/dev/sda1"];
948 ["pvcreate"; "/dev/sda2"];
949 ["pvcreate"; "/dev/sda3"];
950 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
951 ["vgcreate"; "VG2"; "/dev/sda3"];
952 ["vgs"]], ["VG1"; "VG2"])],
953 "list the LVM volume groups (VGs)",
955 List all the volumes groups detected. This is the equivalent
956 of the L<vgs(8)> command.
958 This returns a list of just the volume group names that were
959 detected (eg. C<VolGroup00>).
961 See also C<guestfs_vgs_full>.");
963 ("lvs", (RStringList "logvols", []), 11, [],
964 [InitBasicFSonLVM, Always, TestOutputList (
965 [["lvs"]], ["/dev/VG/LV"]);
966 InitEmpty, Always, TestOutputList (
967 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
968 ["pvcreate"; "/dev/sda1"];
969 ["pvcreate"; "/dev/sda2"];
970 ["pvcreate"; "/dev/sda3"];
971 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
972 ["vgcreate"; "VG2"; "/dev/sda3"];
973 ["lvcreate"; "LV1"; "VG1"; "50"];
974 ["lvcreate"; "LV2"; "VG1"; "50"];
975 ["lvcreate"; "LV3"; "VG2"; "50"];
976 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
977 "list the LVM logical volumes (LVs)",
979 List all the logical volumes detected. This is the equivalent
980 of the L<lvs(8)> command.
982 This returns a list of the logical volume device names
983 (eg. C</dev/VolGroup00/LogVol00>).
985 See also C<guestfs_lvs_full>.");
987 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
988 [], (* XXX how to test? *)
989 "list the LVM physical volumes (PVs)",
991 List all the physical volumes detected. This is the equivalent
992 of the L<pvs(8)> command. The \"full\" version includes all fields.");
994 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
995 [], (* XXX how to test? *)
996 "list the LVM volume groups (VGs)",
998 List all the volumes groups detected. This is the equivalent
999 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1001 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1002 [], (* XXX how to test? *)
1003 "list the LVM logical volumes (LVs)",
1005 List all the logical volumes detected. This is the equivalent
1006 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1008 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1009 [InitSquashFS, Always, TestOutputList (
1010 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1011 InitSquashFS, Always, TestOutputList (
1012 [["read_lines"; "/empty"]], [])],
1013 "read file as lines",
1015 Return the contents of the file named C<path>.
1017 The file contents are returned as a list of lines. Trailing
1018 C<LF> and C<CRLF> character sequences are I<not> returned.
1020 Note that this function cannot correctly handle binary files
1021 (specifically, files containing C<\\0> character which is treated
1022 as end of line). For those you need to use the C<guestfs_read_file>
1023 function which has a more complex interface.");
1025 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1026 [], (* XXX Augeas code needs tests. *)
1027 "create a new Augeas handle",
1029 Create a new Augeas handle for editing configuration files.
1030 If there was any previous Augeas handle associated with this
1031 guestfs session, then it is closed.
1033 You must call this before using any other C<guestfs_aug_*>
1036 C<root> is the filesystem root. C<root> must not be NULL,
1039 The flags are the same as the flags defined in
1040 E<lt>augeas.hE<gt>, the logical I<or> of the following
1045 =item C<AUG_SAVE_BACKUP> = 1
1047 Keep the original file with a C<.augsave> extension.
1049 =item C<AUG_SAVE_NEWFILE> = 2
1051 Save changes into a file with extension C<.augnew>, and
1052 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1054 =item C<AUG_TYPE_CHECK> = 4
1056 Typecheck lenses (can be expensive).
1058 =item C<AUG_NO_STDINC> = 8
1060 Do not use standard load path for modules.
1062 =item C<AUG_SAVE_NOOP> = 16
1064 Make save a no-op, just record what would have been changed.
1066 =item C<AUG_NO_LOAD> = 32
1068 Do not load the tree in C<guestfs_aug_init>.
1072 To close the handle, you can call C<guestfs_aug_close>.
1074 To find out more about Augeas, see L<http://augeas.net/>.");
1076 ("aug_close", (RErr, []), 26, [],
1077 [], (* XXX Augeas code needs tests. *)
1078 "close the current Augeas handle",
1080 Close the current Augeas handle and free up any resources
1081 used by it. After calling this, you have to call
1082 C<guestfs_aug_init> again before you can use any other
1083 Augeas functions.");
1085 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1086 [], (* XXX Augeas code needs tests. *)
1087 "define an Augeas variable",
1089 Defines an Augeas variable C<name> whose value is the result
1090 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1093 On success this returns the number of nodes in C<expr>, or
1094 C<0> if C<expr> evaluates to something which is not a nodeset.");
1096 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1097 [], (* XXX Augeas code needs tests. *)
1098 "define an Augeas node",
1100 Defines a variable C<name> whose value is the result of
1103 If C<expr> evaluates to an empty nodeset, a node is created,
1104 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1105 C<name> will be the nodeset containing that single node.
1107 On success this returns a pair containing the
1108 number of nodes in the nodeset, and a boolean flag
1109 if a node was created.");
1111 ("aug_get", (RString "val", [String "augpath"]), 19, [],
1112 [], (* XXX Augeas code needs tests. *)
1113 "look up the value of an Augeas path",
1115 Look up the value associated with C<path>. If C<path>
1116 matches exactly one node, the C<value> is returned.");
1118 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1119 [], (* XXX Augeas code needs tests. *)
1120 "set Augeas path to value",
1122 Set the value associated with C<path> to C<value>.");
1124 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1125 [], (* XXX Augeas code needs tests. *)
1126 "insert a sibling Augeas node",
1128 Create a new sibling C<label> for C<path>, inserting it into
1129 the tree before or after C<path> (depending on the boolean
1132 C<path> must match exactly one existing node in the tree, and
1133 C<label> must be a label, ie. not contain C</>, C<*> or end
1134 with a bracketed index C<[N]>.");
1136 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1137 [], (* XXX Augeas code needs tests. *)
1138 "remove an Augeas path",
1140 Remove C<path> and all of its children.
1142 On success this returns the number of entries which were removed.");
1144 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1145 [], (* XXX Augeas code needs tests. *)
1148 Move the node C<src> to C<dest>. C<src> must match exactly
1149 one node. C<dest> is overwritten if it exists.");
1151 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1152 [], (* XXX Augeas code needs tests. *)
1153 "return Augeas nodes which match augpath",
1155 Returns a list of paths which match the path expression C<path>.
1156 The returned paths are sufficiently qualified so that they match
1157 exactly one node in the current tree.");
1159 ("aug_save", (RErr, []), 25, [],
1160 [], (* XXX Augeas code needs tests. *)
1161 "write all pending Augeas changes to disk",
1163 This writes all pending changes to disk.
1165 The flags which were passed to C<guestfs_aug_init> affect exactly
1166 how files are saved.");
1168 ("aug_load", (RErr, []), 27, [],
1169 [], (* XXX Augeas code needs tests. *)
1170 "load files into the tree",
1172 Load files into the tree.
1174 See C<aug_load> in the Augeas documentation for the full gory
1177 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1178 [], (* XXX Augeas code needs tests. *)
1179 "list Augeas nodes under augpath",
1181 This is just a shortcut for listing C<guestfs_aug_match>
1182 C<path/*> and sorting the resulting nodes into alphabetical order.");
1184 ("rm", (RErr, [Pathname "path"]), 29, [],
1185 [InitBasicFS, Always, TestRun
1188 InitBasicFS, Always, TestLastFail
1190 InitBasicFS, Always, TestLastFail
1195 Remove the single file C<path>.");
1197 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1198 [InitBasicFS, Always, TestRun
1201 InitBasicFS, Always, TestLastFail
1202 [["rmdir"; "/new"]];
1203 InitBasicFS, Always, TestLastFail
1205 ["rmdir"; "/new"]]],
1206 "remove a directory",
1208 Remove the single directory C<path>.");
1210 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1211 [InitBasicFS, Always, TestOutputFalse
1213 ["mkdir"; "/new/foo"];
1214 ["touch"; "/new/foo/bar"];
1216 ["exists"; "/new"]]],
1217 "remove a file or directory recursively",
1219 Remove the file or directory C<path>, recursively removing the
1220 contents if its a directory. This is like the C<rm -rf> shell
1223 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1224 [InitBasicFS, Always, TestOutputTrue
1226 ["is_dir"; "/new"]];
1227 InitBasicFS, Always, TestLastFail
1228 [["mkdir"; "/new/foo/bar"]]],
1229 "create a directory",
1231 Create a directory named C<path>.");
1233 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1234 [InitBasicFS, Always, TestOutputTrue
1235 [["mkdir_p"; "/new/foo/bar"];
1236 ["is_dir"; "/new/foo/bar"]];
1237 InitBasicFS, Always, TestOutputTrue
1238 [["mkdir_p"; "/new/foo/bar"];
1239 ["is_dir"; "/new/foo"]];
1240 InitBasicFS, Always, TestOutputTrue
1241 [["mkdir_p"; "/new/foo/bar"];
1242 ["is_dir"; "/new"]];
1243 (* Regression tests for RHBZ#503133: *)
1244 InitBasicFS, Always, TestRun
1246 ["mkdir_p"; "/new"]];
1247 InitBasicFS, Always, TestLastFail
1249 ["mkdir_p"; "/new"]]],
1250 "create a directory and parents",
1252 Create a directory named C<path>, creating any parent directories
1253 as necessary. This is like the C<mkdir -p> shell command.");
1255 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1256 [], (* XXX Need stat command to test *)
1259 Change the mode (permissions) of C<path> to C<mode>. Only
1260 numeric modes are supported.");
1262 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1263 [], (* XXX Need stat command to test *)
1264 "change file owner and group",
1266 Change the file owner to C<owner> and group to C<group>.
1268 Only numeric uid and gid are supported. If you want to use
1269 names, you will need to locate and parse the password file
1270 yourself (Augeas support makes this relatively easy).");
1272 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1273 [InitSquashFS, Always, TestOutputTrue (
1274 [["exists"; "/empty"]]);
1275 InitSquashFS, Always, TestOutputTrue (
1276 [["exists"; "/directory"]])],
1277 "test if file or directory exists",
1279 This returns C<true> if and only if there is a file, directory
1280 (or anything) with the given C<path> name.
1282 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1284 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1285 [InitSquashFS, Always, TestOutputTrue (
1286 [["is_file"; "/known-1"]]);
1287 InitSquashFS, Always, TestOutputFalse (
1288 [["is_file"; "/directory"]])],
1289 "test if file exists",
1291 This returns C<true> if and only if there is a file
1292 with the given C<path> name. Note that it returns false for
1293 other objects like directories.
1295 See also C<guestfs_stat>.");
1297 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1298 [InitSquashFS, Always, TestOutputFalse (
1299 [["is_dir"; "/known-3"]]);
1300 InitSquashFS, Always, TestOutputTrue (
1301 [["is_dir"; "/directory"]])],
1302 "test if file exists",
1304 This returns C<true> if and only if there is a directory
1305 with the given C<path> name. Note that it returns false for
1306 other objects like files.
1308 See also C<guestfs_stat>.");
1310 ("pvcreate", (RErr, [Device "device"]), 39, [],
1311 [InitEmpty, Always, TestOutputListOfDevices (
1312 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1313 ["pvcreate"; "/dev/sda1"];
1314 ["pvcreate"; "/dev/sda2"];
1315 ["pvcreate"; "/dev/sda3"];
1316 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1317 "create an LVM physical volume",
1319 This creates an LVM physical volume on the named C<device>,
1320 where C<device> should usually be a partition name such
1323 ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
1324 [InitEmpty, Always, TestOutputList (
1325 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1326 ["pvcreate"; "/dev/sda1"];
1327 ["pvcreate"; "/dev/sda2"];
1328 ["pvcreate"; "/dev/sda3"];
1329 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1330 ["vgcreate"; "VG2"; "/dev/sda3"];
1331 ["vgs"]], ["VG1"; "VG2"])],
1332 "create an LVM volume group",
1334 This creates an LVM volume group called C<volgroup>
1335 from the non-empty list of physical volumes C<physvols>.");
1337 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1338 [InitEmpty, Always, TestOutputList (
1339 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1340 ["pvcreate"; "/dev/sda1"];
1341 ["pvcreate"; "/dev/sda2"];
1342 ["pvcreate"; "/dev/sda3"];
1343 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1344 ["vgcreate"; "VG2"; "/dev/sda3"];
1345 ["lvcreate"; "LV1"; "VG1"; "50"];
1346 ["lvcreate"; "LV2"; "VG1"; "50"];
1347 ["lvcreate"; "LV3"; "VG2"; "50"];
1348 ["lvcreate"; "LV4"; "VG2"; "50"];
1349 ["lvcreate"; "LV5"; "VG2"; "50"];
1351 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1352 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1353 "create an LVM volume group",
1355 This creates an LVM volume group called C<logvol>
1356 on the volume group C<volgroup>, with C<size> megabytes.");
1358 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1359 [InitEmpty, Always, TestOutput (
1360 [["sfdiskM"; "/dev/sda"; ","];
1361 ["mkfs"; "ext2"; "/dev/sda1"];
1362 ["mount"; "/dev/sda1"; "/"];
1363 ["write_file"; "/new"; "new file contents"; "0"];
1364 ["cat"; "/new"]], "new file contents")],
1365 "make a filesystem",
1367 This creates a filesystem on C<device> (usually a partition
1368 or LVM logical volume). The filesystem type is C<fstype>, for
1371 ("sfdisk", (RErr, [Device "device";
1372 Int "cyls"; Int "heads"; Int "sectors";
1373 StringList "lines"]), 43, [DangerWillRobinson],
1375 "create partitions on a block device",
1377 This is a direct interface to the L<sfdisk(8)> program for creating
1378 partitions on block devices.
1380 C<device> should be a block device, for example C</dev/sda>.
1382 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1383 and sectors on the device, which are passed directly to sfdisk as
1384 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1385 of these, then the corresponding parameter is omitted. Usually for
1386 'large' disks, you can just pass C<0> for these, but for small
1387 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1388 out the right geometry and you will need to tell it.
1390 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1391 information refer to the L<sfdisk(8)> manpage.
1393 To create a single partition occupying the whole disk, you would
1394 pass C<lines> as a single element list, when the single element being
1395 the string C<,> (comma).
1397 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1399 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1400 [InitBasicFS, Always, TestOutput (
1401 [["write_file"; "/new"; "new file contents"; "0"];
1402 ["cat"; "/new"]], "new file contents");
1403 InitBasicFS, Always, TestOutput (
1404 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1405 ["cat"; "/new"]], "\nnew file contents\n");
1406 InitBasicFS, Always, TestOutput (
1407 [["write_file"; "/new"; "\n\n"; "0"];
1408 ["cat"; "/new"]], "\n\n");
1409 InitBasicFS, Always, TestOutput (
1410 [["write_file"; "/new"; ""; "0"];
1411 ["cat"; "/new"]], "");
1412 InitBasicFS, Always, TestOutput (
1413 [["write_file"; "/new"; "\n\n\n"; "0"];
1414 ["cat"; "/new"]], "\n\n\n");
1415 InitBasicFS, Always, TestOutput (
1416 [["write_file"; "/new"; "\n"; "0"];
1417 ["cat"; "/new"]], "\n")],
1420 This call creates a file called C<path>. The contents of the
1421 file is the string C<content> (which can contain any 8 bit data),
1422 with length C<size>.
1424 As a special case, if C<size> is C<0>
1425 then the length is calculated using C<strlen> (so in this case
1426 the content cannot contain embedded ASCII NULs).
1428 I<NB.> Owing to a bug, writing content containing ASCII NUL
1429 characters does I<not> work, even if the length is specified.
1430 We hope to resolve this bug in a future version. In the meantime
1431 use C<guestfs_upload>.");
1433 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1434 [InitEmpty, Always, TestOutputListOfDevices (
1435 [["sfdiskM"; "/dev/sda"; ","];
1436 ["mkfs"; "ext2"; "/dev/sda1"];
1437 ["mount"; "/dev/sda1"; "/"];
1438 ["mounts"]], ["/dev/sda1"]);
1439 InitEmpty, Always, TestOutputList (
1440 [["sfdiskM"; "/dev/sda"; ","];
1441 ["mkfs"; "ext2"; "/dev/sda1"];
1442 ["mount"; "/dev/sda1"; "/"];
1445 "unmount a filesystem",
1447 This unmounts the given filesystem. The filesystem may be
1448 specified either by its mountpoint (path) or the device which
1449 contains the filesystem.");
1451 ("mounts", (RStringList "devices", []), 46, [],
1452 [InitBasicFS, Always, TestOutputListOfDevices (
1453 [["mounts"]], ["/dev/sda1"])],
1454 "show mounted filesystems",
1456 This returns the list of currently mounted filesystems. It returns
1457 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1459 Some internal mounts are not shown.
1461 See also: C<guestfs_mountpoints>");
1463 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1464 [InitBasicFS, Always, TestOutputList (
1467 (* check that umount_all can unmount nested mounts correctly: *)
1468 InitEmpty, Always, TestOutputList (
1469 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1470 ["mkfs"; "ext2"; "/dev/sda1"];
1471 ["mkfs"; "ext2"; "/dev/sda2"];
1472 ["mkfs"; "ext2"; "/dev/sda3"];
1473 ["mount"; "/dev/sda1"; "/"];
1475 ["mount"; "/dev/sda2"; "/mp1"];
1476 ["mkdir"; "/mp1/mp2"];
1477 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1478 ["mkdir"; "/mp1/mp2/mp3"];
1481 "unmount all filesystems",
1483 This unmounts all mounted filesystems.
1485 Some internal mounts are not unmounted by this call.");
1487 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1489 "remove all LVM LVs, VGs and PVs",
1491 This command removes all LVM logical volumes, volume groups
1492 and physical volumes.");
1494 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1495 [InitSquashFS, Always, TestOutput (
1496 [["file"; "/empty"]], "empty");
1497 InitSquashFS, Always, TestOutput (
1498 [["file"; "/known-1"]], "ASCII text");
1499 InitSquashFS, Always, TestLastFail (
1500 [["file"; "/notexists"]])],
1501 "determine file type",
1503 This call uses the standard L<file(1)> command to determine
1504 the type or contents of the file. This also works on devices,
1505 for example to find out whether a partition contains a filesystem.
1507 This call will also transparently look inside various types
1510 The exact command which runs is C<file -zbsL path>. Note in
1511 particular that the filename is not prepended to the output
1512 (the C<-b> option).");
1514 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1515 [InitBasicFS, Always, TestOutput (
1516 [["upload"; "test-command"; "/test-command"];
1517 ["chmod"; "0o755"; "/test-command"];
1518 ["command"; "/test-command 1"]], "Result1");
1519 InitBasicFS, Always, TestOutput (
1520 [["upload"; "test-command"; "/test-command"];
1521 ["chmod"; "0o755"; "/test-command"];
1522 ["command"; "/test-command 2"]], "Result2\n");
1523 InitBasicFS, Always, TestOutput (
1524 [["upload"; "test-command"; "/test-command"];
1525 ["chmod"; "0o755"; "/test-command"];
1526 ["command"; "/test-command 3"]], "\nResult3");
1527 InitBasicFS, Always, TestOutput (
1528 [["upload"; "test-command"; "/test-command"];
1529 ["chmod"; "0o755"; "/test-command"];
1530 ["command"; "/test-command 4"]], "\nResult4\n");
1531 InitBasicFS, Always, TestOutput (
1532 [["upload"; "test-command"; "/test-command"];
1533 ["chmod"; "0o755"; "/test-command"];
1534 ["command"; "/test-command 5"]], "\nResult5\n\n");
1535 InitBasicFS, Always, TestOutput (
1536 [["upload"; "test-command"; "/test-command"];
1537 ["chmod"; "0o755"; "/test-command"];
1538 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1539 InitBasicFS, Always, TestOutput (
1540 [["upload"; "test-command"; "/test-command"];
1541 ["chmod"; "0o755"; "/test-command"];
1542 ["command"; "/test-command 7"]], "");
1543 InitBasicFS, Always, TestOutput (
1544 [["upload"; "test-command"; "/test-command"];
1545 ["chmod"; "0o755"; "/test-command"];
1546 ["command"; "/test-command 8"]], "\n");
1547 InitBasicFS, Always, TestOutput (
1548 [["upload"; "test-command"; "/test-command"];
1549 ["chmod"; "0o755"; "/test-command"];
1550 ["command"; "/test-command 9"]], "\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["upload"; "test-command"; "/test-command"];
1553 ["chmod"; "0o755"; "/test-command"];
1554 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1555 InitBasicFS, Always, TestOutput (
1556 [["upload"; "test-command"; "/test-command"];
1557 ["chmod"; "0o755"; "/test-command"];
1558 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1559 InitBasicFS, Always, TestLastFail (
1560 [["upload"; "test-command"; "/test-command"];
1561 ["chmod"; "0o755"; "/test-command"];
1562 ["command"; "/test-command"]])],
1563 "run a command from the guest filesystem",
1565 This call runs a command from the guest filesystem. The
1566 filesystem must be mounted, and must contain a compatible
1567 operating system (ie. something Linux, with the same
1568 or compatible processor architecture).
1570 The single parameter is an argv-style list of arguments.
1571 The first element is the name of the program to run.
1572 Subsequent elements are parameters. The list must be
1573 non-empty (ie. must contain a program name). Note that
1574 the command runs directly, and is I<not> invoked via
1575 the shell (see C<guestfs_sh>).
1577 The return value is anything printed to I<stdout> by
1580 If the command returns a non-zero exit status, then
1581 this function returns an error message. The error message
1582 string is the content of I<stderr> from the command.
1584 The C<$PATH> environment variable will contain at least
1585 C</usr/bin> and C</bin>. If you require a program from
1586 another location, you should provide the full path in the
1589 Shared libraries and data files required by the program
1590 must be available on filesystems which are mounted in the
1591 correct places. It is the caller's responsibility to ensure
1592 all filesystems that are needed are mounted at the right
1595 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1596 [InitBasicFS, Always, TestOutputList (
1597 [["upload"; "test-command"; "/test-command"];
1598 ["chmod"; "0o755"; "/test-command"];
1599 ["command_lines"; "/test-command 1"]], ["Result1"]);
1600 InitBasicFS, Always, TestOutputList (
1601 [["upload"; "test-command"; "/test-command"];
1602 ["chmod"; "0o755"; "/test-command"];
1603 ["command_lines"; "/test-command 2"]], ["Result2"]);
1604 InitBasicFS, Always, TestOutputList (
1605 [["upload"; "test-command"; "/test-command"];
1606 ["chmod"; "0o755"; "/test-command"];
1607 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1608 InitBasicFS, Always, TestOutputList (
1609 [["upload"; "test-command"; "/test-command"];
1610 ["chmod"; "0o755"; "/test-command"];
1611 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1612 InitBasicFS, Always, TestOutputList (
1613 [["upload"; "test-command"; "/test-command"];
1614 ["chmod"; "0o755"; "/test-command"];
1615 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1616 InitBasicFS, Always, TestOutputList (
1617 [["upload"; "test-command"; "/test-command"];
1618 ["chmod"; "0o755"; "/test-command"];
1619 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1620 InitBasicFS, Always, TestOutputList (
1621 [["upload"; "test-command"; "/test-command"];
1622 ["chmod"; "0o755"; "/test-command"];
1623 ["command_lines"; "/test-command 7"]], []);
1624 InitBasicFS, Always, TestOutputList (
1625 [["upload"; "test-command"; "/test-command"];
1626 ["chmod"; "0o755"; "/test-command"];
1627 ["command_lines"; "/test-command 8"]], [""]);
1628 InitBasicFS, Always, TestOutputList (
1629 [["upload"; "test-command"; "/test-command"];
1630 ["chmod"; "0o755"; "/test-command"];
1631 ["command_lines"; "/test-command 9"]], ["";""]);
1632 InitBasicFS, Always, TestOutputList (
1633 [["upload"; "test-command"; "/test-command"];
1634 ["chmod"; "0o755"; "/test-command"];
1635 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1636 InitBasicFS, Always, TestOutputList (
1637 [["upload"; "test-command"; "/test-command"];
1638 ["chmod"; "0o755"; "/test-command"];
1639 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1640 "run a command, returning lines",
1642 This is the same as C<guestfs_command>, but splits the
1643 result into a list of lines.
1645 See also: C<guestfs_sh_lines>");
1647 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1648 [InitSquashFS, Always, TestOutputStruct (
1649 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1650 "get file information",
1652 Returns file information for the given C<path>.
1654 This is the same as the C<stat(2)> system call.");
1656 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1657 [InitSquashFS, Always, TestOutputStruct (
1658 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1659 "get file information for a symbolic link",
1661 Returns file information for the given C<path>.
1663 This is the same as C<guestfs_stat> except that if C<path>
1664 is a symbolic link, then the link is stat-ed, not the file it
1667 This is the same as the C<lstat(2)> system call.");
1669 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1670 [InitSquashFS, Always, TestOutputStruct (
1671 [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
1672 "get file system statistics",
1674 Returns file system statistics for any mounted file system.
1675 C<path> should be a file or directory in the mounted file system
1676 (typically it is the mount point itself, but it doesn't need to be).
1678 This is the same as the C<statvfs(2)> system call.");
1680 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1682 "get ext2/ext3/ext4 superblock details",
1684 This returns the contents of the ext2, ext3 or ext4 filesystem
1685 superblock on C<device>.
1687 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1688 manpage for more details. The list of fields returned isn't
1689 clearly defined, and depends on both the version of C<tune2fs>
1690 that libguestfs was built against, and the filesystem itself.");
1692 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1693 [InitEmpty, Always, TestOutputTrue (
1694 [["blockdev_setro"; "/dev/sda"];
1695 ["blockdev_getro"; "/dev/sda"]])],
1696 "set block device to read-only",
1698 Sets the block device named C<device> to read-only.
1700 This uses the L<blockdev(8)> command.");
1702 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1703 [InitEmpty, Always, TestOutputFalse (
1704 [["blockdev_setrw"; "/dev/sda"];
1705 ["blockdev_getro"; "/dev/sda"]])],
1706 "set block device to read-write",
1708 Sets the block device named C<device> to read-write.
1710 This uses the L<blockdev(8)> command.");
1712 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1713 [InitEmpty, Always, TestOutputTrue (
1714 [["blockdev_setro"; "/dev/sda"];
1715 ["blockdev_getro"; "/dev/sda"]])],
1716 "is block device set to read-only",
1718 Returns a boolean indicating if the block device is read-only
1719 (true if read-only, false if not).
1721 This uses the L<blockdev(8)> command.");
1723 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1724 [InitEmpty, Always, TestOutputInt (
1725 [["blockdev_getss"; "/dev/sda"]], 512)],
1726 "get sectorsize of block device",
1728 This returns the size of sectors on a block device.
1729 Usually 512, but can be larger for modern devices.
1731 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1734 This uses the L<blockdev(8)> command.");
1736 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1737 [InitEmpty, Always, TestOutputInt (
1738 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1739 "get blocksize of block device",
1741 This returns the block size of a device.
1743 (Note this is different from both I<size in blocks> and
1744 I<filesystem block size>).
1746 This uses the L<blockdev(8)> command.");
1748 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1750 "set blocksize of block device",
1752 This sets the block size of a device.
1754 (Note this is different from both I<size in blocks> and
1755 I<filesystem block size>).
1757 This uses the L<blockdev(8)> command.");
1759 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1760 [InitEmpty, Always, TestOutputInt (
1761 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1762 "get total size of device in 512-byte sectors",
1764 This returns the size of the device in units of 512-byte sectors
1765 (even if the sectorsize isn't 512 bytes ... weird).
1767 See also C<guestfs_blockdev_getss> for the real sector size of
1768 the device, and C<guestfs_blockdev_getsize64> for the more
1769 useful I<size in bytes>.
1771 This uses the L<blockdev(8)> command.");
1773 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1774 [InitEmpty, Always, TestOutputInt (
1775 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1776 "get total size of device in bytes",
1778 This returns the size of the device in bytes.
1780 See also C<guestfs_blockdev_getsz>.
1782 This uses the L<blockdev(8)> command.");
1784 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1785 [InitEmpty, Always, TestRun
1786 [["blockdev_flushbufs"; "/dev/sda"]]],
1787 "flush device buffers",
1789 This tells the kernel to flush internal buffers associated
1792 This uses the L<blockdev(8)> command.");
1794 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1795 [InitEmpty, Always, TestRun
1796 [["blockdev_rereadpt"; "/dev/sda"]]],
1797 "reread partition table",
1799 Reread the partition table on C<device>.
1801 This uses the L<blockdev(8)> command.");
1803 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1804 [InitBasicFS, Always, TestOutput (
1805 (* Pick a file from cwd which isn't likely to change. *)
1806 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1807 ["checksum"; "md5"; "/COPYING.LIB"]],
1808 Digest.to_hex (Digest.file "COPYING.LIB"))],
1809 "upload a file from the local machine",
1811 Upload local file C<filename> to C<remotefilename> on the
1814 C<filename> can also be a named pipe.
1816 See also C<guestfs_download>.");
1818 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1819 [InitBasicFS, Always, TestOutput (
1820 (* Pick a file from cwd which isn't likely to change. *)
1821 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1822 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1823 ["upload"; "testdownload.tmp"; "/upload"];
1824 ["checksum"; "md5"; "/upload"]],
1825 Digest.to_hex (Digest.file "COPYING.LIB"))],
1826 "download a file to the local machine",
1828 Download file C<remotefilename> and save it as C<filename>
1829 on the local machine.
1831 C<filename> can also be a named pipe.
1833 See also C<guestfs_upload>, C<guestfs_cat>.");
1835 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1836 [InitSquashFS, Always, TestOutput (
1837 [["checksum"; "crc"; "/known-3"]], "2891671662");
1838 InitSquashFS, Always, TestLastFail (
1839 [["checksum"; "crc"; "/notexists"]]);
1840 InitSquashFS, Always, TestOutput (
1841 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1842 InitSquashFS, Always, TestOutput (
1843 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1844 InitSquashFS, Always, TestOutput (
1845 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1846 InitSquashFS, Always, TestOutput (
1847 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1848 InitSquashFS, Always, TestOutput (
1849 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1850 InitSquashFS, Always, TestOutput (
1851 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1852 "compute MD5, SHAx or CRC checksum of file",
1854 This call computes the MD5, SHAx or CRC checksum of the
1857 The type of checksum to compute is given by the C<csumtype>
1858 parameter which must have one of the following values:
1864 Compute the cyclic redundancy check (CRC) specified by POSIX
1865 for the C<cksum> command.
1869 Compute the MD5 hash (using the C<md5sum> program).
1873 Compute the SHA1 hash (using the C<sha1sum> program).
1877 Compute the SHA224 hash (using the C<sha224sum> program).
1881 Compute the SHA256 hash (using the C<sha256sum> program).
1885 Compute the SHA384 hash (using the C<sha384sum> program).
1889 Compute the SHA512 hash (using the C<sha512sum> program).
1893 The checksum is returned as a printable string.");
1895 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1896 [InitBasicFS, Always, TestOutput (
1897 [["tar_in"; "../images/helloworld.tar"; "/"];
1898 ["cat"; "/hello"]], "hello\n")],
1899 "unpack tarfile to directory",
1901 This command uploads and unpacks local file C<tarfile> (an
1902 I<uncompressed> tar file) into C<directory>.
1904 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1906 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1908 "pack directory into tarfile",
1910 This command packs the contents of C<directory> and downloads
1911 it to local file C<tarfile>.
1913 To download a compressed tarball, use C<guestfs_tgz_out>.");
1915 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1916 [InitBasicFS, Always, TestOutput (
1917 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1918 ["cat"; "/hello"]], "hello\n")],
1919 "unpack compressed tarball to directory",
1921 This command uploads and unpacks local file C<tarball> (a
1922 I<gzip compressed> tar file) into C<directory>.
1924 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1926 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1928 "pack directory into compressed tarball",
1930 This command packs the contents of C<directory> and downloads
1931 it to local file C<tarball>.
1933 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1935 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1936 [InitBasicFS, Always, TestLastFail (
1938 ["mount_ro"; "/dev/sda1"; "/"];
1939 ["touch"; "/new"]]);
1940 InitBasicFS, Always, TestOutput (
1941 [["write_file"; "/new"; "data"; "0"];
1943 ["mount_ro"; "/dev/sda1"; "/"];
1944 ["cat"; "/new"]], "data")],
1945 "mount a guest disk, read-only",
1947 This is the same as the C<guestfs_mount> command, but it
1948 mounts the filesystem with the read-only (I<-o ro>) flag.");
1950 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1952 "mount a guest disk with mount options",
1954 This is the same as the C<guestfs_mount> command, but it
1955 allows you to set the mount options as for the
1956 L<mount(8)> I<-o> flag.");
1958 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1960 "mount a guest disk with mount options and vfstype",
1962 This is the same as the C<guestfs_mount> command, but it
1963 allows you to set both the mount options and the vfstype
1964 as for the L<mount(8)> I<-o> and I<-t> flags.");
1966 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1968 "debugging and internals",
1970 The C<guestfs_debug> command exposes some internals of
1971 C<guestfsd> (the guestfs daemon) that runs inside the
1974 There is no comprehensive help for this command. You have
1975 to look at the file C<daemon/debug.c> in the libguestfs source
1976 to find out what you can do.");
1978 ("lvremove", (RErr, [Device "device"]), 77, [],
1979 [InitEmpty, Always, TestOutputList (
1980 [["sfdiskM"; "/dev/sda"; ","];
1981 ["pvcreate"; "/dev/sda1"];
1982 ["vgcreate"; "VG"; "/dev/sda1"];
1983 ["lvcreate"; "LV1"; "VG"; "50"];
1984 ["lvcreate"; "LV2"; "VG"; "50"];
1985 ["lvremove"; "/dev/VG/LV1"];
1986 ["lvs"]], ["/dev/VG/LV2"]);
1987 InitEmpty, Always, TestOutputList (
1988 [["sfdiskM"; "/dev/sda"; ","];
1989 ["pvcreate"; "/dev/sda1"];
1990 ["vgcreate"; "VG"; "/dev/sda1"];
1991 ["lvcreate"; "LV1"; "VG"; "50"];
1992 ["lvcreate"; "LV2"; "VG"; "50"];
1993 ["lvremove"; "/dev/VG"];
1995 InitEmpty, Always, TestOutputList (
1996 [["sfdiskM"; "/dev/sda"; ","];
1997 ["pvcreate"; "/dev/sda1"];
1998 ["vgcreate"; "VG"; "/dev/sda1"];
1999 ["lvcreate"; "LV1"; "VG"; "50"];
2000 ["lvcreate"; "LV2"; "VG"; "50"];
2001 ["lvremove"; "/dev/VG"];
2003 "remove an LVM logical volume",
2005 Remove an LVM logical volume C<device>, where C<device> is
2006 the path to the LV, such as C</dev/VG/LV>.
2008 You can also remove all LVs in a volume group by specifying
2009 the VG name, C</dev/VG>.");
2011 ("vgremove", (RErr, [String "vgname"]), 78, [],
2012 [InitEmpty, Always, TestOutputList (
2013 [["sfdiskM"; "/dev/sda"; ","];
2014 ["pvcreate"; "/dev/sda1"];
2015 ["vgcreate"; "VG"; "/dev/sda1"];
2016 ["lvcreate"; "LV1"; "VG"; "50"];
2017 ["lvcreate"; "LV2"; "VG"; "50"];
2020 InitEmpty, Always, TestOutputList (
2021 [["sfdiskM"; "/dev/sda"; ","];
2022 ["pvcreate"; "/dev/sda1"];
2023 ["vgcreate"; "VG"; "/dev/sda1"];
2024 ["lvcreate"; "LV1"; "VG"; "50"];
2025 ["lvcreate"; "LV2"; "VG"; "50"];
2028 "remove an LVM volume group",
2030 Remove an LVM volume group C<vgname>, (for example C<VG>).
2032 This also forcibly removes all logical volumes in the volume
2035 ("pvremove", (RErr, [Device "device"]), 79, [],
2036 [InitEmpty, Always, TestOutputListOfDevices (
2037 [["sfdiskM"; "/dev/sda"; ","];
2038 ["pvcreate"; "/dev/sda1"];
2039 ["vgcreate"; "VG"; "/dev/sda1"];
2040 ["lvcreate"; "LV1"; "VG"; "50"];
2041 ["lvcreate"; "LV2"; "VG"; "50"];
2043 ["pvremove"; "/dev/sda1"];
2045 InitEmpty, Always, TestOutputListOfDevices (
2046 [["sfdiskM"; "/dev/sda"; ","];
2047 ["pvcreate"; "/dev/sda1"];
2048 ["vgcreate"; "VG"; "/dev/sda1"];
2049 ["lvcreate"; "LV1"; "VG"; "50"];
2050 ["lvcreate"; "LV2"; "VG"; "50"];
2052 ["pvremove"; "/dev/sda1"];
2054 InitEmpty, Always, TestOutputListOfDevices (
2055 [["sfdiskM"; "/dev/sda"; ","];
2056 ["pvcreate"; "/dev/sda1"];
2057 ["vgcreate"; "VG"; "/dev/sda1"];
2058 ["lvcreate"; "LV1"; "VG"; "50"];
2059 ["lvcreate"; "LV2"; "VG"; "50"];
2061 ["pvremove"; "/dev/sda1"];
2063 "remove an LVM physical volume",
2065 This wipes a physical volume C<device> so that LVM will no longer
2068 The implementation uses the C<pvremove> command which refuses to
2069 wipe physical volumes that contain any volume groups, so you have
2070 to remove those first.");
2072 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2073 [InitBasicFS, Always, TestOutput (
2074 [["set_e2label"; "/dev/sda1"; "testlabel"];
2075 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2076 "set the ext2/3/4 filesystem label",
2078 This sets the ext2/3/4 filesystem label of the filesystem on
2079 C<device> to C<label>. Filesystem labels are limited to
2082 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2083 to return the existing label on a filesystem.");
2085 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2087 "get the ext2/3/4 filesystem label",
2089 This returns the ext2/3/4 filesystem label of the filesystem on
2092 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2093 (let uuid = uuidgen () in
2094 [InitBasicFS, Always, TestOutput (
2095 [["set_e2uuid"; "/dev/sda1"; uuid];
2096 ["get_e2uuid"; "/dev/sda1"]], uuid);
2097 InitBasicFS, Always, TestOutput (
2098 [["set_e2uuid"; "/dev/sda1"; "clear"];
2099 ["get_e2uuid"; "/dev/sda1"]], "");
2100 (* We can't predict what UUIDs will be, so just check the commands run. *)
2101 InitBasicFS, Always, TestRun (
2102 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2103 InitBasicFS, Always, TestRun (
2104 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2105 "set the ext2/3/4 filesystem UUID",
2107 This sets the ext2/3/4 filesystem UUID of the filesystem on
2108 C<device> to C<uuid>. The format of the UUID and alternatives
2109 such as C<clear>, C<random> and C<time> are described in the
2110 L<tune2fs(8)> manpage.
2112 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2113 to return the existing UUID of a filesystem.");
2115 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2117 "get the ext2/3/4 filesystem UUID",
2119 This returns the ext2/3/4 filesystem UUID of the filesystem on
2122 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2123 [InitBasicFS, Always, TestOutputInt (
2124 [["umount"; "/dev/sda1"];
2125 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2126 InitBasicFS, Always, TestOutputInt (
2127 [["umount"; "/dev/sda1"];
2128 ["zero"; "/dev/sda1"];
2129 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2130 "run the filesystem checker",
2132 This runs the filesystem checker (fsck) on C<device> which
2133 should have filesystem type C<fstype>.
2135 The returned integer is the status. See L<fsck(8)> for the
2136 list of status codes from C<fsck>.
2144 Multiple status codes can be summed together.
2148 A non-zero return code can mean \"success\", for example if
2149 errors have been corrected on the filesystem.
2153 Checking or repairing NTFS volumes is not supported
2158 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2160 ("zero", (RErr, [Device "device"]), 85, [],
2161 [InitBasicFS, Always, TestOutput (
2162 [["umount"; "/dev/sda1"];
2163 ["zero"; "/dev/sda1"];
2164 ["file"; "/dev/sda1"]], "data")],
2165 "write zeroes to the device",
2167 This command writes zeroes over the first few blocks of C<device>.
2169 How many blocks are zeroed isn't specified (but it's I<not> enough
2170 to securely wipe the device). It should be sufficient to remove
2171 any partition tables, filesystem superblocks and so on.
2173 See also: C<guestfs_scrub_device>.");
2175 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2176 (* Test disabled because grub-install incompatible with virtio-blk driver.
2177 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2179 [InitBasicFS, Disabled, TestOutputTrue (
2180 [["grub_install"; "/"; "/dev/sda1"];
2181 ["is_dir"; "/boot"]])],
2184 This command installs GRUB (the Grand Unified Bootloader) on
2185 C<device>, with the root directory being C<root>.");
2187 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2188 [InitBasicFS, Always, TestOutput (
2189 [["write_file"; "/old"; "file content"; "0"];
2190 ["cp"; "/old"; "/new"];
2191 ["cat"; "/new"]], "file content");
2192 InitBasicFS, Always, TestOutputTrue (
2193 [["write_file"; "/old"; "file content"; "0"];
2194 ["cp"; "/old"; "/new"];
2195 ["is_file"; "/old"]]);
2196 InitBasicFS, Always, TestOutput (
2197 [["write_file"; "/old"; "file content"; "0"];
2199 ["cp"; "/old"; "/dir/new"];
2200 ["cat"; "/dir/new"]], "file content")],
2203 This copies a file from C<src> to C<dest> where C<dest> is
2204 either a destination filename or destination directory.");
2206 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2207 [InitBasicFS, Always, TestOutput (
2208 [["mkdir"; "/olddir"];
2209 ["mkdir"; "/newdir"];
2210 ["write_file"; "/olddir/file"; "file content"; "0"];
2211 ["cp_a"; "/olddir"; "/newdir"];
2212 ["cat"; "/newdir/olddir/file"]], "file content")],
2213 "copy a file or directory recursively",
2215 This copies a file or directory from C<src> to C<dest>
2216 recursively using the C<cp -a> command.");
2218 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2219 [InitBasicFS, Always, TestOutput (
2220 [["write_file"; "/old"; "file content"; "0"];
2221 ["mv"; "/old"; "/new"];
2222 ["cat"; "/new"]], "file content");
2223 InitBasicFS, Always, TestOutputFalse (
2224 [["write_file"; "/old"; "file content"; "0"];
2225 ["mv"; "/old"; "/new"];
2226 ["is_file"; "/old"]])],
2229 This moves a file from C<src> to C<dest> where C<dest> is
2230 either a destination filename or destination directory.");
2232 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2233 [InitEmpty, Always, TestRun (
2234 [["drop_caches"; "3"]])],
2235 "drop kernel page cache, dentries and inodes",
2237 This instructs the guest kernel to drop its page cache,
2238 and/or dentries and inode caches. The parameter C<whattodrop>
2239 tells the kernel what precisely to drop, see
2240 L<http://linux-mm.org/Drop_Caches>
2242 Setting C<whattodrop> to 3 should drop everything.
2244 This automatically calls L<sync(2)> before the operation,
2245 so that the maximum guest memory is freed.");
2247 ("dmesg", (RString "kmsgs", []), 91, [],
2248 [InitEmpty, Always, TestRun (
2250 "return kernel messages",
2252 This returns the kernel messages (C<dmesg> output) from
2253 the guest kernel. This is sometimes useful for extended
2254 debugging of problems.
2256 Another way to get the same information is to enable
2257 verbose messages with C<guestfs_set_verbose> or by setting
2258 the environment variable C<LIBGUESTFS_DEBUG=1> before
2259 running the program.");
2261 ("ping_daemon", (RErr, []), 92, [],
2262 [InitEmpty, Always, TestRun (
2263 [["ping_daemon"]])],
2264 "ping the guest daemon",
2266 This is a test probe into the guestfs daemon running inside
2267 the qemu subprocess. Calling this function checks that the
2268 daemon responds to the ping message, without affecting the daemon
2269 or attached block device(s) in any other way.");
2271 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2272 [InitBasicFS, Always, TestOutputTrue (
2273 [["write_file"; "/file1"; "contents of a file"; "0"];
2274 ["cp"; "/file1"; "/file2"];
2275 ["equal"; "/file1"; "/file2"]]);
2276 InitBasicFS, Always, TestOutputFalse (
2277 [["write_file"; "/file1"; "contents of a file"; "0"];
2278 ["write_file"; "/file2"; "contents of another file"; "0"];
2279 ["equal"; "/file1"; "/file2"]]);
2280 InitBasicFS, Always, TestLastFail (
2281 [["equal"; "/file1"; "/file2"]])],
2282 "test if two files have equal contents",
2284 This compares the two files C<file1> and C<file2> and returns
2285 true if their content is exactly equal, or false otherwise.
2287 The external L<cmp(1)> program is used for the comparison.");
2289 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2290 [InitSquashFS, Always, TestOutputList (
2291 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2292 InitSquashFS, Always, TestOutputList (
2293 [["strings"; "/empty"]], [])],
2294 "print the printable strings in a file",
2296 This runs the L<strings(1)> command on a file and returns
2297 the list of printable strings found.");
2299 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2300 [InitSquashFS, Always, TestOutputList (
2301 [["strings_e"; "b"; "/known-5"]], []);
2302 InitBasicFS, Disabled, TestOutputList (
2303 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2304 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2305 "print the printable strings in a file",
2307 This is like the C<guestfs_strings> command, but allows you to
2308 specify the encoding.
2310 See the L<strings(1)> manpage for the full list of encodings.
2312 Commonly useful encodings are C<l> (lower case L) which will
2313 show strings inside Windows/x86 files.
2315 The returned strings are transcoded to UTF-8.");
2317 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2318 [InitSquashFS, Always, TestOutput (
2319 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2320 (* Test for RHBZ#501888c2 regression which caused large hexdump
2321 * commands to segfault.
2323 InitSquashFS, Always, TestRun (
2324 [["hexdump"; "/100krandom"]])],
2325 "dump a file in hexadecimal",
2327 This runs C<hexdump -C> on the given C<path>. The result is
2328 the human-readable, canonical hex dump of the file.");
2330 ("zerofree", (RErr, [Device "device"]), 97, [],
2331 [InitNone, Always, TestOutput (
2332 [["sfdiskM"; "/dev/sda"; ","];
2333 ["mkfs"; "ext3"; "/dev/sda1"];
2334 ["mount"; "/dev/sda1"; "/"];
2335 ["write_file"; "/new"; "test file"; "0"];
2336 ["umount"; "/dev/sda1"];
2337 ["zerofree"; "/dev/sda1"];
2338 ["mount"; "/dev/sda1"; "/"];
2339 ["cat"; "/new"]], "test file")],
2340 "zero unused inodes and disk blocks on ext2/3 filesystem",
2342 This runs the I<zerofree> program on C<device>. This program
2343 claims to zero unused inodes and disk blocks on an ext2/3
2344 filesystem, thus making it possible to compress the filesystem
2347 You should B<not> run this program if the filesystem is
2350 It is possible that using this program can damage the filesystem
2351 or data on the filesystem.");
2353 ("pvresize", (RErr, [Device "device"]), 98, [],
2355 "resize an LVM physical volume",
2357 This resizes (expands or shrinks) an existing LVM physical
2358 volume to match the new size of the underlying device.");
2360 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2361 Int "cyls"; Int "heads"; Int "sectors";
2362 String "line"]), 99, [DangerWillRobinson],
2364 "modify a single partition on a block device",
2366 This runs L<sfdisk(8)> option to modify just the single
2367 partition C<n> (note: C<n> counts from 1).
2369 For other parameters, see C<guestfs_sfdisk>. You should usually
2370 pass C<0> for the cyls/heads/sectors parameters.");
2372 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2374 "display the partition table",
2376 This displays the partition table on C<device>, in the
2377 human-readable output of the L<sfdisk(8)> command. It is
2378 not intended to be parsed.");
2380 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2382 "display the kernel geometry",
2384 This displays the kernel's idea of the geometry of C<device>.
2386 The result is in human-readable format, and not designed to
2389 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2391 "display the disk geometry from the partition table",
2393 This displays the disk geometry of C<device> read from the
2394 partition table. Especially in the case where the underlying
2395 block device has been resized, this can be different from the
2396 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2398 The result is in human-readable format, and not designed to
2401 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2403 "activate or deactivate all volume groups",
2405 This command activates or (if C<activate> is false) deactivates
2406 all logical volumes in all volume groups.
2407 If activated, then they are made known to the
2408 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2409 then those devices disappear.
2411 This command is the same as running C<vgchange -a y|n>");
2413 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2415 "activate or deactivate some volume groups",
2417 This command activates or (if C<activate> is false) deactivates
2418 all logical volumes in the listed volume groups C<volgroups>.
2419 If activated, then they are made known to the
2420 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2421 then those devices disappear.
2423 This command is the same as running C<vgchange -a y|n volgroups...>
2425 Note that if C<volgroups> is an empty list then B<all> volume groups
2426 are activated or deactivated.");
2428 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2429 [InitNone, Always, TestOutput (
2430 [["sfdiskM"; "/dev/sda"; ","];
2431 ["pvcreate"; "/dev/sda1"];
2432 ["vgcreate"; "VG"; "/dev/sda1"];
2433 ["lvcreate"; "LV"; "VG"; "10"];
2434 ["mkfs"; "ext2"; "/dev/VG/LV"];
2435 ["mount"; "/dev/VG/LV"; "/"];
2436 ["write_file"; "/new"; "test content"; "0"];
2438 ["lvresize"; "/dev/VG/LV"; "20"];
2439 ["e2fsck_f"; "/dev/VG/LV"];
2440 ["resize2fs"; "/dev/VG/LV"];
2441 ["mount"; "/dev/VG/LV"; "/"];
2442 ["cat"; "/new"]], "test content")],
2443 "resize an LVM logical volume",
2445 This resizes (expands or shrinks) an existing LVM logical
2446 volume to C<mbytes>. When reducing, data in the reduced part
2449 ("resize2fs", (RErr, [Device "device"]), 106, [],
2450 [], (* lvresize tests this *)
2451 "resize an ext2/ext3 filesystem",
2453 This resizes an ext2 or ext3 filesystem to match the size of
2454 the underlying device.
2456 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2457 on the C<device> before calling this command. For unknown reasons
2458 C<resize2fs> sometimes gives an error about this and sometimes not.
2459 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2460 calling this function.");
2462 ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2463 [InitBasicFS, Always, TestOutputList (
2464 [["find"; "/"]], ["lost+found"]);
2465 InitBasicFS, Always, TestOutputList (
2469 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2470 InitBasicFS, Always, TestOutputList (
2471 [["mkdir_p"; "/a/b/c"];
2472 ["touch"; "/a/b/c/d"];
2473 ["find"; "/a/b/"]], ["c"; "c/d"])],
2474 "find all files and directories",
2476 This command lists out all files and directories, recursively,
2477 starting at C<directory>. It is essentially equivalent to
2478 running the shell command C<find directory -print> but some
2479 post-processing happens on the output, described below.
2481 This returns a list of strings I<without any prefix>. Thus
2482 if the directory structure was:
2488 then the returned list from C<guestfs_find> C</tmp> would be
2496 If C<directory> is not a directory, then this command returns
2499 The returned list is sorted.");
2501 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2502 [], (* lvresize tests this *)
2503 "check an ext2/ext3 filesystem",
2505 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2506 filesystem checker on C<device>, noninteractively (C<-p>),
2507 even if the filesystem appears to be clean (C<-f>).
2509 This command is only needed because of C<guestfs_resize2fs>
2510 (q.v.). Normally you should use C<guestfs_fsck>.");
2512 ("sleep", (RErr, [Int "secs"]), 109, [],
2513 [InitNone, Always, TestRun (
2515 "sleep for some seconds",
2517 Sleep for C<secs> seconds.");
2519 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2520 [InitNone, Always, TestOutputInt (
2521 [["sfdiskM"; "/dev/sda"; ","];
2522 ["mkfs"; "ntfs"; "/dev/sda1"];
2523 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2524 InitNone, Always, TestOutputInt (
2525 [["sfdiskM"; "/dev/sda"; ","];
2526 ["mkfs"; "ext2"; "/dev/sda1"];
2527 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2528 "probe NTFS volume",
2530 This command runs the L<ntfs-3g.probe(8)> command which probes
2531 an NTFS C<device> for mountability. (Not all NTFS volumes can
2532 be mounted read-write, and some cannot be mounted at all).
2534 C<rw> is a boolean flag. Set it to true if you want to test
2535 if the volume can be mounted read-write. Set it to false if
2536 you want to test if the volume can be mounted read-only.
2538 The return value is an integer which C<0> if the operation
2539 would succeed, or some non-zero value documented in the
2540 L<ntfs-3g.probe(8)> manual page.");
2542 ("sh", (RString "output", [String "command"]), 111, [],
2543 [], (* XXX needs tests *)
2544 "run a command via the shell",
2546 This call runs a command from the guest filesystem via the
2549 This is like C<guestfs_command>, but passes the command to:
2551 /bin/sh -c \"command\"
2553 Depending on the guest's shell, this usually results in
2554 wildcards being expanded, shell expressions being interpolated
2557 All the provisos about C<guestfs_command> apply to this call.");
2559 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2560 [], (* XXX needs tests *)
2561 "run a command via the shell returning lines",
2563 This is the same as C<guestfs_sh>, but splits the result
2564 into a list of lines.
2566 See also: C<guestfs_command_lines>");
2568 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2569 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2570 * code in stubs.c, since all valid glob patterns must start with "/".
2571 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2573 [InitBasicFS, Always, TestOutputList (
2574 [["mkdir_p"; "/a/b/c"];
2575 ["touch"; "/a/b/c/d"];
2576 ["touch"; "/a/b/c/e"];
2577 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2578 InitBasicFS, Always, TestOutputList (
2579 [["mkdir_p"; "/a/b/c"];
2580 ["touch"; "/a/b/c/d"];
2581 ["touch"; "/a/b/c/e"];
2582 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2583 InitBasicFS, Always, TestOutputList (
2584 [["mkdir_p"; "/a/b/c"];
2585 ["touch"; "/a/b/c/d"];
2586 ["touch"; "/a/b/c/e"];
2587 ["glob_expand"; "/a/*/x/*"]], [])],
2588 "expand a wildcard path",
2590 This command searches for all the pathnames matching
2591 C<pattern> according to the wildcard expansion rules
2594 If no paths match, then this returns an empty list
2595 (note: not an error).
2597 It is just a wrapper around the C L<glob(3)> function
2598 with flags C<GLOB_MARK|GLOB_BRACE>.
2599 See that manual page for more details.");
2601 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2602 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2603 [["scrub_device"; "/dev/sdc"]])],
2604 "scrub (securely wipe) a device",
2606 This command writes patterns over C<device> to make data retrieval
2609 It is an interface to the L<scrub(1)> program. See that
2610 manual page for more details.");
2612 ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2613 [InitBasicFS, Always, TestRun (
2614 [["write_file"; "/file"; "content"; "0"];
2615 ["scrub_file"; "/file"]])],
2616 "scrub (securely wipe) a file",
2618 This command writes patterns over a file to make data retrieval
2621 The file is I<removed> after scrubbing.
2623 It is an interface to the L<scrub(1)> program. See that
2624 manual page for more details.");
2626 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2627 [], (* XXX needs testing *)
2628 "scrub (securely wipe) free space",
2630 This command creates the directory C<dir> and then fills it
2631 with files until the filesystem is full, and scrubs the files
2632 as for C<guestfs_scrub_file>, and deletes them.
2633 The intention is to scrub any free space on the partition
2636 It is an interface to the L<scrub(1)> program. See that
2637 manual page for more details.");
2639 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2640 [InitBasicFS, Always, TestRun (
2642 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2643 "create a temporary directory",
2645 This command creates a temporary directory. The
2646 C<template> parameter should be a full pathname for the
2647 temporary directory name with the final six characters being
2650 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2651 the second one being suitable for Windows filesystems.
2653 The name of the temporary directory that was created
2656 The temporary directory is created with mode 0700
2657 and is owned by root.
2659 The caller is responsible for deleting the temporary
2660 directory and its contents after use.
2662 See also: L<mkdtemp(3)>");
2664 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2665 [InitSquashFS, Always, TestOutputInt (
2666 [["wc_l"; "/10klines"]], 10000)],
2667 "count lines in a file",
2669 This command counts the lines in a file, using the
2670 C<wc -l> external command.");
2672 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2673 [InitSquashFS, Always, TestOutputInt (
2674 [["wc_w"; "/10klines"]], 10000)],
2675 "count words in a file",
2677 This command counts the words in a file, using the
2678 C<wc -w> external command.");
2680 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2681 [InitSquashFS, Always, TestOutputInt (
2682 [["wc_c"; "/100kallspaces"]], 102400)],
2683 "count characters in a file",
2685 This command counts the characters in a file, using the
2686 C<wc -c> external command.");
2688 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2689 [InitSquashFS, Always, TestOutputList (
2690 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2691 "return first 10 lines of a file",
2693 This command returns up to the first 10 lines of a file as
2694 a list of strings.");
2696 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2697 [InitSquashFS, Always, TestOutputList (
2698 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2699 InitSquashFS, Always, TestOutputList (
2700 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2701 InitSquashFS, Always, TestOutputList (
2702 [["head_n"; "0"; "/10klines"]], [])],
2703 "return first N lines of a file",
2705 If the parameter C<nrlines> is a positive number, this returns the first
2706 C<nrlines> lines of the file C<path>.
2708 If the parameter C<nrlines> is a negative number, this returns lines
2709 from the file C<path>, excluding the last C<nrlines> lines.
2711 If the parameter C<nrlines> is zero, this returns an empty list.");
2713 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2714 [InitSquashFS, Always, TestOutputList (
2715 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2716 "return last 10 lines of a file",
2718 This command returns up to the last 10 lines of a file as
2719 a list of strings.");
2721 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2722 [InitSquashFS, Always, TestOutputList (
2723 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2724 InitSquashFS, Always, TestOutputList (
2725 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2726 InitSquashFS, Always, TestOutputList (
2727 [["tail_n"; "0"; "/10klines"]], [])],
2728 "return last N lines of a file",
2730 If the parameter C<nrlines> is a positive number, this returns the last
2731 C<nrlines> lines of the file C<path>.
2733 If the parameter C<nrlines> is a negative number, this returns lines
2734 from the file C<path>, starting with the C<-nrlines>th line.
2736 If the parameter C<nrlines> is zero, this returns an empty list.");
2738 ("df", (RString "output", []), 125, [],
2739 [], (* XXX Tricky to test because it depends on the exact format
2740 * of the 'df' command and other imponderables.
2742 "report file system disk space usage",
2744 This command runs the C<df> command to report disk space used.
2746 This command is mostly useful for interactive sessions. It
2747 is I<not> intended that you try to parse the output string.
2748 Use C<statvfs> from programs.");
2750 ("df_h", (RString "output", []), 126, [],
2751 [], (* XXX Tricky to test because it depends on the exact format
2752 * of the 'df' command and other imponderables.
2754 "report file system disk space usage (human readable)",
2756 This command runs the C<df -h> command to report disk space used
2757 in human-readable format.
2759 This command is mostly useful for interactive sessions. It
2760 is I<not> intended that you try to parse the output string.
2761 Use C<statvfs> from programs.");
2763 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2764 [InitSquashFS, Always, TestOutputInt (
2765 [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))],
2766 "estimate file space usage",
2768 This command runs the C<du -s> command to estimate file space
2771 C<path> can be a file or a directory. If C<path> is a directory
2772 then the estimate includes the contents of the directory and all
2773 subdirectories (recursively).
2775 The result is the estimated size in I<kilobytes>
2776 (ie. units of 1024 bytes).");
2778 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2779 [InitSquashFS, Always, TestOutputList (
2780 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2781 "list files in an initrd",
2783 This command lists out files contained in an initrd.
2785 The files are listed without any initial C</> character. The
2786 files are listed in the order they appear (not necessarily
2787 alphabetical). Directory names are listed as separate items.
2789 Old Linux kernels (2.4 and earlier) used a compressed ext2
2790 filesystem as initrd. We I<only> support the newer initramfs
2791 format (compressed cpio files).");
2793 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2795 "mount a file using the loop device",
2797 This command lets you mount C<file> (a filesystem image
2798 in a file) on a mount point. It is entirely equivalent to
2799 the command C<mount -o loop file mountpoint>.");
2801 ("mkswap", (RErr, [Device "device"]), 130, [],
2802 [InitEmpty, Always, TestRun (
2803 [["sfdiskM"; "/dev/sda"; ","];
2804 ["mkswap"; "/dev/sda1"]])],
2805 "create a swap partition",
2807 Create a swap partition on C<device>.");
2809 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2810 [InitEmpty, Always, TestRun (
2811 [["sfdiskM"; "/dev/sda"; ","];
2812 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2813 "create a swap partition with a label",
2815 Create a swap partition on C<device> with label C<label>.
2817 Note that you cannot attach a swap label to a block device
2818 (eg. C</dev/sda>), just to a partition. This appears to be
2819 a limitation of the kernel or swap tools.");
2821 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2822 (let uuid = uuidgen () in
2823 [InitEmpty, Always, TestRun (
2824 [["sfdiskM"; "/dev/sda"; ","];
2825 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2826 "create a swap partition with an explicit UUID",
2828 Create a swap partition on C<device> with UUID C<uuid>.");
2830 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2831 [InitBasicFS, Always, TestOutputStruct (
2832 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2833 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2834 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2835 InitBasicFS, Always, TestOutputStruct (
2836 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2837 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2838 "make block, character or FIFO devices",
2840 This call creates block or character special devices, or
2841 named pipes (FIFOs).
2843 The C<mode> parameter should be the mode, using the standard
2844 constants. C<devmajor> and C<devminor> are the
2845 device major and minor numbers, only used when creating block
2846 and character special devices.");
2848 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2849 [InitBasicFS, Always, TestOutputStruct (
2850 [["mkfifo"; "0o777"; "/node"];
2851 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2852 "make FIFO (named pipe)",
2854 This call creates a FIFO (named pipe) called C<path> with
2855 mode C<mode>. It is just a convenient wrapper around
2856 C<guestfs_mknod>.");
2858 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2859 [InitBasicFS, Always, TestOutputStruct (
2860 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2861 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2862 "make block device node",
2864 This call creates a block device node called C<path> with
2865 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2866 It is just a convenient wrapper around C<guestfs_mknod>.");
2868 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2869 [InitBasicFS, Always, TestOutputStruct (
2870 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2871 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2872 "make char device node",
2874 This call creates a char device node called C<path> with
2875 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2876 It is just a convenient wrapper around C<guestfs_mknod>.");
2878 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2879 [], (* XXX umask is one of those stateful things that we should
2880 * reset between each test.
2882 "set file mode creation mask (umask)",
2884 This function sets the mask used for creating new files and
2885 device nodes to C<mask & 0777>.
2887 Typical umask values would be C<022> which creates new files
2888 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2889 C<002> which creates new files with permissions like
2890 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2892 The default umask is C<022>. This is important because it
2893 means that directories and device nodes will be created with
2894 C<0644> or C<0755> mode even if you specify C<0777>.
2896 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2898 This call returns the previous umask.");
2900 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2902 "read directories entries",
2904 This returns the list of directory entries in directory C<dir>.
2906 All entries in the directory are returned, including C<.> and
2907 C<..>. The entries are I<not> sorted, but returned in the same
2908 order as the underlying filesystem.
2910 Also this call returns basic file type information about each
2911 file. The C<ftyp> field will contain one of the following characters:
2949 The L<readdir(3)> returned a C<d_type> field with an
2954 This function is primarily intended for use by programs. To
2955 get a simple list of names, use C<guestfs_ls>. To get a printable
2956 directory for human consumption, use C<guestfs_ll>.");
2958 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2960 "create partitions on a block device",
2962 This is a simplified interface to the C<guestfs_sfdisk>
2963 command, where partition sizes are specified in megabytes
2964 only (rounded to the nearest cylinder) and you don't need
2965 to specify the cyls, heads and sectors parameters which
2966 were rarely if ever used anyway.
2968 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2970 ("zfile", (RString "description", [String "method"; Pathname "path"]), 140, [DeprecatedBy "file"],
2972 "determine file type inside a compressed file",
2974 This command runs C<file> after first decompressing C<path>
2977 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2979 Since 1.0.63, use C<guestfs_file> instead which can now
2980 process compressed files.");
2982 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
2984 "list extended attributes of a file or directory",
2986 This call lists the extended attributes of the file or directory
2989 At the system call level, this is a combination of the
2990 L<listxattr(2)> and L<getxattr(2)> calls.
2992 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2994 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
2996 "list extended attributes of a file or directory",
2998 This is the same as C<guestfs_getxattrs>, but if C<path>
2999 is a symbolic link, then it returns the extended attributes
3000 of the link itself.");
3002 ("setxattr", (RErr, [String "xattr";
3003 String "val"; Int "vallen"; (* will be BufferIn *)
3004 Pathname "path"]), 143, [],
3006 "set extended attribute of a file or directory",
3008 This call sets the extended attribute named C<xattr>
3009 of the file C<path> to the value C<val> (of length C<vallen>).
3010 The value is arbitrary 8 bit data.
3012 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3014 ("lsetxattr", (RErr, [String "xattr";
3015 String "val"; Int "vallen"; (* will be BufferIn *)
3016 Pathname "path"]), 144, [],
3018 "set extended attribute of a file or directory",
3020 This is the same as C<guestfs_setxattr>, but if C<path>
3021 is a symbolic link, then it sets an extended attribute
3022 of the link itself.");
3024 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3026 "remove extended attribute of a file or directory",
3028 This call removes the extended attribute named C<xattr>
3029 of the file C<path>.
3031 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3033 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3035 "remove extended attribute of a file or directory",
3037 This is the same as C<guestfs_removexattr>, but if C<path>
3038 is a symbolic link, then it removes an extended attribute
3039 of the link itself.");
3041 ("mountpoints", (RHashtable "mps", []), 147, [],
3045 This call is similar to C<guestfs_mounts>. That call returns
3046 a list of devices. This one returns a hash table (map) of
3047 device name to directory where the device is mounted.");
3049 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3050 (* This is a special case: while you would expect a parameter
3051 * of type "Pathname", that doesn't work, because it implies
3052 * NEED_ROOT in the generated calling code in stubs.c, and
3053 * this function cannot use NEED_ROOT.
3056 "create a mountpoint",
3058 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3059 specialized calls that can be used to create extra mountpoints
3060 before mounting the first filesystem.
3062 These calls are I<only> necessary in some very limited circumstances,
3063 mainly the case where you want to mount a mix of unrelated and/or
3064 read-only filesystems together.
3066 For example, live CDs often contain a \"Russian doll\" nest of
3067 filesystems, an ISO outer layer, with a squashfs image inside, with
3068 an ext2/3 image inside that. You can unpack this as follows
3071 add-ro Fedora-11-i686-Live.iso
3074 mkmountpoint /squash
3077 mount-loop /cd/LiveOS/squashfs.img /squash
3078 mount-loop /squash/LiveOS/ext3fs.img /ext3
3080 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3082 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3084 "remove a mountpoint",
3086 This calls removes a mountpoint that was previously created
3087 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3088 for full details.");
3090 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3091 [InitSquashFS, Always, TestOutputBuffer (
3092 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3095 This calls returns the contents of the file C<path> as a
3098 Unlike C<guestfs_cat>, this function can correctly
3099 handle files that contain embedded ASCII NUL characters.
3100 However unlike C<guestfs_download>, this function is limited
3101 in the total size of file that can be handled.");
3103 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3104 [InitSquashFS, Always, TestOutputList (
3105 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3106 InitSquashFS, Always, TestOutputList (
3107 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3108 "return lines matching a pattern",
3110 This calls the external C<grep> program and returns the
3113 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3114 [InitSquashFS, Always, TestOutputList (
3115 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3116 "return lines matching a pattern",
3118 This calls the external C<egrep> program and returns the
3121 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3122 [InitSquashFS, Always, TestOutputList (
3123 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3124 "return lines matching a pattern",
3126 This calls the external C<fgrep> program and returns the
3129 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3130 [InitSquashFS, Always, TestOutputList (
3131 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3132 "return lines matching a pattern",
3134 This calls the external C<grep -i> program and returns the
3137 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3138 [InitSquashFS, Always, TestOutputList (
3139 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3140 "return lines matching a pattern",
3142 This calls the external C<egrep -i> program and returns the
3145 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3146 [InitSquashFS, Always, TestOutputList (
3147 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3148 "return lines matching a pattern",
3150 This calls the external C<fgrep -i> program and returns the
3153 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3154 [InitSquashFS, Always, TestOutputList (
3155 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3156 "return lines matching a pattern",
3158 This calls the external C<zgrep> program and returns the
3161 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3162 [InitSquashFS, Always, TestOutputList (
3163 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3164 "return lines matching a pattern",
3166 This calls the external C<zegrep> program and returns the
3169 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3170 [InitSquashFS, Always, TestOutputList (
3171 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3172 "return lines matching a pattern",
3174 This calls the external C<zfgrep> program and returns the
3177 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3178 [InitSquashFS, Always, TestOutputList (
3179 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3180 "return lines matching a pattern",
3182 This calls the external C<zgrep -i> program and returns the
3185 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3186 [InitSquashFS, Always, TestOutputList (
3187 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3188 "return lines matching a pattern",
3190 This calls the external C<zegrep -i> program and returns the
3193 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3194 [InitSquashFS, Always, TestOutputList (
3195 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3196 "return lines matching a pattern",
3198 This calls the external C<zfgrep -i> program and returns the
3201 ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3202 [InitSquashFS, Always, TestOutput (
3203 [["realpath"; "/../directory"]], "/directory")],
3204 "canonicalized absolute pathname",
3206 Return the canonicalized absolute pathname of C<path>. The
3207 returned path has no C<.>, C<..> or symbolic link path elements.");
3209 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3210 [InitBasicFS, Always, TestOutputStruct (
3213 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3214 "create a hard link",
3216 This command creates a hard link using the C<ln> command.");
3218 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3219 [InitBasicFS, Always, TestOutputStruct (
3222 ["ln_f"; "/a"; "/b"];
3223 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3224 "create a hard link",
3226 This command creates a hard link using the C<ln -f> command.
3227 The C<-f> option removes the link (C<linkname>) if it exists already.");
3229 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3230 [InitBasicFS, Always, TestOutputStruct (
3232 ["ln_s"; "a"; "/b"];
3233 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3234 "create a symbolic link",
3236 This command creates a symbolic link using the C<ln -s> command.");
3238 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3239 [InitBasicFS, Always, TestOutput (
3240 [["mkdir_p"; "/a/b"];
3241 ["touch"; "/a/b/c"];
3242 ["ln_sf"; "../d"; "/a/b/c"];
3243 ["readlink"; "/a/b/c"]], "../d")],
3244 "create a symbolic link",
3246 This command creates a symbolic link using the C<ln -sf> command,
3247 The C<-f> option removes the link (C<linkname>) if it exists already.");
3249 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3250 [] (* XXX tested above *),
3251 "read the target of a symbolic link",
3253 This command reads the target of a symbolic link.");
3255 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3256 [InitBasicFS, Always, TestOutputStruct (
3257 [["fallocate"; "/a"; "1000000"];
3258 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3259 "preallocate a file in the guest filesystem",
3261 This command preallocates a file (containing zero bytes) named
3262 C<path> of size C<len> bytes. If the file exists already, it
3265 Do not confuse this with the guestfish-specific
3266 C<alloc> command which allocates a file in the host and
3267 attaches it as a device.");
3269 ("swapon_device", (RErr, [Device "device"]), 170, [],
3270 [InitPartition, Always, TestRun (
3271 [["mkswap"; "/dev/sda1"];
3272 ["swapon_device"; "/dev/sda1"];
3273 ["swapoff_device"; "/dev/sda1"]])],
3274 "enable swap on device",
3276 This command enables the libguestfs appliance to use the
3277 swap device or partition named C<device>. The increased
3278 memory is made available for all commands, for example
3279 those run using C<guestfs_command> or C<guestfs_sh>.
3281 Note that you should not swap to existing guest swap
3282 partitions unless you know what you are doing. They may
3283 contain hibernation information, or other information that
3284 the guest doesn't want you to trash. You also risk leaking
3285 information about the host to the guest this way. Instead,
3286 attach a new host device to the guest and swap on that.");
3288 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3289 [], (* XXX tested by swapon_device *)
3290 "disable swap on device",
3292 This command disables the libguestfs appliance swap
3293 device or partition named C<device>.
3294 See C<guestfs_swapon_device>.");
3296 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3297 [InitBasicFS, Always, TestRun (
3298 [["fallocate"; "/swap"; "8388608"];
3299 ["mkswap_file"; "/swap"];
3300 ["swapon_file"; "/swap"];
3301 ["swapoff_file"; "/swap"]])],
3302 "enable swap on file",
3304 This command enables swap to a file.
3305 See C<guestfs_swapon_device> for other notes.");
3307 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3308 [], (* XXX tested by swapon_file *)
3309 "disable swap on file",
3311 This command disables the libguestfs appliance swap on file.");
3313 ("swapon_label", (RErr, [String "label"]), 174, [],
3314 [InitEmpty, Always, TestRun (
3315 [["sfdiskM"; "/dev/sdb"; ","];
3316 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3317 ["swapon_label"; "swapit"];
3318 ["swapoff_label"; "swapit"];
3319 ["zero"; "/dev/sdb"];
3320 ["blockdev_rereadpt"; "/dev/sdb"]])],
3321 "enable swap on labeled swap partition",
3323 This command enables swap to a labeled swap partition.
3324 See C<guestfs_swapon_device> for other notes.");
3326 ("swapoff_label", (RErr, [String "label"]), 175, [],
3327 [], (* XXX tested by swapon_label *)
3328 "disable swap on labeled swap partition",
3330 This command disables the libguestfs appliance swap on
3331 labeled swap partition.");
3333 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3334 (let uuid = uuidgen () in
3335 [InitEmpty, Always, TestRun (
3336 [["mkswap_U"; uuid; "/dev/sdb"];
3337 ["swapon_uuid"; uuid];
3338 ["swapoff_uuid"; uuid]])]),
3339 "enable swap on swap partition by UUID",
3341 This command enables swap to a swap partition with the given UUID.
3342 See C<guestfs_swapon_device> for other notes.");
3344 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3345 [], (* XXX tested by swapon_uuid *)
3346 "disable swap on swap partition by UUID",
3348 This command disables the libguestfs appliance swap partition
3349 with the given UUID.");
3351 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3352 [InitBasicFS, Always, TestRun (
3353 [["fallocate"; "/swap"; "8388608"];
3354 ["mkswap_file"; "/swap"]])],
3355 "create a swap file",
3359 This command just writes a swap file signature to an existing
3360 file. To create the file itself, use something like C<guestfs_fallocate>.");
3362 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3363 [InitSquashFS, Always, TestRun (
3364 [["inotify_init"; "0"]])],
3365 "create an inotify handle",
3367 This command creates a new inotify handle.
3368 The inotify subsystem can be used to notify events which happen to
3369 objects in the guest filesystem.
3371 C<maxevents> is the maximum number of events which will be
3372 queued up between calls to C<guestfs_inotify_read> or
3373 C<guestfs_inotify_files>.
3374 If this is passed as C<0>, then the kernel (or previously set)
3375 default is used. For Linux 2.6.29 the default was 16384 events.
3376 Beyond this limit, the kernel throws away events, but records
3377 the fact that it threw them away by setting a flag
3378 C<IN_Q_OVERFLOW> in the returned structure list (see
3379 C<guestfs_inotify_read>).
3381 Before any events are generated, you have to add some
3382 watches to the internal watch list. See:
3383 C<guestfs_inotify_add_watch>,
3384 C<guestfs_inotify_rm_watch> and
3385 C<guestfs_inotify_watch_all>.
3387 Queued up events should be read periodically by calling
3388 C<guestfs_inotify_read>
3389 (or C<guestfs_inotify_files> which is just a helpful
3390 wrapper around C<guestfs_inotify_read>). If you don't
3391 read the events out often enough then you risk the internal
3394 The handle should be closed after use by calling
3395 C<guestfs_inotify_close>. This also removes any
3396 watches automatically.
3398 See also L<inotify(7)> for an overview of the inotify interface
3399 as exposed by the Linux kernel, which is roughly what we expose
3400 via libguestfs. Note that there is one global inotify handle
3401 per libguestfs instance.");
3403 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3404 [InitBasicFS, Always, TestOutputList (
3405 [["inotify_init"; "0"];
3406 ["inotify_add_watch"; "/"; "1073741823"];
3409 ["inotify_files"]], ["a"; "b"])],
3410 "add an inotify watch",
3412 Watch C<path> for the events listed in C<mask>.
3414 Note that if C<path> is a directory then events within that
3415 directory are watched, but this does I<not> happen recursively
3416 (in subdirectories).
3418 Note for non-C or non-Linux callers: the inotify events are
3419 defined by the Linux kernel ABI and are listed in
3420 C</usr/include/sys/inotify.h>.");
3422 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3424 "remove an inotify watch",
3426 Remove a previously defined inotify watch.
3427 See C<guestfs_inotify_add_watch>.");
3429 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3431 "return list of inotify events",
3433 Return the complete queue of events that have happened
3434 since the previous read call.
3436 If no events have happened, this returns an empty list.
3438 I<Note>: In order to make sure that all events have been
3439 read, you must call this function repeatedly until it
3440 returns an empty list. The reason is that the call will
3441 read events up to the maximum appliance-to-host message
3442 size and leave remaining events in the queue.");
3444 ("inotify_files", (RStringList "paths", []), 183, [],
3446 "return list of watched files that had events",
3448 This function is a helpful wrapper around C<guestfs_inotify_read>
3449 which just returns a list of pathnames of objects that were
3450 touched. The returned pathnames are sorted and deduplicated.");
3452 ("inotify_close", (RErr, []), 184, [],
3454 "close the inotify handle",
3456 This closes the inotify handle which was previously
3457 opened by inotify_init. It removes all watches, throws
3458 away any pending events, and deallocates all resources.");
3460 ("setcon", (RErr, [String "context"]), 185, [],
3462 "set SELinux security context",
3464 This sets the SELinux security context of the daemon
3465 to the string C<context>.
3467 See the documentation about SELINUX in L<guestfs(3)>.");
3469 ("getcon", (RString "context", []), 186, [],
3471 "get SELinux security context",
3473 This gets the SELinux security context of the daemon.
3475 See the documentation about SELINUX in L<guestfs(3)>,
3476 and C<guestfs_setcon>");
3480 let all_functions = non_daemon_functions @ daemon_functions
3482 (* In some places we want the functions to be displayed sorted
3483 * alphabetically, so this is useful:
3485 let all_functions_sorted =
3486 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3487 compare n1 n2) all_functions
3489 (* Field types for structures. *)
3491 | FChar (* C 'char' (really, a 7 bit byte). *)
3492 | FString (* nul-terminated ASCII string, NOT NULL. *)
3493 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3498 | FBytes (* Any int measure that counts bytes. *)
3499 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3500 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3502 (* Because we generate extra parsing code for LVM command line tools,
3503 * we have to pull out the LVM columns separately here.
3513 "pv_attr", FString (* XXX *);
3514 "pv_pe_count", FInt64;
3515 "pv_pe_alloc_count", FInt64;
3518 "pv_mda_count", FInt64;
3519 "pv_mda_free", FBytes;
3520 (* Not in Fedora 10:
3521 "pv_mda_size", FBytes;
3528 "vg_attr", FString (* XXX *);
3531 "vg_sysid", FString;
3532 "vg_extent_size", FBytes;
3533 "vg_extent_count", FInt64;
3534 "vg_free_count", FInt64;
3539 "snap_count", FInt64;
3542 "vg_mda_count", FInt64;
3543 "vg_mda_free", FBytes;
3544 (* Not in Fedora 10:
3545 "vg_mda_size", FBytes;
3551 "lv_attr", FString (* XXX *);
3554 "lv_kernel_major", FInt64;
3555 "lv_kernel_minor", FInt64;
3557 "seg_count", FInt64;
3559 "snap_percent", FOptPercent;
3560 "copy_percent", FOptPercent;
3563 "mirror_log", FString;
3567 (* Names and fields in all structures (in RStruct and RStructList)
3571 (* The old RIntBool return type, only ever used for aug_defnode. Do
3572 * not use this struct in any new code.
3575 "i", FInt32; (* for historical compatibility *)
3576 "b", FInt32; (* for historical compatibility *)
3579 (* LVM PVs, VGs, LVs. *)
3580 "lvm_pv", lvm_pv_cols;
3581 "lvm_vg", lvm_vg_cols;
3582 "lvm_lv", lvm_lv_cols;
3584 (* Column names and types from stat structures.
3585 * NB. Can't use things like 'st_atime' because glibc header files
3586 * define some of these as macros. Ugh.
3617 (* Column names in dirent structure. *)
3620 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3625 (* Version numbers. *)
3633 (* Extended attribute. *)
3635 "attrname", FString;
3639 (* Inotify events. *)
3643 "in_cookie", FUInt32;
3646 ] (* end of structs *)
3648 (* Ugh, Java has to be different ..
3649 * These names are also used by the Haskell bindings.
3651 let java_structs = [
3652 "int_bool", "IntBool";
3657 "statvfs", "StatVFS";
3659 "version", "Version";
3661 "inotify_event", "INotifyEvent";
3664 (* What structs are actually returned. *)
3665 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3667 (* Returns a list of RStruct/RStructList structs that are returned
3668 * by any function. Each element of returned list is a pair:
3670 * (structname, RStructOnly)
3671 * == there exists function which returns RStruct (_, structname)
3672 * (structname, RStructListOnly)
3673 * == there exists function which returns RStructList (_, structname)
3674 * (structname, RStructAndList)
3675 * == there are functions returning both RStruct (_, structname)
3676 * and RStructList (_, structname)
3679 (* ||| is a "logical OR" for rstructs_used_t *)
3683 | _, RStructAndList -> RStructAndList
3684 | RStructOnly, RStructListOnly
3685 | RStructListOnly, RStructOnly -> RStructAndList
3686 | RStructOnly, RStructOnly -> RStructOnly
3687 | RStructListOnly, RStructListOnly -> RStructListOnly
3690 let h = Hashtbl.create 13 in
3692 (* if elem->oldv exists, update entry using ||| operator,
3693 * else just add elem->newv to the hash
3695 let update elem newv =
3696 try let oldv = Hashtbl.find h elem in
3697 Hashtbl.replace h elem (newv ||| oldv)
3698 with Not_found -> Hashtbl.add h elem newv
3702 fun (_, style, _, _, _, _, _) ->
3703 match fst style with
3704 | RStruct (_, structname) -> update structname RStructOnly
3705 | RStructList (_, structname) -> update structname RStructListOnly
3709 (* return key->values as a list of (key,value) *)
3710 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3716 | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3717 | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3718 | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3722 (* Used for testing language bindings. *)
3724 | CallString of string
3725 | CallOptString of string option
3726 | CallStringList of string list
3730 (* Used to memoize the result of pod2text. *)
3731 let pod2text_memo_filename = "src/.pod2text.data"
3732 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3734 let chan = open_in pod2text_memo_filename in
3735 let v = input_value chan in
3739 _ -> Hashtbl.create 13
3741 (* Useful functions.
3742 * Note we don't want to use any external OCaml libraries which
3743 * makes this a bit harder than it should be.
3745 let failwithf fs = ksprintf failwith fs
3747 let replace_char s c1 c2 =
3748 let s2 = String.copy s in
3749 let r = ref false in
3750 for i = 0 to String.length s2 - 1 do
3751 if String.unsafe_get s2 i = c1 then (
3752 String.unsafe_set s2 i c2;
3756 if not !r then s else s2
3760 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3762 let triml ?(test = isspace) str =
3764 let n = ref (String.length str) in
3765 while !n > 0 && test str.[!i]; do
3770 else String.sub str !i !n
3772 let trimr ?(test = isspace) str =
3773 let n = ref (String.length str) in
3774 while !n > 0 && test str.[!n-1]; do
3777 if !n = String.length str then str
3778 else String.sub str 0 !n
3780 let trim ?(test = isspace) str =
3781 trimr ~test (triml ~test str)
3783 let rec find s sub =
3784 let len = String.length s in
3785 let sublen = String.length sub in
3787 if i <= len-sublen then (
3789 if j < sublen then (
3790 if s.[i+j] = sub.[j] then loop2 (j+1)
3796 if r = -1 then loop (i+1) else r
3802 let rec replace_str s s1 s2 =
3803 let len = String.length s in
3804 let sublen = String.length s1 in
3805 let i = find s s1 in
3808 let s' = String.sub s 0 i in
3809 let s'' = String.sub s (i+sublen) (len-i-sublen) in
3810 s' ^ s2 ^ replace_str s'' s1 s2
3813 let rec string_split sep str =
3814 let len = String.length str in
3815 let seplen = String.length sep in
3816 let i = find str sep in
3817 if i = -1 then [str]
3819 let s' = String.sub str 0 i in
3820 let s'' = String.sub str (i+seplen) (len-i-seplen) in
3821 s' :: string_split sep s''
3824 let files_equal n1 n2 =
3825 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3826 match Sys.command cmd with
3829 | i -> failwithf "%s: failed with error code %d" cmd i
3831 let rec filter_map f = function
3835 | Some y -> y :: filter_map f xs
3836 | None -> filter_map f xs
3838 let rec find_map f = function
3839 | [] -> raise Not_found
3843 | None -> find_map f xs
3846 let rec loop i = function
3848 | x :: xs -> f i x; loop (i+1) xs
3853 let rec loop i = function
3855 | x :: xs -> let r = f i x in r :: loop (i+1) xs
3859 let name_of_argt = function
3860 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | Bool n | Int n
3861 | FileIn n | FileOut n -> n
3863 let java_name_of_struct typ =
3864 try List.assoc typ java_structs
3867 "java_name_of_struct: no java_structs entry corresponding to %s" typ
3869 let cols_of_struct typ =
3870 try List.assoc typ structs
3872 failwithf "cols_of_struct: unknown struct %s" typ
3874 let seq_of_test = function
3875 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3876 | TestOutputListOfDevices (s, _)
3877 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3878 | TestOutputTrue s | TestOutputFalse s
3879 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3880 | TestOutputStruct (s, _)
3881 | TestLastFail s -> s
3883 (* Handling for function flags. *)
3884 let protocol_limit_warning =
3885 "Because of the message protocol, there is a transfer limit
3886 of somewhere between 2MB and 4MB. To transfer large files you should use
3889 let danger_will_robinson =
3890 "B<This command is dangerous. Without careful use you
3891 can easily destroy all your data>."
3893 let deprecation_notice flags =
3896 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
3898 sprintf "This function is deprecated.
3899 In new code, use the C<%s> call instead.
3901 Deprecated functions will not be removed from the API, but the
3902 fact that they are deprecated indicates that there are problems
3903 with correct use of these functions." alt in
3908 (* Check function names etc. for consistency. *)
3909 let check_functions () =
3910 let contains_uppercase str =
3911 let len = String.length str in
3913 if i >= len then false
3916 if c >= 'A' && c <= 'Z' then true
3923 (* Check function names. *)
3925 fun (name, _, _, _, _, _, _) ->
3926 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
3927 failwithf "function name %s does not need 'guestfs' prefix" name;
3929 failwithf "function name is empty";
3930 if name.[0] < 'a' || name.[0] > 'z' then
3931 failwithf "function name %s must start with lowercase a-z" name;
3932 if String.contains name '-' then
3933 failwithf "function name %s should not contain '-', use '_' instead."
3937 (* Check function parameter/return names. *)
3939 fun (name, style, _, _, _, _, _) ->
3940 let check_arg_ret_name n =
3941 if contains_uppercase n then
3942 failwithf "%s param/ret %s should not contain uppercase chars"
3944 if String.contains n '-' || String.contains n '_' then
3945 failwithf "%s param/ret %s should not contain '-' or '_'"
3948 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;
3949 if n = "int" || n = "char" || n = "short" || n = "long" then
3950 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
3951 if n = "i" || n = "n" then
3952 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
3953 if n = "argv" || n = "args" then
3954 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
3957 (match fst style with
3959 | RInt n | RInt64 n | RBool n
3960 | RConstString n | RConstOptString n | RString n
3961 | RStringList n | RStruct (n, _) | RStructList (n, _)
3962 | RHashtable n | RBufferOut n ->
3963 check_arg_ret_name n
3965 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
3968 (* Check short descriptions. *)
3970 fun (name, _, _, _, _, shortdesc, _) ->
3971 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
3972 failwithf "short description of %s should begin with lowercase." name;
3973 let c = shortdesc.[String.length shortdesc-1] in
3974 if c = '\n' || c = '.' then
3975 failwithf "short description of %s should not end with . or \\n." name
3978 (* Check long dscriptions. *)
3980 fun (name, _, _, _, _, _, longdesc) ->
3981 if longdesc.[String.length longdesc-1] = '\n' then
3982 failwithf "long description of %s should not end with \\n." name
3985 (* Check proc_nrs. *)
3987 fun (name, _, proc_nr, _, _, _, _) ->
3988 if proc_nr <= 0 then
3989 failwithf "daemon function %s should have proc_nr > 0" name
3993 fun (name, _, proc_nr, _, _, _, _) ->
3994 if proc_nr <> -1 then
3995 failwithf "non-daemon function %s should have proc_nr -1" name
3996 ) non_daemon_functions;
3999 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4002 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4003 let rec loop = function
4006 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4008 | (name1,nr1) :: (name2,nr2) :: _ ->
4009 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4017 (* Ignore functions that have no tests. We generate a
4018 * warning when the user does 'make check' instead.
4020 | name, _, _, _, [], _, _ -> ()
4021 | name, _, _, _, tests, _, _ ->
4025 match seq_of_test test with
4027 failwithf "%s has a test containing an empty sequence" name
4028 | cmds -> List.map List.hd cmds
4030 let funcs = List.flatten funcs in
4032 let tested = List.mem name funcs in
4035 failwithf "function %s has tests but does not test itself" name
4038 (* 'pr' prints to the current output file. *)
4039 let chan = ref stdout
4040 let pr fs = ksprintf (output_string !chan) fs
4042 (* Generate a header block in a number of standard styles. *)
4043 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4044 type license = GPLv2 | LGPLv2
4046 let generate_header comment license =
4047 let c = match comment with
4048 | CStyle -> pr "/* "; " *"
4049 | HashStyle -> pr "# "; "#"
4050 | OCamlStyle -> pr "(* "; " *"
4051 | HaskellStyle -> pr "{- "; " " in
4052 pr "libguestfs generated file\n";
4053 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4054 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4056 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4060 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4061 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4062 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4063 pr "%s (at your option) any later version.\n" c;
4065 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4066 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4067 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4068 pr "%s GNU General Public License for more details.\n" c;
4070 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4071 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4072 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4075 pr "%s This library is free software; you can redistribute it and/or\n" c;
4076 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4077 pr "%s License as published by the Free Software Foundation; either\n" c;
4078 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4080 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4081 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4082 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4083 pr "%s Lesser General Public License for more details.\n" c;
4085 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4086 pr "%s License along with this library; if not, write to the Free Software\n" c;
4087 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4090 | CStyle -> pr " */\n"
4092 | OCamlStyle -> pr " *)\n"
4093 | HaskellStyle -> pr "-}\n"
4097 (* Start of main code generation functions below this line. *)
4099 (* Generate the pod documentation for the C API. *)
4100 let rec generate_actions_pod () =
4102 fun (shortname, style, _, flags, _, _, longdesc) ->
4103 if not (List.mem NotInDocs flags) then (
4104 let name = "guestfs_" ^ shortname in
4105 pr "=head2 %s\n\n" name;
4107 generate_prototype ~extern:false ~handle:"handle" name style;
4109 pr "%s\n\n" longdesc;
4110 (match fst style with
4112 pr "This function returns 0 on success or -1 on error.\n\n"
4114 pr "On error this function returns -1.\n\n"
4116 pr "On error this function returns -1.\n\n"
4118 pr "This function returns a C truth value on success or -1 on error.\n\n"
4120 pr "This function returns a string, or NULL on error.
4121 The string is owned by the guest handle and must I<not> be freed.\n\n"
4122 | RConstOptString _ ->
4123 pr "This function returns a string which may be NULL.
4124 There is way to return an error from this function.
4125 The string is owned by the guest handle and must I<not> be freed.\n\n"
4127 pr "This function returns a string, or NULL on error.
4128 I<The caller must free the returned string after use>.\n\n"
4130 pr "This function returns a NULL-terminated array of strings
4131 (like L<environ(3)>), or NULL if there was an error.
4132 I<The caller must free the strings and the array after use>.\n\n"
4133 | RStruct (_, typ) ->
4134 pr "This function returns a C<struct guestfs_%s *>,
4135 or NULL if there was an error.
4136 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4137 | RStructList (_, typ) ->
4138 pr "This function returns a C<struct guestfs_%s_list *>
4139 (see E<lt>guestfs-structs.hE<gt>),
4140 or NULL if there was an error.
4141 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4143 pr "This function returns a NULL-terminated array of
4144 strings, or NULL if there was an error.
4145 The array of strings will always have length C<2n+1>, where
4146 C<n> keys and values alternate, followed by the trailing NULL entry.
4147 I<The caller must free the strings and the array after use>.\n\n"
4149 pr "This function returns a buffer, or NULL on error.
4150 The size of the returned buffer is written to C<*size_r>.
4151 I<The caller must free the returned buffer after use>.\n\n"
4153 if List.mem ProtocolLimitWarning flags then
4154 pr "%s\n\n" protocol_limit_warning;
4155 if List.mem DangerWillRobinson flags then
4156 pr "%s\n\n" danger_will_robinson;
4157 match deprecation_notice flags with
4159 | Some txt -> pr "%s\n\n" txt
4161 ) all_functions_sorted
4163 and generate_structs_pod () =
4164 (* Structs documentation. *)
4167 pr "=head2 guestfs_%s\n" typ;
4169 pr " struct guestfs_%s {\n" typ;
4172 | name, FChar -> pr " char %s;\n" name
4173 | name, FUInt32 -> pr " uint32_t %s;\n" name
4174 | name, FInt32 -> pr " int32_t %s;\n" name
4175 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4176 | name, FInt64 -> pr " int64_t %s;\n" name
4177 | name, FString -> pr " char *%s;\n" name
4179 pr " /* The next two fields describe a byte array. */\n";
4180 pr " uint32_t %s_len;\n" name;
4181 pr " char *%s;\n" name
4183 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4184 pr " char %s[32];\n" name
4185 | name, FOptPercent ->
4186 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4187 pr " float %s;\n" name
4191 pr " struct guestfs_%s_list {\n" typ;
4192 pr " uint32_t len; /* Number of elements in list. */\n";
4193 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4196 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4197 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4202 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4203 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4205 * We have to use an underscore instead of a dash because otherwise
4206 * rpcgen generates incorrect code.
4208 * This header is NOT exported to clients, but see also generate_structs_h.
4210 and generate_xdr () =
4211 generate_header CStyle LGPLv2;
4213 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4214 pr "typedef string str<>;\n";
4217 (* Internal structures. *)
4221 pr "struct guestfs_int_%s {\n" typ;
4223 | name, FChar -> pr " char %s;\n" name
4224 | name, FString -> pr " string %s<>;\n" name
4225 | name, FBuffer -> pr " opaque %s<>;\n" name
4226 | name, FUUID -> pr " opaque %s[32];\n" name
4227 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4228 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4229 | name, FOptPercent -> pr " float %s;\n" name
4233 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4238 fun (shortname, style, _, _, _, _, _) ->
4239 let name = "guestfs_" ^ shortname in
4241 (match snd style with
4244 pr "struct %s_args {\n" name;
4247 | Pathname n | Device n | Dev_or_Path n | String n -> pr " string %s<>;\n" n
4248 | OptString n -> pr " str *%s;\n" n
4249 | StringList n -> pr " str %s<>;\n" n
4250 | Bool n -> pr " bool %s;\n" n
4251 | Int n -> pr " int %s;\n" n
4252 | FileIn _ | FileOut _ -> ()
4256 (match fst style with
4259 pr "struct %s_ret {\n" name;
4263 pr "struct %s_ret {\n" name;
4264 pr " hyper %s;\n" n;
4267 pr "struct %s_ret {\n" name;
4270 | RConstString _ | RConstOptString _ ->
4271 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4273 pr "struct %s_ret {\n" name;
4274 pr " string %s<>;\n" n;
4277 pr "struct %s_ret {\n" name;
4278 pr " str %s<>;\n" n;
4280 | RStruct (n, typ) ->
4281 pr "struct %s_ret {\n" name;
4282 pr " guestfs_int_%s %s;\n" typ n;
4284 | RStructList (n, typ) ->
4285 pr "struct %s_ret {\n" name;
4286 pr " guestfs_int_%s_list %s;\n" typ n;
4289 pr "struct %s_ret {\n" name;
4290 pr " str %s<>;\n" n;
4293 pr "struct %s_ret {\n" name;
4294 pr " opaque %s<>;\n" n;
4299 (* Table of procedure numbers. *)
4300 pr "enum guestfs_procedure {\n";
4302 fun (shortname, _, proc_nr, _, _, _, _) ->
4303 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4305 pr " GUESTFS_PROC_NR_PROCS\n";
4309 (* Having to choose a maximum message size is annoying for several
4310 * reasons (it limits what we can do in the API), but it (a) makes
4311 * the protocol a lot simpler, and (b) provides a bound on the size
4312 * of the daemon which operates in limited memory space. For large
4313 * file transfers you should use FTP.
4315 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4318 (* Message header, etc. *)
4320 /* The communication protocol is now documented in the guestfs(3)
4324 const GUESTFS_PROGRAM = 0x2000F5F5;
4325 const GUESTFS_PROTOCOL_VERSION = 1;
4327 /* These constants must be larger than any possible message length. */
4328 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4329 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4331 enum guestfs_message_direction {
4332 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4333 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4336 enum guestfs_message_status {
4337 GUESTFS_STATUS_OK = 0,
4338 GUESTFS_STATUS_ERROR = 1
4341 const GUESTFS_ERROR_LEN = 256;
4343 struct guestfs_message_error {
4344 string error_message<GUESTFS_ERROR_LEN>;
4347 struct guestfs_message_header {
4348 unsigned prog; /* GUESTFS_PROGRAM */
4349 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4350 guestfs_procedure proc; /* GUESTFS_PROC_x */
4351 guestfs_message_direction direction;
4352 unsigned serial; /* message serial number */
4353 guestfs_message_status status;
4356 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4358 struct guestfs_chunk {
4359 int cancel; /* if non-zero, transfer is cancelled */
4360 /* data size is 0 bytes if the transfer has finished successfully */
4361 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4365 (* Generate the guestfs-structs.h file. *)
4366 and generate_structs_h () =
4367 generate_header CStyle LGPLv2;
4369 (* This is a public exported header file containing various
4370 * structures. The structures are carefully written to have
4371 * exactly the same in-memory format as the XDR structures that
4372 * we use on the wire to the daemon. The reason for creating
4373 * copies of these structures here is just so we don't have to
4374 * export the whole of guestfs_protocol.h (which includes much
4375 * unrelated and XDR-dependent stuff that we don't want to be
4376 * public, or required by clients).
4378 * To reiterate, we will pass these structures to and from the
4379 * client with a simple assignment or memcpy, so the format
4380 * must be identical to what rpcgen / the RFC defines.
4383 (* Public structures. *)
4386 pr "struct guestfs_%s {\n" typ;
4389 | name, FChar -> pr " char %s;\n" name
4390 | name, FString -> pr " char *%s;\n" name
4392 pr " uint32_t %s_len;\n" name;
4393 pr " char *%s;\n" name
4394 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4395 | name, FUInt32 -> pr " uint32_t %s;\n" name
4396 | name, FInt32 -> pr " int32_t %s;\n" name
4397 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4398 | name, FInt64 -> pr " int64_t %s;\n" name
4399 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4403 pr "struct guestfs_%s_list {\n" typ;
4404 pr " uint32_t len;\n";
4405 pr " struct guestfs_%s *val;\n" typ;
4408 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4409 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4413 (* Generate the guestfs-actions.h file. *)
4414 and generate_actions_h () =
4415 generate_header CStyle LGPLv2;
4417 fun (shortname, style, _, _, _, _, _) ->
4418 let name = "guestfs_" ^ shortname in
4419 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4423 (* Generate the client-side dispatch stubs. *)
4424 and generate_client_actions () =
4425 generate_header CStyle LGPLv2;
4431 #include \"guestfs.h\"
4432 #include \"guestfs_protocol.h\"
4434 #define error guestfs_error
4435 #define perrorf guestfs_perrorf
4436 #define safe_malloc guestfs_safe_malloc
4437 #define safe_realloc guestfs_safe_realloc
4438 #define safe_strdup guestfs_safe_strdup
4439 #define safe_memdup guestfs_safe_memdup
4441 /* Check the return message from a call for validity. */
4443 check_reply_header (guestfs_h *g,
4444 const struct guestfs_message_header *hdr,
4445 int proc_nr, int serial)
4447 if (hdr->prog != GUESTFS_PROGRAM) {
4448 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4451 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4452 error (g, \"wrong protocol version (%%d/%%d)\",
4453 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4456 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4457 error (g, \"unexpected message direction (%%d/%%d)\",
4458 hdr->direction, GUESTFS_DIRECTION_REPLY);
4461 if (hdr->proc != proc_nr) {
4462 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4465 if (hdr->serial != serial) {
4466 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4473 /* Check we are in the right state to run a high-level action. */
4475 check_state (guestfs_h *g, const char *caller)
4477 if (!guestfs_is_ready (g)) {
4478 if (guestfs_is_config (g))
4479 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4481 else if (guestfs_is_launching (g))
4482 error (g, \"%%s: call wait_ready() before using this function\",
4485 error (g, \"%%s called from the wrong state, %%d != READY\",
4486 caller, guestfs_get_state (g));
4494 (* Client-side stubs for each function. *)
4496 fun (shortname, style, _, _, _, _, _) ->
4497 let name = "guestfs_" ^ shortname in
4499 (* Generate the context struct which stores the high-level
4500 * state between callback functions.
4502 pr "struct %s_ctx {\n" shortname;
4503 pr " /* This flag is set by the callbacks, so we know we've done\n";
4504 pr " * the callbacks as expected, and in the right sequence.\n";
4505 pr " * 0 = not called, 1 = reply_cb called.\n";
4507 pr " int cb_sequence;\n";
4508 pr " struct guestfs_message_header hdr;\n";
4509 pr " struct guestfs_message_error err;\n";
4510 (match fst style with
4512 | RConstString _ | RConstOptString _ ->
4513 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4515 | RBool _ | RString _ | RStringList _
4516 | RStruct _ | RStructList _
4517 | RHashtable _ | RBufferOut _ ->
4518 pr " struct %s_ret ret;\n" name
4523 (* Generate the reply callback function. *)
4524 pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4526 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4527 pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4529 pr " /* This should definitely not happen. */\n";
4530 pr " if (ctx->cb_sequence != 0) {\n";
4531 pr " ctx->cb_sequence = 9999;\n";
4532 pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4536 pr " ml->main_loop_quit (ml, g);\n";
4538 pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4539 pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4542 pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4543 pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4544 pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4551 (match fst style with
4553 | RConstString _ | RConstOptString _ ->
4554 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4556 | RBool _ | RString _ | RStringList _
4557 | RStruct _ | RStructList _
4558 | RHashtable _ | RBufferOut _ ->
4559 pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4560 pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4566 pr " ctx->cb_sequence = 1;\n";
4569 (* Generate the action stub. *)
4570 generate_prototype ~extern:false ~semicolon:false ~newline:true
4571 ~handle:"g" name style;
4574 match fst style with
4575 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4576 | RConstString _ | RConstOptString _ ->
4577 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4578 | RString _ | RStringList _
4579 | RStruct _ | RStructList _
4580 | RHashtable _ | RBufferOut _ ->
4585 (match snd style with
4587 | _ -> pr " struct %s_args args;\n" name
4590 pr " struct %s_ctx ctx;\n" shortname;
4591 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4592 pr " int serial;\n";
4594 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4595 pr " guestfs_set_busy (g);\n";
4597 pr " memset (&ctx, 0, sizeof ctx);\n";
4600 (* Send the main header and arguments. *)
4601 (match snd style with
4603 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4604 (String.uppercase shortname)
4608 | Pathname n | Device n | Dev_or_Path n | String n ->
4609 pr " args.%s = (char *) %s;\n" n n
4611 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
4613 pr " args.%s.%s_val = (char **) %s;\n" n n n;
4614 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4616 pr " args.%s = %s;\n" n n
4618 pr " args.%s = %s;\n" n n
4619 | FileIn _ | FileOut _ -> ()
4621 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4622 (String.uppercase shortname);
4623 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4626 pr " if (serial == -1) {\n";
4627 pr " guestfs_end_busy (g);\n";
4628 pr " return %s;\n" error_code;
4632 (* Send any additional files (FileIn) requested. *)
4633 let need_read_reply_label = ref false in
4640 pr " r = guestfs__send_file_sync (g, %s);\n" n;
4641 pr " if (r == -1) {\n";
4642 pr " guestfs_end_busy (g);\n";
4643 pr " return %s;\n" error_code;
4645 pr " if (r == -2) /* daemon cancelled */\n";
4646 pr " goto read_reply;\n";
4647 need_read_reply_label := true;
4653 (* Wait for the reply from the remote end. *)
4654 if !need_read_reply_label then pr " read_reply:\n";
4655 pr " guestfs__switch_to_receiving (g);\n";
4656 pr " ctx.cb_sequence = 0;\n";
4657 pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4658 pr " (void) ml->main_loop_run (ml, g);\n";
4659 pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
4660 pr " if (ctx.cb_sequence != 1) {\n";
4661 pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4662 pr " guestfs_end_busy (g);\n";
4663 pr " return %s;\n" error_code;
4667 pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4668 (String.uppercase shortname);
4669 pr " guestfs_end_busy (g);\n";
4670 pr " return %s;\n" error_code;
4674 pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4675 pr " error (g, \"%%s\", ctx.err.error_message);\n";
4676 pr " free (ctx.err.error_message);\n";
4677 pr " guestfs_end_busy (g);\n";
4678 pr " return %s;\n" error_code;
4682 (* Expecting to receive further files (FileOut)? *)
4686 pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4687 pr " guestfs_end_busy (g);\n";
4688 pr " return %s;\n" error_code;
4694 pr " guestfs_end_busy (g);\n";
4696 (match fst style with
4697 | RErr -> pr " return 0;\n"
4698 | RInt n | RInt64 n | RBool n ->
4699 pr " return ctx.ret.%s;\n" n
4700 | RConstString _ | RConstOptString _ ->
4701 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4703 pr " return ctx.ret.%s; /* caller will free */\n" n
4704 | RStringList n | RHashtable n ->
4705 pr " /* caller will free this, but we need to add a NULL entry */\n";
4706 pr " ctx.ret.%s.%s_val =\n" n n;
4707 pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4708 pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4710 pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4711 pr " return ctx.ret.%s.%s_val;\n" n n
4713 pr " /* caller will free this */\n";
4714 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4715 | RStructList (n, _) ->
4716 pr " /* caller will free this */\n";
4717 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4719 pr " *size_r = ctx.ret.%s.%s_len;\n" n n;
4720 pr " return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4726 (* Functions to free structures. *)
4727 pr "/* Structure-freeing functions. These rely on the fact that the\n";
4728 pr " * structure format is identical to the XDR format. See note in\n";
4729 pr " * generator.ml.\n";
4736 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4738 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4744 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4746 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4753 (* Generate daemon/actions.h. *)
4754 and generate_daemon_actions_h () =
4755 generate_header CStyle GPLv2;
4757 pr "#include \"../src/guestfs_protocol.h\"\n";
4761 fun (name, style, _, _, _, _, _) ->
4763 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4767 (* Generate the server-side stubs. *)
4768 and generate_daemon_actions () =
4769 generate_header CStyle GPLv2;
4771 pr "#include <config.h>\n";
4773 pr "#include <stdio.h>\n";
4774 pr "#include <stdlib.h>\n";
4775 pr "#include <string.h>\n";
4776 pr "#include <inttypes.h>\n";
4777 pr "#include <ctype.h>\n";
4778 pr "#include <rpc/types.h>\n";
4779 pr "#include <rpc/xdr.h>\n";
4781 pr "#include \"daemon.h\"\n";
4782 pr "#include \"../src/guestfs_protocol.h\"\n";
4783 pr "#include \"actions.h\"\n";
4787 fun (name, style, _, _, _, _, _) ->
4788 (* Generate server-side stubs. *)
4789 pr "static void %s_stub (XDR *xdr_in)\n" name;
4792 match fst style with
4793 | RErr | RInt _ -> pr " int r;\n"; "-1"
4794 | RInt64 _ -> pr " int64_t r;\n"; "-1"
4795 | RBool _ -> pr " int r;\n"; "-1"
4796 | RConstString _ | RConstOptString _ ->
4797 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4798 | RString _ -> pr " char *r;\n"; "NULL"
4799 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
4800 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
4801 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
4803 pr " size_t size;\n";
4807 (match snd style with
4810 pr " struct guestfs_%s_args args;\n" name;
4813 | Device n | Dev_or_Path n
4816 | OptString n -> pr " char *%s;\n" n
4817 | StringList n -> pr " char **%s;\n" n
4818 | Bool n -> pr " int %s;\n" n
4819 | Int n -> pr " int %s;\n" n
4820 | FileIn _ | FileOut _ -> ()
4825 (match snd style with
4828 pr " memset (&args, 0, sizeof args);\n";
4830 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4831 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4835 pr " char *%s = args.%s;\n" n n
4841 pr " ABS_PATH (%s, goto done);\n" n;
4844 pr " RESOLVE_DEVICE (%s, goto done);" n;
4847 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);" n;
4848 | String n -> pr_args n
4849 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
4851 pr " %s = realloc (args.%s.%s_val,\n" n n n;
4852 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4853 pr " if (%s == NULL) {\n" n;
4854 pr " reply_with_perror (\"realloc\");\n";
4857 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
4858 pr " args.%s.%s_val = %s;\n" n n n;
4859 | Bool n -> pr " %s = args.%s;\n" n n
4860 | Int n -> pr " %s = args.%s;\n" n n
4861 | FileIn _ | FileOut _ -> ()
4866 (* this is used at least for do_equal *)
4867 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
4868 (* Emit NEED_ROOT just once, even when there are two or
4869 more Pathname args *)
4870 pr " NEED_ROOT (goto done);\n";
4873 (* Don't want to call the impl with any FileIn or FileOut
4874 * parameters, since these go "outside" the RPC protocol.
4877 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
4879 pr " r = do_%s " name;
4880 generate_c_call_args (fst style, args');
4883 pr " if (r == %s)\n" error_code;
4884 pr " /* do_%s has already called reply_with_error */\n" name;
4888 (* If there are any FileOut parameters, then the impl must
4889 * send its own reply.
4892 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
4894 pr " /* do_%s has already sent a reply */\n" name
4896 match fst style with
4897 | RErr -> pr " reply (NULL, NULL);\n"
4898 | RInt n | RInt64 n | RBool n ->
4899 pr " struct guestfs_%s_ret ret;\n" name;
4900 pr " ret.%s = r;\n" n;
4901 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4903 | RConstString _ | RConstOptString _ ->
4904 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4906 pr " struct guestfs_%s_ret ret;\n" name;
4907 pr " ret.%s = r;\n" n;
4908 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4911 | RStringList n | RHashtable n ->
4912 pr " struct guestfs_%s_ret ret;\n" name;
4913 pr " ret.%s.%s_len = count_strings (r);\n" n n;
4914 pr " ret.%s.%s_val = r;\n" n n;
4915 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4917 pr " free_strings (r);\n"
4919 pr " struct guestfs_%s_ret ret;\n" name;
4920 pr " ret.%s = *r;\n" n;
4921 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4923 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4925 | RStructList (n, _) ->
4926 pr " struct guestfs_%s_ret ret;\n" name;
4927 pr " ret.%s = *r;\n" n;
4928 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4930 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4933 pr " struct guestfs_%s_ret ret;\n" name;
4934 pr " ret.%s.%s_val = r;\n" n n;
4935 pr " ret.%s.%s_len = size;\n" n n;
4936 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4941 (* Free the args. *)
4942 (match snd style with
4947 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
4954 (* Dispatch function. *)
4955 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
4957 pr " switch (proc_nr) {\n";
4960 fun (name, style, _, _, _, _, _) ->
4961 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
4962 pr " %s_stub (xdr_in);\n" name;
4967 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";
4972 (* LVM columns and tokenization functions. *)
4973 (* XXX This generates crap code. We should rethink how we
4979 pr "static const char *lvm_%s_cols = \"%s\";\n"
4980 typ (String.concat "," (List.map fst cols));
4983 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
4985 pr " char *tok, *p, *next;\n";
4989 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
4992 pr " if (!str) {\n";
4993 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
4996 pr " if (!*str || isspace (*str)) {\n";
4997 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5002 fun (name, coltype) ->
5003 pr " if (!tok) {\n";
5004 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5007 pr " p = strchrnul (tok, ',');\n";
5008 pr " if (*p) next = p+1; else next = NULL;\n";
5009 pr " *p = '\\0';\n";
5012 pr " r->%s = strdup (tok);\n" name;
5013 pr " if (r->%s == NULL) {\n" name;
5014 pr " perror (\"strdup\");\n";
5018 pr " for (i = j = 0; i < 32; ++j) {\n";
5019 pr " if (tok[j] == '\\0') {\n";
5020 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5022 pr " } else if (tok[j] != '-')\n";
5023 pr " r->%s[i++] = tok[j];\n" name;
5026 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5027 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5031 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5032 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5036 pr " if (tok[0] == '\\0')\n";
5037 pr " r->%s = -1;\n" name;
5038 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5039 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5042 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5043 assert false (* can never be an LVM column *)
5045 pr " tok = next;\n";
5048 pr " if (tok != NULL) {\n";
5049 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5056 pr "guestfs_int_lvm_%s_list *\n" typ;
5057 pr "parse_command_line_%ss (void)\n" typ;
5059 pr " char *out, *err;\n";
5060 pr " char *p, *pend;\n";
5062 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
5063 pr " void *newp;\n";
5065 pr " ret = malloc (sizeof *ret);\n";
5066 pr " if (!ret) {\n";
5067 pr " reply_with_perror (\"malloc\");\n";
5068 pr " return NULL;\n";
5071 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5072 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5074 pr " r = command (&out, &err,\n";
5075 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
5076 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5077 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5078 pr " if (r == -1) {\n";
5079 pr " reply_with_error (\"%%s\", err);\n";
5080 pr " free (out);\n";
5081 pr " free (err);\n";
5082 pr " free (ret);\n";
5083 pr " return NULL;\n";
5086 pr " free (err);\n";
5088 pr " /* Tokenize each line of the output. */\n";
5091 pr " while (p) {\n";
5092 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
5093 pr " if (pend) {\n";
5094 pr " *pend = '\\0';\n";
5098 pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
5101 pr " if (!*p) { /* Empty line? Skip it. */\n";
5106 pr " /* Allocate some space to store this next entry. */\n";
5107 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5108 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5109 pr " if (newp == NULL) {\n";
5110 pr " reply_with_perror (\"realloc\");\n";
5111 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5112 pr " free (ret);\n";
5113 pr " free (out);\n";
5114 pr " return NULL;\n";
5116 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5118 pr " /* Tokenize the next entry. */\n";
5119 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5120 pr " if (r == -1) {\n";
5121 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5122 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5123 pr " free (ret);\n";
5124 pr " free (out);\n";
5125 pr " return NULL;\n";
5132 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5134 pr " free (out);\n";
5135 pr " return ret;\n";
5138 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5140 (* Generate a list of function names, for debugging in the daemon.. *)
5141 and generate_daemon_names () =
5142 generate_header CStyle GPLv2;
5144 pr "#include <config.h>\n";
5146 pr "#include \"daemon.h\"\n";
5149 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5150 pr "const char *function_names[] = {\n";
5152 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5156 (* Generate the tests. *)
5157 and generate_tests () =
5158 generate_header CStyle GPLv2;
5165 #include <sys/types.h>
5168 #include \"guestfs.h\"
5170 static guestfs_h *g;
5171 static int suppress_error = 0;
5173 static void print_error (guestfs_h *g, void *data, const char *msg)
5175 if (!suppress_error)
5176 fprintf (stderr, \"%%s\\n\", msg);
5179 static void print_strings (char * const * const argv)
5183 for (argc = 0; argv[argc] != NULL; ++argc)
5184 printf (\"\\t%%s\\n\", argv[argc]);
5188 static void print_table (char * const * const argv)
5192 for (i = 0; argv[i] != NULL; i += 2)
5193 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5199 (* Generate a list of commands which are not tested anywhere. *)
5200 pr "static void no_test_warnings (void)\n";
5203 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5205 fun (_, _, _, _, tests, _, _) ->
5206 let tests = filter_map (
5208 | (_, (Always|If _|Unless _), test) -> Some test
5209 | (_, Disabled, _) -> None
5211 let seq = List.concat (List.map seq_of_test tests) in
5212 let cmds_tested = List.map List.hd seq in
5213 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5217 fun (name, _, _, _, _, _, _) ->
5218 if not (Hashtbl.mem hash name) then
5219 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5225 (* Generate the actual tests. Note that we generate the tests
5226 * in reverse order, deliberately, so that (in general) the
5227 * newest tests run first. This makes it quicker and easier to
5232 fun (name, _, _, _, tests, _, _) ->
5233 mapi (generate_one_test name) tests
5234 ) (List.rev all_functions) in
5235 let test_names = List.concat test_names in
5236 let nr_tests = List.length test_names in
5239 int main (int argc, char *argv[])
5243 const char *filename;
5245 int nr_tests, test_num = 0;
5247 setbuf (stdout, NULL);
5249 no_test_warnings ();
5251 g = guestfs_create ();
5253 printf (\"guestfs_create FAILED\\n\");
5257 guestfs_set_error_handler (g, print_error, NULL);
5259 guestfs_set_path (g, \"../appliance\");
5261 filename = \"test1.img\";
5262 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5267 if (lseek (fd, %d, SEEK_SET) == -1) {
5273 if (write (fd, &c, 1) == -1) {
5279 if (close (fd) == -1) {
5284 if (guestfs_add_drive (g, filename) == -1) {
5285 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5289 filename = \"test2.img\";
5290 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5295 if (lseek (fd, %d, SEEK_SET) == -1) {
5301 if (write (fd, &c, 1) == -1) {
5307 if (close (fd) == -1) {
5312 if (guestfs_add_drive (g, filename) == -1) {
5313 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5317 filename = \"test3.img\";
5318 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5323 if (lseek (fd, %d, SEEK_SET) == -1) {
5329 if (write (fd, &c, 1) == -1) {
5335 if (close (fd) == -1) {
5340 if (guestfs_add_drive (g, filename) == -1) {
5341 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5345 if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
5346 printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
5350 if (guestfs_launch (g) == -1) {
5351 printf (\"guestfs_launch FAILED\\n\");
5355 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5358 if (guestfs_wait_ready (g) == -1) {
5359 printf (\"guestfs_wait_ready FAILED\\n\");
5363 /* Cancel previous alarm. */
5368 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5372 pr " test_num++;\n";
5373 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5374 pr " if (%s () == -1) {\n" test_name;
5375 pr " printf (\"%s FAILED\\n\");\n" test_name;
5381 pr " guestfs_close (g);\n";
5382 pr " unlink (\"test1.img\");\n";
5383 pr " unlink (\"test2.img\");\n";
5384 pr " unlink (\"test3.img\");\n";
5387 pr " if (failed > 0) {\n";
5388 pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
5396 and generate_one_test name i (init, prereq, test) =
5397 let test_name = sprintf "test_%s_%d" name i in
5400 static int %s_skip (void)
5404 str = getenv (\"TEST_ONLY\");
5406 return strstr (str, \"%s\") == NULL;
5407 str = getenv (\"SKIP_%s\");
5408 if (str && strcmp (str, \"1\") == 0) return 1;
5409 str = getenv (\"SKIP_TEST_%s\");
5410 if (str && strcmp (str, \"1\") == 0) return 1;
5414 " test_name name (String.uppercase test_name) (String.uppercase name);
5417 | Disabled | Always -> ()
5418 | If code | Unless code ->
5419 pr "static int %s_prereq (void)\n" test_name;
5427 static int %s (void)
5430 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5434 " test_name test_name test_name;
5438 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5440 pr " if (! %s_prereq ()) {\n" test_name;
5441 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5445 generate_one_test_body name i test_name init test;
5447 pr " if (%s_prereq ()) {\n" test_name;
5448 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5452 generate_one_test_body name i test_name init test;
5454 generate_one_test_body name i test_name init test
5462 and generate_one_test_body name i test_name init test =
5464 | InitNone (* XXX at some point, InitNone and InitEmpty became
5465 * folded together as the same thing. Really we should
5466 * make InitNone do nothing at all, but the tests may
5467 * need to be checked to make sure this is OK.
5470 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5471 List.iter (generate_test_command_call test_name)
5472 [["blockdev_setrw"; "/dev/sda"];
5476 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5477 List.iter (generate_test_command_call test_name)
5478 [["blockdev_setrw"; "/dev/sda"];
5481 ["sfdiskM"; "/dev/sda"; ","]]
5483 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5484 List.iter (generate_test_command_call test_name)
5485 [["blockdev_setrw"; "/dev/sda"];
5488 ["sfdiskM"; "/dev/sda"; ","];
5489 ["mkfs"; "ext2"; "/dev/sda1"];
5490 ["mount"; "/dev/sda1"; "/"]]
5491 | InitBasicFSonLVM ->
5492 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5494 List.iter (generate_test_command_call test_name)
5495 [["blockdev_setrw"; "/dev/sda"];
5498 ["sfdiskM"; "/dev/sda"; ","];
5499 ["pvcreate"; "/dev/sda1"];
5500 ["vgcreate"; "VG"; "/dev/sda1"];
5501 ["lvcreate"; "LV"; "VG"; "8"];
5502 ["mkfs"; "ext2"; "/dev/VG/LV"];
5503 ["mount"; "/dev/VG/LV"; "/"]]
5505 pr " /* InitSquashFS for %s */\n" test_name;
5506 List.iter (generate_test_command_call test_name)
5507 [["blockdev_setrw"; "/dev/sda"];
5510 ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
5513 let get_seq_last = function
5515 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5518 let seq = List.rev seq in
5519 List.rev (List.tl seq), List.hd seq
5524 pr " /* TestRun for %s (%d) */\n" name i;
5525 List.iter (generate_test_command_call test_name) seq
5526 | TestOutput (seq, expected) ->
5527 pr " /* TestOutput for %s (%d) */\n" name i;
5528 pr " const char *expected = \"%s\";\n" (c_quote expected);
5529 let seq, last = get_seq_last seq in
5531 pr " if (strcmp (r, expected) != 0) {\n";
5532 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5536 List.iter (generate_test_command_call test_name) seq;
5537 generate_test_command_call ~test test_name last
5538 | TestOutputList (seq, expected) ->
5539 pr " /* TestOutputList for %s (%d) */\n" name i;
5540 let seq, last = get_seq_last seq in
5544 pr " if (!r[%d]) {\n" i;
5545 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5546 pr " print_strings (r);\n";
5550 pr " const char *expected = \"%s\";\n" (c_quote str);
5551 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5552 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5557 pr " if (r[%d] != NULL) {\n" (List.length expected);
5558 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5560 pr " print_strings (r);\n";
5564 List.iter (generate_test_command_call test_name) seq;
5565 generate_test_command_call ~test test_name last
5566 | TestOutputListOfDevices (seq, expected) ->
5567 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
5568 let seq, last = get_seq_last seq in
5572 pr " if (!r[%d]) {\n" i;
5573 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5574 pr " print_strings (r);\n";
5578 pr " const char *expected = \"%s\";\n" (c_quote str);
5579 pr " r[%d][5] = 's';\n" i;
5580 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5581 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5586 pr " if (r[%d] != NULL) {\n" (List.length expected);
5587 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5589 pr " print_strings (r);\n";
5593 List.iter (generate_test_command_call test_name) seq;
5594 generate_test_command_call ~test test_name last
5595 | TestOutputInt (seq, expected) ->
5596 pr " /* TestOutputInt for %s (%d) */\n" name i;
5597 let seq, last = get_seq_last seq in
5599 pr " if (r != %d) {\n" expected;
5600 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5606 List.iter (generate_test_command_call test_name) seq;
5607 generate_test_command_call ~test test_name last
5608 | TestOutputIntOp (seq, op, expected) ->
5609 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
5610 let seq, last = get_seq_last seq in
5612 pr " if (! (r %s %d)) {\n" op expected;
5613 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5614 test_name op expected;
5619 List.iter (generate_test_command_call test_name) seq;
5620 generate_test_command_call ~test test_name last
5621 | TestOutputTrue seq ->
5622 pr " /* TestOutputTrue for %s (%d) */\n" name i;
5623 let seq, last = get_seq_last seq in
5626 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5631 List.iter (generate_test_command_call test_name) seq;
5632 generate_test_command_call ~test test_name last
5633 | TestOutputFalse seq ->
5634 pr " /* TestOutputFalse for %s (%d) */\n" name i;
5635 let seq, last = get_seq_last seq in
5638 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5643 List.iter (generate_test_command_call test_name) seq;
5644 generate_test_command_call ~test test_name last
5645 | TestOutputLength (seq, expected) ->
5646 pr " /* TestOutputLength for %s (%d) */\n" name i;
5647 let seq, last = get_seq_last seq in
5650 pr " for (j = 0; j < %d; ++j)\n" expected;
5651 pr " if (r[j] == NULL) {\n";
5652 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
5654 pr " print_strings (r);\n";
5657 pr " if (r[j] != NULL) {\n";
5658 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
5660 pr " print_strings (r);\n";
5664 List.iter (generate_test_command_call test_name) seq;
5665 generate_test_command_call ~test test_name last
5666 | TestOutputBuffer (seq, expected) ->
5667 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
5668 pr " const char *expected = \"%s\";\n" (c_quote expected);
5669 let seq, last = get_seq_last seq in
5670 let len = String.length expected in
5672 pr " if (size != %d) {\n" len;
5673 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5676 pr " if (strncmp (r, expected, size) != 0) {\n";
5677 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5681 List.iter (generate_test_command_call test_name) seq;
5682 generate_test_command_call ~test test_name last
5683 | TestOutputStruct (seq, checks) ->
5684 pr " /* TestOutputStruct for %s (%d) */\n" name i;
5685 let seq, last = get_seq_last seq in
5689 | CompareWithInt (field, expected) ->
5690 pr " if (r->%s != %d) {\n" field expected;
5691 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5692 test_name field expected;
5693 pr " (int) r->%s);\n" field;
5696 | CompareWithIntOp (field, op, expected) ->
5697 pr " if (!(r->%s %s %d)) {\n" field op expected;
5698 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5699 test_name field op expected;
5700 pr " (int) r->%s);\n" field;
5703 | CompareWithString (field, expected) ->
5704 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5705 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5706 test_name field expected;
5707 pr " r->%s);\n" field;
5710 | CompareFieldsIntEq (field1, field2) ->
5711 pr " if (r->%s != r->%s) {\n" field1 field2;
5712 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5713 test_name field1 field2;
5714 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
5717 | CompareFieldsStrEq (field1, field2) ->
5718 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5719 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5720 test_name field1 field2;
5721 pr " r->%s, r->%s);\n" field1 field2;
5726 List.iter (generate_test_command_call test_name) seq;
5727 generate_test_command_call ~test test_name last
5728 | TestLastFail seq ->
5729 pr " /* TestLastFail for %s (%d) */\n" name i;
5730 let seq, last = get_seq_last seq in
5731 List.iter (generate_test_command_call test_name) seq;
5732 generate_test_command_call test_name ~expect_error:true last
5734 (* Generate the code to run a command, leaving the result in 'r'.
5735 * If you expect to get an error then you should set expect_error:true.
5737 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5739 | [] -> assert false
5741 (* Look up the command to find out what args/ret it has. *)
5744 let _, style, _, _, _, _, _ =
5745 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5748 failwithf "%s: in test, command %s was not found" test_name name in
5750 if List.length (snd style) <> List.length args then
5751 failwithf "%s: in test, wrong number of args given to %s"
5758 | OptString n, "NULL" -> ()
5761 | Dev_or_Path n, arg
5763 | OptString n, arg ->
5764 pr " const char *%s = \"%s\";\n" n (c_quote arg);
5767 | FileIn _, _ | FileOut _, _ -> ()
5768 | StringList n, arg ->
5769 let strs = string_split " " arg in
5772 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
5774 pr " const char *%s[] = {\n" n;
5776 fun i _ -> pr " %s_%d,\n" n i
5780 ) (List.combine (snd style) args);
5783 match fst style with
5784 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
5785 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5786 | RConstString _ | RConstOptString _ ->
5787 pr " const char *r;\n"; "NULL"
5788 | RString _ -> pr " char *r;\n"; "NULL"
5789 | RStringList _ | RHashtable _ ->
5793 | RStruct (_, typ) ->
5794 pr " struct guestfs_%s *r;\n" typ; "NULL"
5795 | RStructList (_, typ) ->
5796 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
5799 pr " size_t size;\n";
5802 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
5803 pr " r = guestfs_%s (g" name;
5805 (* Generate the parameters. *)
5808 | OptString _, "NULL" -> pr ", NULL"
5810 | Device n, _ | Dev_or_Path n, _
5814 | FileIn _, arg | FileOut _, arg ->
5815 pr ", \"%s\"" (c_quote arg)
5816 | StringList n, _ ->
5820 try int_of_string arg
5821 with Failure "int_of_string" ->
5822 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5825 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5826 ) (List.combine (snd style) args);
5828 (match fst style with
5829 | RBufferOut _ -> pr ", &size"
5835 if not expect_error then
5836 pr " if (r == %s)\n" error_code
5838 pr " if (r != %s)\n" error_code;
5841 (* Insert the test code. *)
5847 (match fst style with
5848 | RErr | RInt _ | RInt64 _ | RBool _
5849 | RConstString _ | RConstOptString _ -> ()
5850 | RString _ | RBufferOut _ -> pr " free (r);\n"
5851 | RStringList _ | RHashtable _ ->
5852 pr " for (i = 0; r[i] != NULL; ++i)\n";
5853 pr " free (r[i]);\n";
5855 | RStruct (_, typ) ->
5856 pr " guestfs_free_%s (r);\n" typ
5857 | RStructList (_, typ) ->
5858 pr " guestfs_free_%s_list (r);\n" typ
5864 let str = replace_str str "\r" "\\r" in
5865 let str = replace_str str "\n" "\\n" in
5866 let str = replace_str str "\t" "\\t" in
5867 let str = replace_str str "\000" "\\0" in
5870 (* Generate a lot of different functions for guestfish. *)
5871 and generate_fish_cmds () =
5872 generate_header CStyle GPLv2;
5876 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5878 let all_functions_sorted =
5880 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5881 ) all_functions_sorted in
5883 pr "#include <stdio.h>\n";
5884 pr "#include <stdlib.h>\n";
5885 pr "#include <string.h>\n";
5886 pr "#include <inttypes.h>\n";
5887 pr "#include <ctype.h>\n";
5889 pr "#include <guestfs.h>\n";
5890 pr "#include \"fish.h\"\n";
5893 (* list_commands function, which implements guestfish -h *)
5894 pr "void list_commands (void)\n";
5896 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
5897 pr " list_builtin_commands ();\n";
5899 fun (name, _, _, flags, _, shortdesc, _) ->
5900 let name = replace_char name '_' '-' in
5901 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
5903 ) all_functions_sorted;
5904 pr " printf (\" %%s\\n\",";
5905 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
5909 (* display_command function, which implements guestfish -h cmd *)
5910 pr "void display_command (const char *cmd)\n";
5913 fun (name, style, _, flags, _, shortdesc, longdesc) ->
5914 let name2 = replace_char name '_' '-' in
5916 try find_map (function FishAlias n -> Some n | _ -> None) flags
5917 with Not_found -> name in
5918 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
5920 match snd style with
5924 name2 (String.concat "> <" (List.map name_of_argt args)) in
5927 if List.mem ProtocolLimitWarning flags then
5928 ("\n\n" ^ protocol_limit_warning)
5931 (* For DangerWillRobinson commands, we should probably have
5932 * guestfish prompt before allowing you to use them (especially
5933 * in interactive mode). XXX
5937 if List.mem DangerWillRobinson flags then
5938 ("\n\n" ^ danger_will_robinson)
5943 match deprecation_notice flags with
5945 | Some txt -> "\n\n" ^ txt in
5947 let describe_alias =
5948 if name <> alias then
5949 sprintf "\n\nYou can use '%s' as an alias for this command." alias
5953 pr "strcasecmp (cmd, \"%s\") == 0" name;
5954 if name <> name2 then
5955 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
5956 if name <> alias then
5957 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
5959 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
5961 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
5964 pr " display_builtin_command (cmd);\n";
5968 (* print_* functions *)
5972 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
5974 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
5983 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
5985 pr " printf (\"%s: \");\n" name;
5986 pr " for (i = 0; i < 32; ++i)\n";
5987 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5988 pr " printf (\"\\n\");\n"
5990 pr " printf (\"%%s%s: \", indent);\n" name;
5991 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
5992 pr " if (isprint (%s->%s[i]))\n" typ name;
5993 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5995 pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
5996 pr " printf (\"\\n\");\n"
5997 | name, (FUInt64|FBytes) ->
5998 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6001 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6004 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6007 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6010 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6012 | name, FOptPercent ->
6013 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6014 typ name name typ name;
6015 pr " else printf (\"%%s%s: \\n\", indent);\n" name
6019 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6021 pr " print_%s_indent (%s, \"\");\n" typ typ;
6024 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6029 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6030 pr " printf (\"[%%d] = {\\n\", i);\n";
6031 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
6032 pr " printf (\"}\\n\");\n";
6038 (* run_<action> actions *)
6040 fun (name, style, _, flags, _, _, _) ->
6041 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6043 (match fst style with
6046 | RBool _ -> pr " int r;\n"
6047 | RInt64 _ -> pr " int64_t r;\n"
6048 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
6049 | RString _ -> pr " char *r;\n"
6050 | RStringList _ | RHashtable _ -> pr " char **r;\n"
6051 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
6052 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
6055 pr " size_t size;\n";
6060 | Device n | Dev_or_Path n
6064 | FileOut n -> pr " const char *%s;\n" n
6065 | StringList n -> pr " char **%s;\n" n
6066 | Bool n -> pr " int %s;\n" n
6067 | Int n -> pr " int %s;\n" n
6070 (* Check and convert parameters. *)
6071 let argc_expected = List.length (snd style) in
6072 pr " if (argc != %d) {\n" argc_expected;
6073 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6075 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6082 | Device name | Dev_or_Path name | String name -> pr " %s = argv[%d];\n" name i
6084 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6087 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6090 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6092 | StringList name ->
6093 pr " %s = parse_string_list (argv[%d]);\n" name i
6095 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6097 pr " %s = atoi (argv[%d]);\n" name i
6100 (* Call C API function. *)
6102 try find_map (function FishAction n -> Some n | _ -> None) flags
6103 with Not_found -> sprintf "guestfs_%s" name in
6105 generate_c_call_args ~handle:"g" style;
6108 (* Check return value for errors and display command results. *)
6109 (match fst style with
6110 | RErr -> pr " return r;\n"
6112 pr " if (r == -1) return -1;\n";
6113 pr " printf (\"%%d\\n\", r);\n";
6116 pr " if (r == -1) return -1;\n";
6117 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6120 pr " if (r == -1) return -1;\n";
6121 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6124 pr " if (r == NULL) return -1;\n";
6125 pr " printf (\"%%s\\n\", r);\n";
6127 | RConstOptString _ ->
6128 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6131 pr " if (r == NULL) return -1;\n";
6132 pr " printf (\"%%s\\n\", r);\n";
6136 pr " if (r == NULL) return -1;\n";
6137 pr " print_strings (r);\n";
6138 pr " free_strings (r);\n";
6140 | RStruct (_, typ) ->
6141 pr " if (r == NULL) return -1;\n";
6142 pr " print_%s (r);\n" typ;
6143 pr " guestfs_free_%s (r);\n" typ;
6145 | RStructList (_, typ) ->
6146 pr " if (r == NULL) return -1;\n";
6147 pr " print_%s_list (r);\n" typ;
6148 pr " guestfs_free_%s_list (r);\n" typ;
6151 pr " if (r == NULL) return -1;\n";
6152 pr " print_table (r);\n";
6153 pr " free_strings (r);\n";
6156 pr " if (r == NULL) return -1;\n";
6157 pr " fwrite (r, size, 1, stdout);\n";
6165 (* run_action function *)
6166 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6169 fun (name, _, _, flags, _, _, _) ->
6170 let name2 = replace_char name '_' '-' in
6172 try find_map (function FishAlias n -> Some n | _ -> None) flags
6173 with Not_found -> name in
6175 pr "strcasecmp (cmd, \"%s\") == 0" name;
6176 if name <> name2 then
6177 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6178 if name <> alias then
6179 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6181 pr " return run_%s (cmd, argc, argv);\n" name;
6185 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6192 (* Readline completion for guestfish. *)
6193 and generate_fish_completion () =
6194 generate_header CStyle GPLv2;
6198 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6208 #ifdef HAVE_LIBREADLINE
6209 #include <readline/readline.h>
6214 #ifdef HAVE_LIBREADLINE
6216 static const char *const commands[] = {
6217 BUILTIN_COMMANDS_FOR_COMPLETION,
6220 (* Get the commands, including the aliases. They don't need to be
6221 * sorted - the generator() function just does a dumb linear search.
6225 fun (name, _, _, flags, _, _, _) ->
6226 let name2 = replace_char name '_' '-' in
6228 try find_map (function FishAlias n -> Some n | _ -> None) flags
6229 with Not_found -> name in
6231 if name <> alias then [name2; alias] else [name2]
6233 let commands = List.flatten commands in
6235 List.iter (pr " \"%s\",\n") commands;
6241 generator (const char *text, int state)
6243 static int index, len;
6248 len = strlen (text);
6251 rl_attempted_completion_over = 1;
6253 while ((name = commands[index]) != NULL) {
6255 if (strncasecmp (name, text, len) == 0)
6256 return strdup (name);
6262 #endif /* HAVE_LIBREADLINE */
6264 char **do_completion (const char *text, int start, int end)
6266 char **matches = NULL;
6268 #ifdef HAVE_LIBREADLINE
6269 rl_completion_append_character = ' ';
6272 matches = rl_completion_matches (text, generator);
6273 else if (complete_dest_paths)
6274 matches = rl_completion_matches (text, complete_dest_paths_generator);
6281 (* Generate the POD documentation for guestfish. *)
6282 and generate_fish_actions_pod () =
6283 let all_functions_sorted =
6285 fun (_, _, _, flags, _, _, _) ->
6286 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6287 ) all_functions_sorted in
6289 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6292 fun (name, style, _, flags, _, _, longdesc) ->
6294 Str.global_substitute rex (
6297 try Str.matched_group 1 s
6299 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6300 "C<" ^ replace_char sub '_' '-' ^ ">"
6302 let name = replace_char name '_' '-' in
6304 try find_map (function FishAlias n -> Some n | _ -> None) flags
6305 with Not_found -> name in
6307 pr "=head2 %s" name;
6308 if name <> alias then
6315 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6316 | OptString n -> pr " %s" n
6317 | StringList n -> pr " '%s ...'" n
6318 | Bool _ -> pr " true|false"
6319 | Int n -> pr " %s" n
6320 | FileIn n | FileOut n -> pr " (%s|-)" n
6324 pr "%s\n\n" longdesc;
6326 if List.exists (function FileIn _ | FileOut _ -> true
6327 | _ -> false) (snd style) then
6328 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6330 if List.mem ProtocolLimitWarning flags then
6331 pr "%s\n\n" protocol_limit_warning;
6333 if List.mem DangerWillRobinson flags then
6334 pr "%s\n\n" danger_will_robinson;
6336 match deprecation_notice flags with
6338 | Some txt -> pr "%s\n\n" txt
6339 ) all_functions_sorted
6341 (* Generate a C function prototype. *)
6342 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6343 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6345 ?handle name style =
6346 if extern then pr "extern ";
6347 if static then pr "static ";
6348 (match fst style with
6350 | RInt _ -> pr "int "
6351 | RInt64 _ -> pr "int64_t "
6352 | RBool _ -> pr "int "
6353 | RConstString _ | RConstOptString _ -> pr "const char *"
6354 | RString _ | RBufferOut _ -> pr "char *"
6355 | RStringList _ | RHashtable _ -> pr "char **"
6356 | RStruct (_, typ) ->
6357 if not in_daemon then pr "struct guestfs_%s *" typ
6358 else pr "guestfs_int_%s *" typ
6359 | RStructList (_, typ) ->
6360 if not in_daemon then pr "struct guestfs_%s_list *" typ
6361 else pr "guestfs_int_%s_list *" typ
6363 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6364 pr "%s%s (" prefix name;
6365 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6368 let comma = ref false in
6371 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6375 if single_line then pr ", " else pr ",\n\t\t"
6382 | Device n | Dev_or_Path n
6386 pr "const char *%s" n
6389 if not in_daemon then pr "char * const* const %s" n
6390 else pr "char **%s" n
6391 | Bool n -> next (); pr "int %s" n
6392 | Int n -> next (); pr "int %s" n
6395 if not in_daemon then (next (); pr "const char *%s" n)
6397 if is_RBufferOut then (next (); pr "size_t *size_r");
6400 if semicolon then pr ";";
6401 if newline then pr "\n"
6403 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6404 and generate_c_call_args ?handle ?(decl = false) style =
6406 let comma = ref false in
6408 if !comma then pr ", ";
6413 | Some handle -> pr "%s" handle; comma := true
6418 pr "%s" (name_of_argt arg)
6420 (* For RBufferOut calls, add implicit &size parameter. *)
6422 match fst style with
6430 (* Generate the OCaml bindings interface. *)
6431 and generate_ocaml_mli () =
6432 generate_header OCamlStyle LGPLv2;
6435 (** For API documentation you should refer to the C API
6436 in the guestfs(3) manual page. The OCaml API uses almost
6437 exactly the same calls. *)
6440 (** A [guestfs_h] handle. *)
6442 exception Error of string
6443 (** This exception is raised when there is an error. *)
6445 val create : unit -> t
6447 val close : t -> unit
6448 (** Handles are closed by the garbage collector when they become
6449 unreferenced, but callers can also call this in order to
6450 provide predictable cleanup. *)
6453 generate_ocaml_structure_decls ();
6457 fun (name, style, _, _, _, shortdesc, _) ->
6458 generate_ocaml_prototype name style;
6459 pr "(** %s *)\n" shortdesc;
6463 (* Generate the OCaml bindings implementation. *)
6464 and generate_ocaml_ml () =
6465 generate_header OCamlStyle LGPLv2;
6469 exception Error of string
6470 external create : unit -> t = \"ocaml_guestfs_create\"
6471 external close : t -> unit = \"ocaml_guestfs_close\"
6474 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6478 generate_ocaml_structure_decls ();
6482 fun (name, style, _, _, _, shortdesc, _) ->
6483 generate_ocaml_prototype ~is_external:true name style;
6486 (* Generate the OCaml bindings C implementation. *)
6487 and generate_ocaml_c () =
6488 generate_header CStyle LGPLv2;
6495 #include <caml/config.h>
6496 #include <caml/alloc.h>
6497 #include <caml/callback.h>
6498 #include <caml/fail.h>
6499 #include <caml/memory.h>
6500 #include <caml/mlvalues.h>
6501 #include <caml/signals.h>
6503 #include <guestfs.h>
6505 #include \"guestfs_c.h\"
6507 /* Copy a hashtable of string pairs into an assoc-list. We return
6508 * the list in reverse order, but hashtables aren't supposed to be
6511 static CAMLprim value
6512 copy_table (char * const * argv)
6515 CAMLlocal5 (rv, pairv, kv, vv, cons);
6519 for (i = 0; argv[i] != NULL; i += 2) {
6520 kv = caml_copy_string (argv[i]);
6521 vv = caml_copy_string (argv[i+1]);
6522 pairv = caml_alloc (2, 0);
6523 Store_field (pairv, 0, kv);
6524 Store_field (pairv, 1, vv);
6525 cons = caml_alloc (2, 0);
6526 Store_field (cons, 1, rv);
6528 Store_field (cons, 0, pairv);
6536 (* Struct copy functions. *)
6539 let has_optpercent_col =
6540 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6542 pr "static CAMLprim value\n";
6543 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6545 pr " CAMLparam0 ();\n";
6546 if has_optpercent_col then
6547 pr " CAMLlocal3 (rv, v, v2);\n"
6549 pr " CAMLlocal2 (rv, v);\n";
6551 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
6556 pr " v = caml_copy_string (%s->%s);\n" typ name
6558 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
6559 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6562 pr " v = caml_alloc_string (32);\n";
6563 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
6564 | name, (FBytes|FInt64|FUInt64) ->
6565 pr " v = caml_copy_int64 (%s->%s);\n" typ name
6566 | name, (FInt32|FUInt32) ->
6567 pr " v = caml_copy_int32 (%s->%s);\n" typ name
6568 | name, FOptPercent ->
6569 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6570 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
6571 pr " v = caml_alloc (1, 0);\n";
6572 pr " Store_field (v, 0, v2);\n";
6573 pr " } else /* None */\n";
6574 pr " v = Val_int (0);\n";
6576 pr " v = Val_int (%s->%s);\n" typ name
6578 pr " Store_field (rv, %d, v);\n" i
6580 pr " CAMLreturn (rv);\n";
6584 pr "static CAMLprim value\n";
6585 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
6588 pr " CAMLparam0 ();\n";
6589 pr " CAMLlocal2 (rv, v);\n";
6592 pr " if (%ss->len == 0)\n" typ;
6593 pr " CAMLreturn (Atom (0));\n";
6595 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
6596 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6597 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
6598 pr " caml_modify (&Field (rv, i), v);\n";
6600 pr " CAMLreturn (rv);\n";
6608 fun (name, style, _, _, _, _, _) ->
6610 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6612 let needs_extra_vs =
6613 match fst style with RConstOptString _ -> true | _ -> false in
6615 pr "CAMLprim value\n";
6616 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6617 List.iter (pr ", value %s") (List.tl params);
6622 | [p1; p2; p3; p4; p5] ->
6623 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
6624 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6625 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6626 pr " CAMLxparam%d (%s);\n"
6627 (List.length rest) (String.concat ", " rest)
6629 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6631 if not needs_extra_vs then
6632 pr " CAMLlocal1 (rv);\n"
6634 pr " CAMLlocal3 (rv, v, v2);\n";
6637 pr " guestfs_h *g = Guestfs_val (gv);\n";
6638 pr " if (g == NULL)\n";
6639 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
6645 | Device n | Dev_or_Path n
6649 pr " const char *%s = String_val (%sv);\n" n n
6651 pr " const char *%s =\n" n;
6652 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6655 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6657 pr " int %s = Bool_val (%sv);\n" n n
6659 pr " int %s = Int_val (%sv);\n" n n
6662 match fst style with
6663 | RErr -> pr " int r;\n"; "-1"
6664 | RInt _ -> pr " int r;\n"; "-1"
6665 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6666 | RBool _ -> pr " int r;\n"; "-1"
6667 | RConstString _ | RConstOptString _ ->
6668 pr " const char *r;\n"; "NULL"
6669 | RString _ -> pr " char *r;\n"; "NULL"
6674 | RStruct (_, typ) ->
6675 pr " struct guestfs_%s *r;\n" typ; "NULL"
6676 | RStructList (_, typ) ->
6677 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6684 pr " size_t size;\n";
6688 pr " caml_enter_blocking_section ();\n";
6689 pr " r = guestfs_%s " name;
6690 generate_c_call_args ~handle:"g" style;
6692 pr " caml_leave_blocking_section ();\n";
6697 pr " ocaml_guestfs_free_strings (%s);\n" n;
6698 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6699 | FileIn _ | FileOut _ -> ()
6702 pr " if (r == %s)\n" error_code;
6703 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6706 (match fst style with
6707 | RErr -> pr " rv = Val_unit;\n"
6708 | RInt _ -> pr " rv = Val_int (r);\n"
6710 pr " rv = caml_copy_int64 (r);\n"
6711 | RBool _ -> pr " rv = Val_bool (r);\n"
6713 pr " rv = caml_copy_string (r);\n"
6714 | RConstOptString _ ->
6715 pr " if (r) { /* Some string */\n";
6716 pr " v = caml_alloc (1, 0);\n";
6717 pr " v2 = caml_copy_string (r);\n";
6718 pr " Store_field (v, 0, v2);\n";
6719 pr " } else /* None */\n";
6720 pr " v = Val_int (0);\n";
6722 pr " rv = caml_copy_string (r);\n";
6725 pr " rv = caml_copy_string_array ((const char **) r);\n";
6726 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6728 | RStruct (_, typ) ->
6729 pr " rv = copy_%s (r);\n" typ;
6730 pr " guestfs_free_%s (r);\n" typ;
6731 | RStructList (_, typ) ->
6732 pr " rv = copy_%s_list (r);\n" typ;
6733 pr " guestfs_free_%s_list (r);\n" typ;
6735 pr " rv = copy_table (r);\n";
6736 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6739 pr " rv = caml_alloc_string (size);\n";
6740 pr " memcpy (String_val (rv), r, size);\n";
6743 pr " CAMLreturn (rv);\n";
6747 if List.length params > 5 then (
6748 pr "CAMLprim value\n";
6749 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6751 pr " return ocaml_guestfs_%s (argv[0]" name;
6752 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6759 and generate_ocaml_structure_decls () =
6762 pr "type %s = {\n" typ;
6765 | name, FString -> pr " %s : string;\n" name
6766 | name, FBuffer -> pr " %s : string;\n" name
6767 | name, FUUID -> pr " %s : string;\n" name
6768 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
6769 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
6770 | name, FChar -> pr " %s : char;\n" name
6771 | name, FOptPercent -> pr " %s : float option;\n" name
6777 and generate_ocaml_prototype ?(is_external = false) name style =
6778 if is_external then pr "external " else pr "val ";
6779 pr "%s : t -> " name;
6782 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6783 | OptString _ -> pr "string option -> "
6784 | StringList _ -> pr "string array -> "
6785 | Bool _ -> pr "bool -> "
6786 | Int _ -> pr "int -> "
6788 (match fst style with
6789 | RErr -> pr "unit" (* all errors are turned into exceptions *)
6790 | RInt _ -> pr "int"
6791 | RInt64 _ -> pr "int64"
6792 | RBool _ -> pr "bool"
6793 | RConstString _ -> pr "string"
6794 | RConstOptString _ -> pr "string option"
6795 | RString _ | RBufferOut _ -> pr "string"
6796 | RStringList _ -> pr "string array"
6797 | RStruct (_, typ) -> pr "%s" typ
6798 | RStructList (_, typ) -> pr "%s array" typ
6799 | RHashtable _ -> pr "(string * string) list"
6801 if is_external then (
6803 if List.length (snd style) + 1 > 5 then
6804 pr "\"ocaml_guestfs_%s_byte\" " name;
6805 pr "\"ocaml_guestfs_%s\"" name
6809 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
6810 and generate_perl_xs () =
6811 generate_header CStyle LGPLv2;
6814 #include \"EXTERN.h\"
6818 #include <guestfs.h>
6821 #define PRId64 \"lld\"
6825 my_newSVll(long long val) {
6826 #ifdef USE_64_BIT_ALL
6827 return newSViv(val);
6831 len = snprintf(buf, 100, \"%%\" PRId64, val);
6832 return newSVpv(buf, len);
6837 #define PRIu64 \"llu\"
6841 my_newSVull(unsigned long long val) {
6842 #ifdef USE_64_BIT_ALL
6843 return newSVuv(val);
6847 len = snprintf(buf, 100, \"%%\" PRIu64, val);
6848 return newSVpv(buf, len);
6852 /* http://www.perlmonks.org/?node_id=680842 */
6854 XS_unpack_charPtrPtr (SV *arg) {
6859 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
6860 croak (\"array reference expected\");
6862 av = (AV *)SvRV (arg);
6863 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
6865 croak (\"malloc failed\");
6867 for (i = 0; i <= av_len (av); i++) {
6868 SV **elem = av_fetch (av, i, 0);
6870 if (!elem || !*elem)
6871 croak (\"missing element in list\");
6873 ret[i] = SvPV_nolen (*elem);
6881 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
6888 RETVAL = guestfs_create ();
6890 croak (\"could not create guestfs handle\");
6891 guestfs_set_error_handler (RETVAL, NULL, NULL);
6904 fun (name, style, _, _, _, _, _) ->
6905 (match fst style with
6906 | RErr -> pr "void\n"
6907 | RInt _ -> pr "SV *\n"
6908 | RInt64 _ -> pr "SV *\n"
6909 | RBool _ -> pr "SV *\n"
6910 | RConstString _ -> pr "SV *\n"
6911 | RConstOptString _ -> pr "SV *\n"
6912 | RString _ -> pr "SV *\n"
6913 | RBufferOut _ -> pr "SV *\n"
6915 | RStruct _ | RStructList _
6917 pr "void\n" (* all lists returned implictly on the stack *)
6919 (* Call and arguments. *)
6921 generate_c_call_args ~handle:"g" ~decl:true style;
6923 pr " guestfs_h *g;\n";
6927 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
6930 (* http://www.perlmonks.org/?node_id=554277
6931 * Note that the implicit handle argument means we have
6932 * to add 1 to the ST(x) operator.
6934 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
6935 | StringList n -> pr " char **%s;\n" n
6936 | Bool n -> pr " int %s;\n" n
6937 | Int n -> pr " int %s;\n" n
6940 let do_cleanups () =
6943 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6944 | FileIn _ | FileOut _ -> ()
6945 | StringList n -> pr " free (%s);\n" n
6950 (match fst style with
6955 pr " r = guestfs_%s " name;
6956 generate_c_call_args ~handle:"g" style;
6959 pr " if (r == -1)\n";
6960 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6966 pr " %s = guestfs_%s " n name;
6967 generate_c_call_args ~handle:"g" style;
6970 pr " if (%s == -1)\n" n;
6971 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6972 pr " RETVAL = newSViv (%s);\n" n;
6977 pr " int64_t %s;\n" n;
6979 pr " %s = guestfs_%s " n name;
6980 generate_c_call_args ~handle:"g" style;
6983 pr " if (%s == -1)\n" n;
6984 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6985 pr " RETVAL = my_newSVll (%s);\n" n;
6990 pr " const char *%s;\n" n;
6992 pr " %s = guestfs_%s " n name;
6993 generate_c_call_args ~handle:"g" style;
6996 pr " if (%s == NULL)\n" n;
6997 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6998 pr " RETVAL = newSVpv (%s, 0);\n" n;
7001 | RConstOptString n ->
7003 pr " const char *%s;\n" n;
7005 pr " %s = guestfs_%s " n name;
7006 generate_c_call_args ~handle:"g" style;
7009 pr " if (%s == NULL)\n" n;
7010 pr " RETVAL = &PL_sv_undef;\n";
7012 pr " RETVAL = newSVpv (%s, 0);\n" n;
7017 pr " char *%s;\n" n;
7019 pr " %s = guestfs_%s " n name;
7020 generate_c_call_args ~handle:"g" style;
7023 pr " if (%s == NULL)\n" n;
7024 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7025 pr " RETVAL = newSVpv (%s, 0);\n" n;
7026 pr " free (%s);\n" n;
7029 | RStringList n | RHashtable n ->
7031 pr " char **%s;\n" n;
7034 pr " %s = guestfs_%s " n name;
7035 generate_c_call_args ~handle:"g" style;
7038 pr " if (%s == NULL)\n" n;
7039 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7040 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7041 pr " EXTEND (SP, n);\n";
7042 pr " for (i = 0; i < n; ++i) {\n";
7043 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7044 pr " free (%s[i]);\n" n;
7046 pr " free (%s);\n" n;
7047 | RStruct (n, typ) ->
7048 let cols = cols_of_struct typ in
7049 generate_perl_struct_code typ cols name style n do_cleanups
7050 | RStructList (n, typ) ->
7051 let cols = cols_of_struct typ in
7052 generate_perl_struct_list_code typ cols name style n do_cleanups
7055 pr " char *%s;\n" n;
7056 pr " size_t size;\n";
7058 pr " %s = guestfs_%s " n name;
7059 generate_c_call_args ~handle:"g" style;
7062 pr " if (%s == NULL)\n" n;
7063 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7064 pr " RETVAL = newSVpv (%s, size);\n" n;
7065 pr " free (%s);\n" n;
7073 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7075 pr " struct guestfs_%s_list *%s;\n" typ n;
7079 pr " %s = guestfs_%s " n name;
7080 generate_c_call_args ~handle:"g" style;
7083 pr " if (%s == NULL)\n" n;
7084 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7085 pr " EXTEND (SP, %s->len);\n" n;
7086 pr " for (i = 0; i < %s->len; ++i) {\n" n;
7087 pr " hv = newHV ();\n";
7091 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7092 name (String.length name) n name
7094 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7095 name (String.length name) n name
7097 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7098 name (String.length name) n name n name
7099 | name, (FBytes|FUInt64) ->
7100 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7101 name (String.length name) n name
7103 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7104 name (String.length name) n name
7105 | name, (FInt32|FUInt32) ->
7106 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7107 name (String.length name) n name
7109 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7110 name (String.length name) n name
7111 | name, FOptPercent ->
7112 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7113 name (String.length name) n name
7115 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7117 pr " guestfs_free_%s_list (%s);\n" typ n
7119 and generate_perl_struct_code typ cols name style n do_cleanups =
7121 pr " struct guestfs_%s *%s;\n" typ n;
7123 pr " %s = guestfs_%s " n name;
7124 generate_c_call_args ~handle:"g" style;
7127 pr " if (%s == NULL)\n" n;
7128 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7129 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7131 fun ((name, _) as col) ->
7132 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7136 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7139 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7142 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7144 | name, (FBytes|FUInt64) ->
7145 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7148 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7150 | name, (FInt32|FUInt32) ->
7151 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7154 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7156 | name, FOptPercent ->
7157 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7160 pr " free (%s);\n" n
7162 (* Generate Sys/Guestfs.pm. *)
7163 and generate_perl_pm () =
7164 generate_header HashStyle LGPLv2;
7171 Sys::Guestfs - Perl bindings for libguestfs
7177 my $h = Sys::Guestfs->new ();
7178 $h->add_drive ('guest.img');
7181 $h->mount ('/dev/sda1', '/');
7182 $h->touch ('/hello');
7187 The C<Sys::Guestfs> module provides a Perl XS binding to the
7188 libguestfs API for examining and modifying virtual machine
7191 Amongst the things this is good for: making batch configuration
7192 changes to guests, getting disk used/free statistics (see also:
7193 virt-df), migrating between virtualization systems (see also:
7194 virt-p2v), performing partial backups, performing partial guest
7195 clones, cloning guests and changing registry/UUID/hostname info, and
7198 Libguestfs uses Linux kernel and qemu code, and can access any type of
7199 guest filesystem that Linux and qemu can, including but not limited
7200 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7201 schemes, qcow, qcow2, vmdk.
7203 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7204 LVs, what filesystem is in each LV, etc.). It can also run commands
7205 in the context of the guest. Also you can access filesystems over FTP.
7207 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7208 functions for using libguestfs from Perl, including integration
7213 All errors turn into calls to C<croak> (see L<Carp(3)>).
7221 package Sys::Guestfs;
7227 XSLoader::load ('Sys::Guestfs');
7229 =item $h = Sys::Guestfs->new ();
7231 Create a new guestfs handle.
7237 my $class = ref ($proto) || $proto;
7239 my $self = Sys::Guestfs::_create ();
7240 bless $self, $class;
7246 (* Actions. We only need to print documentation for these as
7247 * they are pulled in from the XS code automatically.
7250 fun (name, style, _, flags, _, _, longdesc) ->
7251 if not (List.mem NotInDocs flags) then (
7252 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7254 generate_perl_prototype name style;
7256 pr "%s\n\n" longdesc;
7257 if List.mem ProtocolLimitWarning flags then
7258 pr "%s\n\n" protocol_limit_warning;
7259 if List.mem DangerWillRobinson flags then
7260 pr "%s\n\n" danger_will_robinson;
7261 match deprecation_notice flags with
7263 | Some txt -> pr "%s\n\n" txt
7265 ) all_functions_sorted;
7277 Copyright (C) 2009 Red Hat Inc.
7281 Please see the file COPYING.LIB for the full license.
7287 L<http://libguestfs.org>,
7288 L<Sys::Guestfs::Lib(3)>.
7293 and generate_perl_prototype name style =
7294 (match fst style with
7302 | RBufferOut n -> pr "$%s = " n
7304 | RHashtable n -> pr "%%%s = " n
7306 | RStructList (n,_) -> pr "@%s = " n
7309 let comma = ref false in
7312 if !comma then pr ", ";
7315 | Pathname n | Device n | Dev_or_Path n | String n
7316 | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7323 (* Generate Python C module. *)
7324 and generate_python_c () =
7325 generate_header CStyle LGPLv2;
7334 #include \"guestfs.h\"
7342 get_handle (PyObject *obj)
7345 assert (obj != Py_None);
7346 return ((Pyguestfs_Object *) obj)->g;
7350 put_handle (guestfs_h *g)
7354 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7357 /* This list should be freed (but not the strings) after use. */
7358 static const char **
7359 get_string_list (PyObject *obj)
7366 if (!PyList_Check (obj)) {
7367 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7371 len = PyList_Size (obj);
7372 r = malloc (sizeof (char *) * (len+1));
7374 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7378 for (i = 0; i < len; ++i)
7379 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7386 put_string_list (char * const * const argv)
7391 for (argc = 0; argv[argc] != NULL; ++argc)
7394 list = PyList_New (argc);
7395 for (i = 0; i < argc; ++i)
7396 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7402 put_table (char * const * const argv)
7404 PyObject *list, *item;
7407 for (argc = 0; argv[argc] != NULL; ++argc)
7410 list = PyList_New (argc >> 1);
7411 for (i = 0; i < argc; i += 2) {
7412 item = PyTuple_New (2);
7413 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7414 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7415 PyList_SetItem (list, i >> 1, item);
7422 free_strings (char **argv)
7426 for (argc = 0; argv[argc] != NULL; ++argc)
7432 py_guestfs_create (PyObject *self, PyObject *args)
7436 g = guestfs_create ();
7438 PyErr_SetString (PyExc_RuntimeError,
7439 \"guestfs.create: failed to allocate handle\");
7442 guestfs_set_error_handler (g, NULL, NULL);
7443 return put_handle (g);
7447 py_guestfs_close (PyObject *self, PyObject *args)
7452 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7454 g = get_handle (py_g);
7458 Py_INCREF (Py_None);
7464 let emit_put_list_function typ =
7465 pr "static PyObject *\n";
7466 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7468 pr " PyObject *list;\n";
7471 pr " list = PyList_New (%ss->len);\n" typ;
7472 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7473 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7474 pr " return list;\n";
7479 (* Structures, turned into Python dictionaries. *)
7482 pr "static PyObject *\n";
7483 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7485 pr " PyObject *dict;\n";
7487 pr " dict = PyDict_New ();\n";
7491 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7492 pr " PyString_FromString (%s->%s));\n"
7495 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7496 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7499 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7500 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
7502 | name, (FBytes|FUInt64) ->
7503 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7504 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
7507 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7508 pr " PyLong_FromLongLong (%s->%s));\n"
7511 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7512 pr " PyLong_FromUnsignedLong (%s->%s));\n"
7515 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7516 pr " PyLong_FromLong (%s->%s));\n"
7518 | name, FOptPercent ->
7519 pr " if (%s->%s >= 0)\n" typ name;
7520 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7521 pr " PyFloat_FromDouble ((double) %s->%s));\n"
7524 pr " Py_INCREF (Py_None);\n";
7525 pr " PyDict_SetItemString (dict, \"%s\", Py_None);" name;
7528 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7529 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7531 pr " return dict;\n";
7537 (* Emit a put_TYPE_list function definition only if that function is used. *)
7540 | typ, (RStructListOnly | RStructAndList) ->
7541 (* generate the function for typ *)
7542 emit_put_list_function typ
7543 | typ, _ -> () (* empty *)
7546 (* Python wrapper functions. *)
7548 fun (name, style, _, _, _, _, _) ->
7549 pr "static PyObject *\n";
7550 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7553 pr " PyObject *py_g;\n";
7554 pr " guestfs_h *g;\n";
7555 pr " PyObject *py_r;\n";
7558 match fst style with
7559 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7560 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7561 | RConstString _ | RConstOptString _ ->
7562 pr " const char *r;\n"; "NULL"
7563 | RString _ -> pr " char *r;\n"; "NULL"
7564 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7565 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7566 | RStructList (_, typ) ->
7567 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7570 pr " size_t size;\n";
7575 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7576 pr " const char *%s;\n" n
7577 | OptString n -> pr " const char *%s;\n" n
7579 pr " PyObject *py_%s;\n" n;
7580 pr " const char **%s;\n" n
7581 | Bool n -> pr " int %s;\n" n
7582 | Int n -> pr " int %s;\n" n
7587 (* Convert the parameters. *)
7588 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
7591 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7592 | OptString _ -> pr "z"
7593 | StringList _ -> pr "O"
7594 | Bool _ -> pr "i" (* XXX Python has booleans? *)
7597 pr ":guestfs_%s\",\n" name;
7601 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7602 | OptString n -> pr ", &%s" n
7603 | StringList n -> pr ", &py_%s" n
7604 | Bool n -> pr ", &%s" n
7605 | Int n -> pr ", &%s" n
7609 pr " return NULL;\n";
7611 pr " g = get_handle (py_g);\n";
7614 | Pathname _ | Device _ | Dev_or_Path _ | String _
7615 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7617 pr " %s = get_string_list (py_%s);\n" n n;
7618 pr " if (!%s) return NULL;\n" n
7623 pr " r = guestfs_%s " name;
7624 generate_c_call_args ~handle:"g" style;
7629 | Pathname _ | Device _ | Dev_or_Path _ | String _
7630 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7632 pr " free (%s);\n" n
7635 pr " if (r == %s) {\n" error_code;
7636 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7637 pr " return NULL;\n";
7641 (match fst style with
7643 pr " Py_INCREF (Py_None);\n";
7644 pr " py_r = Py_None;\n"
7646 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
7647 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
7648 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
7649 | RConstOptString _ ->
7651 pr " py_r = PyString_FromString (r);\n";
7653 pr " Py_INCREF (Py_None);\n";
7654 pr " py_r = Py_None;\n";
7657 pr " py_r = PyString_FromString (r);\n";
7660 pr " py_r = put_string_list (r);\n";
7661 pr " free_strings (r);\n"
7662 | RStruct (_, typ) ->
7663 pr " py_r = put_%s (r);\n" typ;
7664 pr " guestfs_free_%s (r);\n" typ
7665 | RStructList (_, typ) ->
7666 pr " py_r = put_%s_list (r);\n" typ;
7667 pr " guestfs_free_%s_list (r);\n" typ
7669 pr " py_r = put_table (r);\n";
7670 pr " free_strings (r);\n"
7672 pr " py_r = PyString_FromStringAndSize (r, size);\n";
7676 pr " return py_r;\n";
7681 (* Table of functions. *)
7682 pr "static PyMethodDef methods[] = {\n";
7683 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7684 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7686 fun (name, _, _, _, _, _, _) ->
7687 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7690 pr " { NULL, NULL, 0, NULL }\n";
7694 (* Init function. *)
7697 initlibguestfsmod (void)
7699 static int initialized = 0;
7701 if (initialized) return;
7702 Py_InitModule ((char *) \"libguestfsmod\", methods);
7707 (* Generate Python module. *)
7708 and generate_python_py () =
7709 generate_header HashStyle LGPLv2;
7712 u\"\"\"Python bindings for libguestfs
7715 g = guestfs.GuestFS ()
7716 g.add_drive (\"guest.img\")
7719 parts = g.list_partitions ()
7721 The guestfs module provides a Python binding to the libguestfs API
7722 for examining and modifying virtual machine disk images.
7724 Amongst the things this is good for: making batch configuration
7725 changes to guests, getting disk used/free statistics (see also:
7726 virt-df), migrating between virtualization systems (see also:
7727 virt-p2v), performing partial backups, performing partial guest
7728 clones, cloning guests and changing registry/UUID/hostname info, and
7731 Libguestfs uses Linux kernel and qemu code, and can access any type of
7732 guest filesystem that Linux and qemu can, including but not limited
7733 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7734 schemes, qcow, qcow2, vmdk.
7736 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7737 LVs, what filesystem is in each LV, etc.). It can also run commands
7738 in the context of the guest. Also you can access filesystems over FTP.
7740 Errors which happen while using the API are turned into Python
7741 RuntimeError exceptions.
7743 To create a guestfs handle you usually have to perform the following
7746 # Create the handle, call add_drive at least once, and possibly
7747 # several times if the guest has multiple block devices:
7748 g = guestfs.GuestFS ()
7749 g.add_drive (\"guest.img\")
7751 # Launch the qemu subprocess and wait for it to become ready:
7755 # Now you can issue commands, for example:
7760 import libguestfsmod
7763 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7765 def __init__ (self):
7766 \"\"\"Create a new libguestfs handle.\"\"\"
7767 self._o = libguestfsmod.create ()
7770 libguestfsmod.close (self._o)
7775 fun (name, style, _, flags, _, _, longdesc) ->
7777 generate_py_call_args ~handle:"self" (snd style);
7780 if not (List.mem NotInDocs flags) then (
7781 let doc = replace_str longdesc "C<guestfs_" "C<g." in
7783 match fst style with
7784 | RErr | RInt _ | RInt64 _ | RBool _
7785 | RConstOptString _ | RConstString _
7786 | RString _ | RBufferOut _ -> doc
7788 doc ^ "\n\nThis function returns a list of strings."
7789 | RStruct (_, typ) ->
7790 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7791 | RStructList (_, typ) ->
7792 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
7794 doc ^ "\n\nThis function returns a dictionary." in
7796 if List.mem ProtocolLimitWarning flags then
7797 doc ^ "\n\n" ^ protocol_limit_warning
7800 if List.mem DangerWillRobinson flags then
7801 doc ^ "\n\n" ^ danger_will_robinson
7804 match deprecation_notice flags with
7806 | Some txt -> doc ^ "\n\n" ^ txt in
7807 let doc = pod2text ~width:60 name doc in
7808 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
7809 let doc = String.concat "\n " doc in
7810 pr " u\"\"\"%s\"\"\"\n" doc;
7812 pr " return libguestfsmod.%s " name;
7813 generate_py_call_args ~handle:"self._o" (snd style);
7818 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
7819 and generate_py_call_args ~handle args =
7821 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
7824 (* Useful if you need the longdesc POD text as plain text. Returns a
7827 * Because this is very slow (the slowest part of autogeneration),
7828 * we memoize the results.
7830 and pod2text ~width name longdesc =
7831 let key = width, name, longdesc in
7832 try Hashtbl.find pod2text_memo key
7834 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
7835 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
7837 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
7838 let chan = Unix.open_process_in cmd in
7839 let lines = ref [] in
7841 let line = input_line chan in
7842 if i = 1 then (* discard the first line of output *)
7845 let line = triml line in
7846 lines := line :: !lines;
7849 let lines = try loop 1 with End_of_file -> List.rev !lines in
7850 Unix.unlink filename;
7851 (match Unix.close_process_in chan with
7852 | Unix.WEXITED 0 -> ()
7854 failwithf "pod2text: process exited with non-zero status (%d)" i
7855 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
7856 failwithf "pod2text: process signalled or stopped by signal %d" i
7858 Hashtbl.add pod2text_memo key lines;
7859 let chan = open_out pod2text_memo_filename in
7860 output_value chan pod2text_memo;
7864 (* Generate ruby bindings. *)
7865 and generate_ruby_c () =
7866 generate_header CStyle LGPLv2;
7874 #include \"guestfs.h\"
7876 #include \"extconf.h\"
7878 /* For Ruby < 1.9 */
7880 #define RARRAY_LEN(r) (RARRAY((r))->len)
7883 static VALUE m_guestfs; /* guestfs module */
7884 static VALUE c_guestfs; /* guestfs_h handle */
7885 static VALUE e_Error; /* used for all errors */
7887 static void ruby_guestfs_free (void *p)
7890 guestfs_close ((guestfs_h *) p);
7893 static VALUE ruby_guestfs_create (VALUE m)
7897 g = guestfs_create ();
7899 rb_raise (e_Error, \"failed to create guestfs handle\");
7901 /* Don't print error messages to stderr by default. */
7902 guestfs_set_error_handler (g, NULL, NULL);
7904 /* Wrap it, and make sure the close function is called when the
7907 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
7910 static VALUE ruby_guestfs_close (VALUE gv)
7913 Data_Get_Struct (gv, guestfs_h, g);
7915 ruby_guestfs_free (g);
7916 DATA_PTR (gv) = NULL;
7924 fun (name, style, _, _, _, _, _) ->
7925 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
7926 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
7929 pr " guestfs_h *g;\n";
7930 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
7932 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
7938 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7939 pr " Check_Type (%sv, T_STRING);\n" n;
7940 pr " const char *%s = StringValueCStr (%sv);\n" n n;
7942 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
7943 pr " \"%s\", \"%s\");\n" n name
7945 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
7947 pr " char **%s;\n" n;
7948 pr " Check_Type (%sv, T_ARRAY);\n" n;
7950 pr " int i, len;\n";
7951 pr " len = RARRAY_LEN (%sv);\n" n;
7952 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
7954 pr " for (i = 0; i < len; ++i) {\n";
7955 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
7956 pr " %s[i] = StringValueCStr (v);\n" n;
7958 pr " %s[len] = NULL;\n" n;
7961 pr " int %s = RTEST (%sv);\n" n n
7963 pr " int %s = NUM2INT (%sv);\n" n n
7968 match fst style with
7969 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7970 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7971 | RConstString _ | RConstOptString _ ->
7972 pr " const char *r;\n"; "NULL"
7973 | RString _ -> pr " char *r;\n"; "NULL"
7974 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7975 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7976 | RStructList (_, typ) ->
7977 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7980 pr " size_t size;\n";
7984 pr " r = guestfs_%s " name;
7985 generate_c_call_args ~handle:"g" style;
7990 | Pathname _ | Device _ | Dev_or_Path _ | String _
7991 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7993 pr " free (%s);\n" n
7996 pr " if (r == %s)\n" error_code;
7997 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8000 (match fst style with
8002 pr " return Qnil;\n"
8003 | RInt _ | RBool _ ->
8004 pr " return INT2NUM (r);\n"
8006 pr " return ULL2NUM (r);\n"
8008 pr " return rb_str_new2 (r);\n";
8009 | RConstOptString _ ->
8011 pr " return rb_str_new2 (r);\n";
8013 pr " return Qnil;\n";
8015 pr " VALUE rv = rb_str_new2 (r);\n";
8019 pr " int i, len = 0;\n";
8020 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
8021 pr " VALUE rv = rb_ary_new2 (len);\n";
8022 pr " for (i = 0; r[i] != NULL; ++i) {\n";
8023 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8024 pr " free (r[i]);\n";
8028 | RStruct (_, typ) ->
8029 let cols = cols_of_struct typ in
8030 generate_ruby_struct_code typ cols
8031 | RStructList (_, typ) ->
8032 let cols = cols_of_struct typ in
8033 generate_ruby_struct_list_code typ cols
8035 pr " VALUE rv = rb_hash_new ();\n";
8037 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
8038 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8039 pr " free (r[i]);\n";
8040 pr " free (r[i+1]);\n";
8045 pr " VALUE rv = rb_str_new (r, size);\n";
8055 /* Initialize the module. */
8056 void Init__guestfs ()
8058 m_guestfs = rb_define_module (\"Guestfs\");
8059 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8060 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8062 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8063 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8066 (* Define the rest of the methods. *)
8068 fun (name, style, _, _, _, _, _) ->
8069 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
8070 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8075 (* Ruby code to return a struct. *)
8076 and generate_ruby_struct_code typ cols =
8077 pr " VALUE rv = rb_hash_new ();\n";
8081 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8083 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8085 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8086 | name, (FBytes|FUInt64) ->
8087 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8089 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8091 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8093 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8094 | name, FOptPercent ->
8095 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8096 | name, FChar -> (* XXX wrong? *)
8097 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8099 pr " guestfs_free_%s (r);\n" typ;
8102 (* Ruby code to return a struct list. *)
8103 and generate_ruby_struct_list_code typ cols =
8104 pr " VALUE rv = rb_ary_new2 (r->len);\n";
8106 pr " for (i = 0; i < r->len; ++i) {\n";
8107 pr " VALUE hv = rb_hash_new ();\n";
8111 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8113 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
8115 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8116 | name, (FBytes|FUInt64) ->
8117 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8119 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8121 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8123 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8124 | name, FOptPercent ->
8125 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8126 | name, FChar -> (* XXX wrong? *)
8127 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8129 pr " rb_ary_push (rv, hv);\n";
8131 pr " guestfs_free_%s_list (r);\n" typ;
8134 (* Generate Java bindings GuestFS.java file. *)
8135 and generate_java_java () =
8136 generate_header CStyle LGPLv2;
8139 package com.redhat.et.libguestfs;
8141 import java.util.HashMap;
8142 import com.redhat.et.libguestfs.LibGuestFSException;
8143 import com.redhat.et.libguestfs.PV;
8144 import com.redhat.et.libguestfs.VG;
8145 import com.redhat.et.libguestfs.LV;
8146 import com.redhat.et.libguestfs.Stat;
8147 import com.redhat.et.libguestfs.StatVFS;
8148 import com.redhat.et.libguestfs.IntBool;
8149 import com.redhat.et.libguestfs.Dirent;
8152 * The GuestFS object is a libguestfs handle.
8156 public class GuestFS {
8157 // Load the native code.
8159 System.loadLibrary (\"guestfs_jni\");
8163 * The native guestfs_h pointer.
8168 * Create a libguestfs handle.
8170 * @throws LibGuestFSException
8172 public GuestFS () throws LibGuestFSException
8176 private native long _create () throws LibGuestFSException;
8179 * Close a libguestfs handle.
8181 * You can also leave handles to be collected by the garbage
8182 * collector, but this method ensures that the resources used
8183 * by the handle are freed up immediately. If you call any
8184 * other methods after closing the handle, you will get an
8187 * @throws LibGuestFSException
8189 public void close () throws LibGuestFSException
8195 private native void _close (long g) throws LibGuestFSException;
8197 public void finalize () throws LibGuestFSException
8205 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8206 if not (List.mem NotInDocs flags); then (
8207 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8209 if List.mem ProtocolLimitWarning flags then
8210 doc ^ "\n\n" ^ protocol_limit_warning
8213 if List.mem DangerWillRobinson flags then
8214 doc ^ "\n\n" ^ danger_will_robinson
8217 match deprecation_notice flags with
8219 | Some txt -> doc ^ "\n\n" ^ txt in
8220 let doc = pod2text ~width:60 name doc in
8221 let doc = List.map ( (* RHBZ#501883 *)
8224 | nonempty -> nonempty
8226 let doc = String.concat "\n * " doc in
8229 pr " * %s\n" shortdesc;
8232 pr " * @throws LibGuestFSException\n";
8236 generate_java_prototype ~public:true ~semicolon:false name style;
8239 pr " if (g == 0)\n";
8240 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8243 if fst style <> RErr then pr "return ";
8245 generate_java_call_args ~handle:"g" (snd style);
8249 generate_java_prototype ~privat:true ~native:true name style;
8256 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8257 and generate_java_call_args ~handle args =
8259 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8262 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8263 ?(semicolon=true) name style =
8264 if privat then pr "private ";
8265 if public then pr "public ";
8266 if native then pr "native ";
8269 (match fst style with
8270 | RErr -> pr "void ";
8271 | RInt _ -> pr "int ";
8272 | RInt64 _ -> pr "long ";
8273 | RBool _ -> pr "boolean ";
8274 | RConstString _ | RConstOptString _ | RString _
8275 | RBufferOut _ -> pr "String ";
8276 | RStringList _ -> pr "String[] ";
8277 | RStruct (_, typ) ->
8278 let name = java_name_of_struct typ in
8280 | RStructList (_, typ) ->
8281 let name = java_name_of_struct typ in
8283 | RHashtable _ -> pr "HashMap<String,String> ";
8286 if native then pr "_%s " name else pr "%s " name;
8288 let needs_comma = ref false in
8297 if !needs_comma then pr ", ";
8298 needs_comma := true;
8302 | Device n | Dev_or_Path n
8317 pr " throws LibGuestFSException";
8318 if semicolon then pr ";"
8320 and generate_java_struct jtyp cols =
8321 generate_header CStyle LGPLv2;
8324 package com.redhat.et.libguestfs;
8327 * Libguestfs %s structure.
8339 | name, FBuffer -> pr " public String %s;\n" name
8340 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8341 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8342 | name, FChar -> pr " public char %s;\n" name
8343 | name, FOptPercent ->
8344 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8345 pr " public float %s;\n" name
8350 and generate_java_c () =
8351 generate_header CStyle LGPLv2;
8358 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8359 #include \"guestfs.h\"
8361 /* Note that this function returns. The exception is not thrown
8362 * until after the wrapper function returns.
8365 throw_exception (JNIEnv *env, const char *msg)
8368 cl = (*env)->FindClass (env,
8369 \"com/redhat/et/libguestfs/LibGuestFSException\");
8370 (*env)->ThrowNew (env, cl, msg);
8373 JNIEXPORT jlong JNICALL
8374 Java_com_redhat_et_libguestfs_GuestFS__1create
8375 (JNIEnv *env, jobject obj)
8379 g = guestfs_create ();
8381 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8384 guestfs_set_error_handler (g, NULL, NULL);
8385 return (jlong) (long) g;
8388 JNIEXPORT void JNICALL
8389 Java_com_redhat_et_libguestfs_GuestFS__1close
8390 (JNIEnv *env, jobject obj, jlong jg)
8392 guestfs_h *g = (guestfs_h *) (long) jg;
8399 fun (name, style, _, _, _, _, _) ->
8401 (match fst style with
8402 | RErr -> pr "void ";
8403 | RInt _ -> pr "jint ";
8404 | RInt64 _ -> pr "jlong ";
8405 | RBool _ -> pr "jboolean ";
8406 | RConstString _ | RConstOptString _ | RString _
8407 | RBufferOut _ -> pr "jstring ";
8408 | RStruct _ | RHashtable _ ->
8410 | RStringList _ | RStructList _ ->
8414 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8415 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8417 pr " (JNIEnv *env, jobject obj, jlong jg";
8421 | Device n | Dev_or_Path n
8426 pr ", jstring j%s" n
8428 pr ", jobjectArray j%s" n
8430 pr ", jboolean j%s" n
8436 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8437 let error_code, no_ret =
8438 match fst style with
8439 | RErr -> pr " int r;\n"; "-1", ""
8441 | RInt _ -> pr " int r;\n"; "-1", "0"
8442 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8443 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8444 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8446 pr " jstring jr;\n";
8447 pr " char *r;\n"; "NULL", "NULL"
8449 pr " jobjectArray jr;\n";
8452 pr " jstring jstr;\n";
8453 pr " char **r;\n"; "NULL", "NULL"
8454 | RStruct (_, typ) ->
8455 pr " jobject jr;\n";
8457 pr " jfieldID fl;\n";
8458 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8459 | RStructList (_, typ) ->
8460 pr " jobjectArray jr;\n";
8462 pr " jfieldID fl;\n";
8463 pr " jobject jfl;\n";
8464 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8465 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8467 pr " jstring jr;\n";
8469 pr " size_t size;\n";
8474 | Device n | Dev_or_Path n
8479 pr " const char *%s;\n" n
8481 pr " int %s_len;\n" n;
8482 pr " const char **%s;\n" n
8489 (match fst style with
8490 | RStringList _ | RStructList _ -> true
8491 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8493 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8494 List.exists (function StringList _ -> true | _ -> false) (snd style) in
8500 (* Get the parameters. *)
8504 | Device n | Dev_or_Path n
8508 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8510 (* This is completely undocumented, but Java null becomes
8513 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8515 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8516 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8517 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8518 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8520 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8522 pr " %s[%s_len] = NULL;\n" n n;
8525 pr " %s = j%s;\n" n n
8528 (* Make the call. *)
8529 pr " r = guestfs_%s " name;
8530 generate_c_call_args ~handle:"g" style;
8533 (* Release the parameters. *)
8537 | Device n | Dev_or_Path n
8541 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8544 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8546 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8547 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8549 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8551 pr " free (%s);\n" n
8556 (* Check for errors. *)
8557 pr " if (r == %s) {\n" error_code;
8558 pr " throw_exception (env, guestfs_last_error (g));\n";
8559 pr " return %s;\n" no_ret;
8563 (match fst style with
8565 | RInt _ -> pr " return (jint) r;\n"
8566 | RBool _ -> pr " return (jboolean) r;\n"
8567 | RInt64 _ -> pr " return (jlong) r;\n"
8568 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
8569 | RConstOptString _ ->
8570 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8572 pr " jr = (*env)->NewStringUTF (env, r);\n";
8576 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8577 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8578 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
8579 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8580 pr " for (i = 0; i < r_len; ++i) {\n";
8581 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
8582 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8583 pr " free (r[i]);\n";
8587 | RStruct (_, typ) ->
8588 let jtyp = java_name_of_struct typ in
8589 let cols = cols_of_struct typ in
8590 generate_java_struct_return typ jtyp cols
8591 | RStructList (_, typ) ->
8592 let jtyp = java_name_of_struct typ in
8593 let cols = cols_of_struct typ in
8594 generate_java_struct_list_return typ jtyp cols
8597 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8598 pr " return NULL;\n"
8600 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8609 and generate_java_struct_return typ jtyp cols =
8610 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8611 pr " jr = (*env)->AllocObject (env, cl);\n";
8615 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8616 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8619 pr " char s[33];\n";
8620 pr " memcpy (s, r->%s, 32);\n" name;
8622 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8623 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8627 pr " int len = r->%s_len;\n" name;
8628 pr " char s[len+1];\n";
8629 pr " memcpy (s, r->%s, len);\n" name;
8630 pr " s[len] = 0;\n";
8631 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8632 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8634 | name, (FBytes|FUInt64|FInt64) ->
8635 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8636 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8637 | name, (FUInt32|FInt32) ->
8638 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8639 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8640 | name, FOptPercent ->
8641 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8642 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8644 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8645 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8650 and generate_java_struct_list_return typ jtyp cols =
8651 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8652 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8653 pr " for (i = 0; i < r->len; ++i) {\n";
8654 pr " jfl = (*env)->AllocObject (env, cl);\n";
8658 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8659 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8662 pr " char s[33];\n";
8663 pr " memcpy (s, r->val[i].%s, 32);\n" name;
8665 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8666 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8670 pr " int len = r->val[i].%s_len;\n" name;
8671 pr " char s[len+1];\n";
8672 pr " memcpy (s, r->val[i].%s, len);\n" name;
8673 pr " s[len] = 0;\n";
8674 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8675 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8677 | name, (FBytes|FUInt64|FInt64) ->
8678 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8679 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8680 | name, (FUInt32|FInt32) ->
8681 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8682 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8683 | name, FOptPercent ->
8684 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8685 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8687 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8688 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8690 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8692 pr " guestfs_free_%s_list (r);\n" typ;
8695 and generate_java_makefile_inc () =
8696 generate_header HashStyle GPLv2;
8698 pr "java_built_sources = \\\n";
8701 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8703 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8705 and generate_haskell_hs () =
8706 generate_header HaskellStyle LGPLv2;
8708 (* XXX We only know how to generate partial FFI for Haskell
8709 * at the moment. Please help out!
8711 let can_generate style =
8715 | RInt64 _, _ -> true
8718 | RConstOptString _, _
8724 | RBufferOut _, _ -> false in
8727 {-# INCLUDE <guestfs.h> #-}
8728 {-# LANGUAGE ForeignFunctionInterface #-}
8733 (* List out the names of the actions we want to export. *)
8735 fun (name, style, _, _, _, _, _) ->
8736 if can_generate style then pr ",\n %s" name
8743 import Foreign.C.Types
8745 import Control.Exception
8746 import Data.Typeable
8748 data GuestfsS = GuestfsS -- represents the opaque C struct
8749 type GuestfsP = Ptr GuestfsS -- guestfs_h *
8750 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8752 -- XXX define properly later XXX
8756 data IntBool = IntBool
8758 data StatVFS = StatVFS
8759 data Hashtable = Hashtable
8761 foreign import ccall unsafe \"guestfs_create\" c_create
8763 foreign import ccall unsafe \"&guestfs_close\" c_close
8764 :: FunPtr (GuestfsP -> IO ())
8765 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8766 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8768 create :: IO GuestfsH
8771 c_set_error_handler p nullPtr nullPtr
8772 h <- newForeignPtr c_close p
8775 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8776 :: GuestfsP -> IO CString
8778 -- last_error :: GuestfsH -> IO (Maybe String)
8779 -- last_error h = do
8780 -- str <- withForeignPtr h (\\p -> c_last_error p)
8781 -- maybePeek peekCString str
8783 last_error :: GuestfsH -> IO (String)
8785 str <- withForeignPtr h (\\p -> c_last_error p)
8787 then return \"no error\"
8788 else peekCString str
8792 (* Generate wrappers for each foreign function. *)
8794 fun (name, style, _, _, _, _, _) ->
8795 if can_generate style then (
8796 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8798 generate_haskell_prototype ~handle:"GuestfsP" style;
8802 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
8804 pr "%s %s = do\n" name
8805 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
8807 (* Convert pointer arguments using with* functions. *)
8812 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
8813 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
8814 | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
8815 | Bool _ | Int _ -> ()
8817 (* Convert integer arguments. *)
8821 | Bool n -> sprintf "(fromBool %s)" n
8822 | Int n -> sprintf "(fromIntegral %s)" n
8823 | FileIn n | FileOut n
8824 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n -> n
8826 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
8827 (String.concat " " ("p" :: args));
8828 (match fst style with
8829 | RErr | RInt _ | RInt64 _ | RBool _ ->
8830 pr " if (r == -1)\n";
8832 pr " err <- last_error h\n";
8834 | RConstString _ | RConstOptString _ | RString _
8835 | RStringList _ | RStruct _
8836 | RStructList _ | RHashtable _ | RBufferOut _ ->
8837 pr " if (r == nullPtr)\n";
8839 pr " err <- last_error h\n";
8842 (match fst style with
8844 pr " else return ()\n"
8846 pr " else return (fromIntegral r)\n"
8848 pr " else return (fromIntegral r)\n"
8850 pr " else return (toBool r)\n"
8859 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
8865 and generate_haskell_prototype ~handle ?(hs = false) style =
8867 let string = if hs then "String" else "CString" in
8868 let int = if hs then "Int" else "CInt" in
8869 let bool = if hs then "Bool" else "CInt" in
8870 let int64 = if hs then "Integer" else "Int64" in
8874 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
8875 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
8876 | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
8877 | Bool _ -> pr "%s" bool
8878 | Int _ -> pr "%s" int
8879 | FileIn _ -> pr "%s" string
8880 | FileOut _ -> pr "%s" string
8885 (match fst style with
8886 | RErr -> if not hs then pr "CInt"
8887 | RInt _ -> pr "%s" int
8888 | RInt64 _ -> pr "%s" int64
8889 | RBool _ -> pr "%s" bool
8890 | RConstString _ -> pr "%s" string
8891 | RConstOptString _ -> pr "Maybe %s" string
8892 | RString _ -> pr "%s" string
8893 | RStringList _ -> pr "[%s]" string
8894 | RStruct (_, typ) ->
8895 let name = java_name_of_struct typ in
8897 | RStructList (_, typ) ->
8898 let name = java_name_of_struct typ in
8900 | RHashtable _ -> pr "Hashtable"
8901 | RBufferOut _ -> pr "%s" string
8905 and generate_bindtests () =
8906 generate_header CStyle LGPLv2;
8911 #include <inttypes.h>
8914 #include \"guestfs.h\"
8915 #include \"guestfs_protocol.h\"
8917 #define error guestfs_error
8918 #define safe_calloc guestfs_safe_calloc
8919 #define safe_malloc guestfs_safe_malloc
8922 print_strings (char * const* const argv)
8927 for (argc = 0; argv[argc] != NULL; ++argc) {
8928 if (argc > 0) printf (\", \");
8929 printf (\"\\\"%%s\\\"\", argv[argc]);
8934 /* The test0 function prints its parameters to stdout. */
8938 match test_functions with
8939 | [] -> assert false
8940 | test0 :: tests -> test0, tests in
8943 let (name, style, _, _, _, _, _) = test0 in
8944 generate_prototype ~extern:false ~semicolon:false ~newline:true
8945 ~handle:"g" ~prefix:"guestfs_" name style;
8950 | Device n | Dev_or_Path n
8953 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
8954 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
8955 | StringList n -> pr " print_strings (%s);\n" n
8956 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
8957 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
8959 pr " /* Java changes stdout line buffering so we need this: */\n";
8960 pr " fflush (stdout);\n";
8966 fun (name, style, _, _, _, _, _) ->
8967 if String.sub name (String.length name - 3) 3 <> "err" then (
8968 pr "/* Test normal return. */\n";
8969 generate_prototype ~extern:false ~semicolon:false ~newline:true
8970 ~handle:"g" ~prefix:"guestfs_" name style;
8972 (match fst style with
8977 pr " sscanf (val, \"%%d\", &r);\n";
8981 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
8984 pr " return strcmp (val, \"true\") == 0;\n"
8986 | RConstOptString _ ->
8987 (* Can't return the input string here. Return a static
8988 * string so we ensure we get a segfault if the caller
8991 pr " return \"static string\";\n"
8993 pr " return strdup (val);\n"
8995 pr " char **strs;\n";
8997 pr " sscanf (val, \"%%d\", &n);\n";
8998 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
8999 pr " for (i = 0; i < n; ++i) {\n";
9000 pr " strs[i] = safe_malloc (g, 16);\n";
9001 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
9003 pr " strs[n] = NULL;\n";
9004 pr " return strs;\n"
9005 | RStruct (_, typ) ->
9006 pr " struct guestfs_%s *r;\n" typ;
9007 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9009 | RStructList (_, typ) ->
9010 pr " struct guestfs_%s_list *r;\n" typ;
9011 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9012 pr " sscanf (val, \"%%d\", &r->len);\n";
9013 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9016 pr " char **strs;\n";
9018 pr " sscanf (val, \"%%d\", &n);\n";
9019 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9020 pr " for (i = 0; i < n; ++i) {\n";
9021 pr " strs[i*2] = safe_malloc (g, 16);\n";
9022 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
9023 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
9024 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9026 pr " strs[n*2] = NULL;\n";
9027 pr " return strs;\n"
9029 pr " return strdup (val);\n"
9034 pr "/* Test error return. */\n";
9035 generate_prototype ~extern:false ~semicolon:false ~newline:true
9036 ~handle:"g" ~prefix:"guestfs_" name style;
9038 pr " error (g, \"error\");\n";
9039 (match fst style with
9040 | RErr | RInt _ | RInt64 _ | RBool _ ->
9042 | RConstString _ | RConstOptString _
9043 | RString _ | RStringList _ | RStruct _
9047 pr " return NULL;\n"
9054 and generate_ocaml_bindtests () =
9055 generate_header OCamlStyle GPLv2;
9059 let g = Guestfs.create () in
9066 | CallString s -> "\"" ^ s ^ "\""
9067 | CallOptString None -> "None"
9068 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9069 | CallStringList xs ->
9070 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9071 | CallInt i when i >= 0 -> string_of_int i
9072 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9073 | CallBool b -> string_of_bool b
9078 generate_lang_bindtests (
9079 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
9082 pr "print_endline \"EOF\"\n"
9084 and generate_perl_bindtests () =
9085 pr "#!/usr/bin/perl -w\n";
9086 generate_header HashStyle GPLv2;
9093 my $g = Sys::Guestfs->new ();
9097 String.concat ", " (
9100 | CallString s -> "\"" ^ s ^ "\""
9101 | CallOptString None -> "undef"
9102 | CallOptString (Some s) -> sprintf "\"%s\"" s
9103 | CallStringList xs ->
9104 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9105 | CallInt i -> string_of_int i
9106 | CallBool b -> if b then "1" else "0"
9111 generate_lang_bindtests (
9112 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9115 pr "print \"EOF\\n\"\n"
9117 and generate_python_bindtests () =
9118 generate_header HashStyle GPLv2;
9123 g = guestfs.GuestFS ()
9127 String.concat ", " (
9130 | CallString s -> "\"" ^ s ^ "\""
9131 | CallOptString None -> "None"
9132 | CallOptString (Some s) -> sprintf "\"%s\"" s
9133 | CallStringList xs ->
9134 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9135 | CallInt i -> string_of_int i
9136 | CallBool b -> if b then "1" else "0"
9141 generate_lang_bindtests (
9142 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9145 pr "print \"EOF\"\n"
9147 and generate_ruby_bindtests () =
9148 generate_header HashStyle GPLv2;
9153 g = Guestfs::create()
9157 String.concat ", " (
9160 | CallString s -> "\"" ^ s ^ "\""
9161 | CallOptString None -> "nil"
9162 | CallOptString (Some s) -> sprintf "\"%s\"" s
9163 | CallStringList xs ->
9164 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9165 | CallInt i -> string_of_int i
9166 | CallBool b -> string_of_bool b
9171 generate_lang_bindtests (
9172 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9175 pr "print \"EOF\\n\"\n"
9177 and generate_java_bindtests () =
9178 generate_header CStyle GPLv2;
9181 import com.redhat.et.libguestfs.*;
9183 public class Bindtests {
9184 public static void main (String[] argv)
9187 GuestFS g = new GuestFS ();
9191 String.concat ", " (
9194 | CallString s -> "\"" ^ s ^ "\""
9195 | CallOptString None -> "null"
9196 | CallOptString (Some s) -> sprintf "\"%s\"" s
9197 | CallStringList xs ->
9199 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9200 | CallInt i -> string_of_int i
9201 | CallBool b -> string_of_bool b
9206 generate_lang_bindtests (
9207 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9211 System.out.println (\"EOF\");
9213 catch (Exception exn) {
9214 System.err.println (exn);
9221 and generate_haskell_bindtests () =
9222 generate_header HaskellStyle GPLv2;
9225 module Bindtests where
9226 import qualified Guestfs
9236 | CallString s -> "\"" ^ s ^ "\""
9237 | CallOptString None -> "Nothing"
9238 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9239 | CallStringList xs ->
9240 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9241 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9242 | CallInt i -> string_of_int i
9243 | CallBool true -> "True"
9244 | CallBool false -> "False"
9249 generate_lang_bindtests (
9250 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9253 pr " putStrLn \"EOF\"\n"
9255 (* Language-independent bindings tests - we do it this way to
9256 * ensure there is parity in testing bindings across all languages.
9258 and generate_lang_bindtests call =
9259 call "test0" [CallString "abc"; CallOptString (Some "def");
9260 CallStringList []; CallBool false;
9261 CallInt 0; CallString "123"; CallString "456"];
9262 call "test0" [CallString "abc"; CallOptString None;
9263 CallStringList []; CallBool false;
9264 CallInt 0; CallString "123"; CallString "456"];
9265 call "test0" [CallString ""; CallOptString (Some "def");
9266 CallStringList []; CallBool false;
9267 CallInt 0; CallString "123"; CallString "456"];
9268 call "test0" [CallString ""; CallOptString (Some "");
9269 CallStringList []; CallBool false;
9270 CallInt 0; CallString "123"; CallString "456"];
9271 call "test0" [CallString "abc"; CallOptString (Some "def");
9272 CallStringList ["1"]; CallBool false;
9273 CallInt 0; CallString "123"; CallString "456"];
9274 call "test0" [CallString "abc"; CallOptString (Some "def");
9275 CallStringList ["1"; "2"]; CallBool false;
9276 CallInt 0; CallString "123"; CallString "456"];
9277 call "test0" [CallString "abc"; CallOptString (Some "def");
9278 CallStringList ["1"]; CallBool true;
9279 CallInt 0; CallString "123"; CallString "456"];
9280 call "test0" [CallString "abc"; CallOptString (Some "def");
9281 CallStringList ["1"]; CallBool false;
9282 CallInt (-1); CallString "123"; CallString "456"];
9283 call "test0" [CallString "abc"; CallOptString (Some "def");
9284 CallStringList ["1"]; CallBool false;
9285 CallInt (-2); CallString "123"; CallString "456"];
9286 call "test0" [CallString "abc"; CallOptString (Some "def");
9287 CallStringList ["1"]; CallBool false;
9288 CallInt 1; CallString "123"; CallString "456"];
9289 call "test0" [CallString "abc"; CallOptString (Some "def");
9290 CallStringList ["1"]; CallBool false;
9291 CallInt 2; CallString "123"; CallString "456"];
9292 call "test0" [CallString "abc"; CallOptString (Some "def");
9293 CallStringList ["1"]; CallBool false;
9294 CallInt 4095; CallString "123"; CallString "456"];
9295 call "test0" [CallString "abc"; CallOptString (Some "def");
9296 CallStringList ["1"]; CallBool false;
9297 CallInt 0; CallString ""; CallString ""]
9299 (* XXX Add here tests of the return and error functions. *)
9301 (* This is used to generate the src/MAX_PROC_NR file which
9302 * contains the maximum procedure number, a surrogate for the
9303 * ABI version number. See src/Makefile.am for the details.
9305 and generate_max_proc_nr () =
9306 let proc_nrs = List.map (
9307 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9308 ) daemon_functions in
9310 let max_proc_nr = List.fold_left max 0 proc_nrs in
9312 pr "%d\n" max_proc_nr
9314 let output_to filename =
9315 let filename_new = filename ^ ".new" in
9316 chan := open_out filename_new;
9321 (* Is the new file different from the current file? *)
9322 if Sys.file_exists filename && files_equal filename filename_new then
9323 Unix.unlink filename_new (* same, so skip it *)
9325 (* different, overwrite old one *)
9326 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9327 Unix.rename filename_new filename;
9328 Unix.chmod filename 0o444;
9329 printf "written %s\n%!" filename;
9338 if not (Sys.file_exists "HACKING") then (
9340 You are probably running this from the wrong directory.
9341 Run it from the top source directory using the command
9347 let close = output_to "src/guestfs_protocol.x" in
9351 let close = output_to "src/guestfs-structs.h" in
9352 generate_structs_h ();
9355 let close = output_to "src/guestfs-actions.h" in
9356 generate_actions_h ();
9359 let close = output_to "src/guestfs-actions.c" in
9360 generate_client_actions ();
9363 let close = output_to "daemon/actions.h" in
9364 generate_daemon_actions_h ();
9367 let close = output_to "daemon/stubs.c" in
9368 generate_daemon_actions ();
9371 let close = output_to "daemon/names.c" in
9372 generate_daemon_names ();
9375 let close = output_to "capitests/tests.c" in
9379 let close = output_to "src/guestfs-bindtests.c" in
9380 generate_bindtests ();
9383 let close = output_to "fish/cmds.c" in
9384 generate_fish_cmds ();
9387 let close = output_to "fish/completion.c" in
9388 generate_fish_completion ();
9391 let close = output_to "guestfs-structs.pod" in
9392 generate_structs_pod ();
9395 let close = output_to "guestfs-actions.pod" in
9396 generate_actions_pod ();
9399 let close = output_to "guestfish-actions.pod" in
9400 generate_fish_actions_pod ();
9403 let close = output_to "ocaml/guestfs.mli" in
9404 generate_ocaml_mli ();
9407 let close = output_to "ocaml/guestfs.ml" in
9408 generate_ocaml_ml ();
9411 let close = output_to "ocaml/guestfs_c_actions.c" in
9412 generate_ocaml_c ();
9415 let close = output_to "ocaml/bindtests.ml" in
9416 generate_ocaml_bindtests ();
9419 let close = output_to "perl/Guestfs.xs" in
9420 generate_perl_xs ();
9423 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9424 generate_perl_pm ();
9427 let close = output_to "perl/bindtests.pl" in
9428 generate_perl_bindtests ();
9431 let close = output_to "python/guestfs-py.c" in
9432 generate_python_c ();
9435 let close = output_to "python/guestfs.py" in
9436 generate_python_py ();
9439 let close = output_to "python/bindtests.py" in
9440 generate_python_bindtests ();
9443 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9447 let close = output_to "ruby/bindtests.rb" in
9448 generate_ruby_bindtests ();
9451 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9452 generate_java_java ();
9457 let cols = cols_of_struct typ in
9458 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9459 let close = output_to filename in
9460 generate_java_struct jtyp cols;
9464 let close = output_to "java/Makefile.inc" in
9465 generate_java_makefile_inc ();
9468 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9472 let close = output_to "java/Bindtests.java" in
9473 generate_java_bindtests ();
9476 let close = output_to "haskell/Guestfs.hs" in
9477 generate_haskell_hs ();
9480 let close = output_to "haskell/Bindtests.hs" in
9481 generate_haskell_bindtests ();
9484 let close = output_to "src/MAX_PROC_NR" in
9485 generate_max_proc_nr ();
9488 (* Always generate this file last, and unconditionally. It's used
9489 * by the Makefile to know when we must re-run the generator.
9491 let chan = open_out "src/stamp-generator" in