3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <const char *, size_t> pair.
169 * Most other languages have a string type which can contain
170 * ASCII NUL. We use whatever type is appropriate for each
172 * Buffers are limited by the total message size. To transfer
173 * large blocks of data, use FileIn/FileOut parameters instead.
174 * To return an arbitrary buffer, use RBufferOut.
179 | ProtocolLimitWarning (* display warning about protocol size limits *)
180 | DangerWillRobinson (* flags particularly dangerous commands *)
181 | FishAlias of string (* provide an alias for this cmd in guestfish *)
182 | FishOutput of fish_output_t (* how to display output in guestfish *)
183 | NotInFish (* do not export via guestfish *)
184 | NotInDocs (* do not add this function to documentation *)
185 | DeprecatedBy of string (* function is deprecated, use .. instead *)
186 | Optional of string (* function is part of an optional group *)
189 | FishOutputOctal (* for int return, print in octal *)
190 | FishOutputHexadecimal (* for int return, print in hex *)
192 (* You can supply zero or as many tests as you want per API call.
194 * Note that the test environment has 3 block devices, of size 500MB,
195 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196 * a fourth ISO block device with some known files on it (/dev/sdd).
198 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199 * Number of cylinders was 63 for IDE emulated disks with precisely
200 * the same size. How exactly this is calculated is a mystery.
202 * The ISO block device (/dev/sdd) comes from images/test.iso.
204 * To be able to run the tests in a reasonable amount of time,
205 * the virtual machine and block devices are reused between tests.
206 * So don't try testing kill_subprocess :-x
208 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
210 * Don't assume anything about the previous contents of the block
211 * devices. Use 'Init*' to create some initial scenarios.
213 * You can add a prerequisite clause to any individual test. This
214 * is a run-time check, which, if it fails, causes the test to be
215 * skipped. Useful if testing a command which might not work on
216 * all variations of libguestfs builds. A test that has prerequisite
217 * of 'Always' is run unconditionally.
219 * In addition, packagers can skip individual tests by setting the
220 * environment variables: eg:
221 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
222 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
224 type tests = (test_init * test_prereq * test) list
226 (* Run the command sequence and just expect nothing to fail. *)
229 (* Run the command sequence and expect the output of the final
230 * command to be the string.
232 | TestOutput of seq * string
234 (* Run the command sequence and expect the output of the final
235 * command to be the list of strings.
237 | TestOutputList of seq * string list
239 (* Run the command sequence and expect the output of the final
240 * command to be the list of block devices (could be either
241 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242 * character of each string).
244 | TestOutputListOfDevices of seq * string list
246 (* Run the command sequence and expect the output of the final
247 * command to be the integer.
249 | TestOutputInt of seq * int
251 (* Run the command sequence and expect the output of the final
252 * command to be <op> <int>, eg. ">=", "1".
254 | TestOutputIntOp of seq * string * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a true value (!= 0 or != NULL).
259 | TestOutputTrue of seq
261 (* Run the command sequence and expect the output of the final
262 * command to be a false value (== 0 or == NULL, but not an error).
264 | TestOutputFalse of seq
266 (* Run the command sequence and expect the output of the final
267 * command to be a list of the given length (but don't care about
270 | TestOutputLength of seq * int
272 (* Run the command sequence and expect the output of the final
273 * command to be a buffer (RBufferOut), ie. string + size.
275 | TestOutputBuffer of seq * string
277 (* Run the command sequence and expect the output of the final
278 * command to be a structure.
280 | TestOutputStruct of seq * test_field_compare list
282 (* Run the command sequence and expect the final command (only)
285 | TestLastFail of seq
287 and test_field_compare =
288 | CompareWithInt of string * int
289 | CompareWithIntOp of string * string * int
290 | CompareWithString of string * string
291 | CompareFieldsIntEq of string * string
292 | CompareFieldsStrEq of string * string
294 (* Test prerequisites. *)
296 (* Test always runs. *)
299 (* Test is currently disabled - eg. it fails, or it tests some
300 * unimplemented feature.
304 (* 'string' is some C code (a function body) that should return
305 * true or false. The test will run if the code returns true.
309 (* As for 'If' but the test runs _unless_ the code returns true. *)
312 (* Run the test only if 'string' is available in the daemon. *)
313 | IfAvailable of string
315 (* Some initial scenarios for testing. *)
317 (* Do nothing, block devices could contain random stuff including
318 * LVM PVs, and some filesystems might be mounted. This is usually
323 (* Block devices are empty and no filesystems are mounted. *)
326 (* /dev/sda contains a single partition /dev/sda1, with random
327 * content. /dev/sdb and /dev/sdc may have random content.
332 (* /dev/sda contains a single partition /dev/sda1, which is formatted
333 * as ext2, empty [except for lost+found] and mounted on /.
334 * /dev/sdb and /dev/sdc may have random content.
340 * /dev/sda1 (is a PV):
341 * /dev/VG/LV (size 8MB):
342 * formatted as ext2, empty [except for lost+found], mounted on /
343 * /dev/sdb and /dev/sdc may have random content.
347 (* /dev/sdd (the ISO, see images/ directory in source)
352 (* Sequence of commands for testing. *)
354 and cmd = string list
356 (* Note about long descriptions: When referring to another
357 * action, use the format C<guestfs_other> (ie. the full name of
358 * the C function). This will be replaced as appropriate in other
361 * Apart from that, long descriptions are just perldoc paragraphs.
364 (* Generate a random UUID (used in tests). *)
366 let chan = open_process_in "uuidgen" in
367 let uuid = input_line chan in
368 (match close_process_in chan with
371 failwith "uuidgen: process exited with non-zero status"
372 | WSIGNALED _ | WSTOPPED _ ->
373 failwith "uuidgen: process signalled or stopped by signal"
377 (* These test functions are used in the language binding tests. *)
379 let test_all_args = [
382 StringList "strlist";
391 let test_all_rets = [
392 (* except for RErr, which is tested thoroughly elsewhere *)
393 "test0rint", RInt "valout";
394 "test0rint64", RInt64 "valout";
395 "test0rbool", RBool "valout";
396 "test0rconststring", RConstString "valout";
397 "test0rconstoptstring", RConstOptString "valout";
398 "test0rstring", RString "valout";
399 "test0rstringlist", RStringList "valout";
400 "test0rstruct", RStruct ("valout", "lvm_pv");
401 "test0rstructlist", RStructList ("valout", "lvm_pv");
402 "test0rhashtable", RHashtable "valout";
405 let test_functions = [
406 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
408 "internal test function - do not use",
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
414 It echos the contents of each parameter to stdout.
416 You probably don't want to call this function.");
420 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
422 "internal test function - do not use",
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
428 It converts string C<val> to the return type.
430 You probably don't want to call this function.");
431 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
433 "internal test function - do not use",
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
439 This function always returns an error.
441 You probably don't want to call this function.")]
445 (* non_daemon_functions are any functions which don't get processed
446 * in the daemon, eg. functions for setting and getting local
447 * configuration values.
450 let non_daemon_functions = test_functions @ [
451 ("launch", (RErr, []), -1, [FishAlias "run"],
453 "launch the qemu subprocess",
455 Internally libguestfs is implemented by running a virtual machine
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
461 ("wait_ready", (RErr, []), -1, [NotInFish],
463 "wait until the qemu subprocess launches (no op)",
465 This function is a no op.
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete. However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
476 ("kill_subprocess", (RErr, []), -1, [],
478 "kill the qemu subprocess",
480 This kills the qemu subprocess. You should never need to call this.");
482 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
484 "add an image to examine or modify",
486 This function adds a virtual machine disk image C<filename> to the
487 guest. The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
491 You don't necessarily need to be root when using libguestfs. However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>. In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
508 Note that this call checks for the existence of C<filename>. This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
511 the general C<guestfs_config> call instead.");
513 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
515 "add a CD-ROM disk image to examine",
517 This function adds a virtual CD-ROM disk image to the guest.
519 This is equivalent to the qemu parameter C<-cdrom filename>.
527 This call checks for the existence of C<filename>. This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
530 the general C<guestfs_config> call instead.
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
540 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
542 "add a drive in snapshot mode (read-only)",
544 This adds a drive in snapshot mode, making it effectively
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed. We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,if=...>.
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>. In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
561 Note that this call checks for the existence of C<filename>. This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
564 the general C<guestfs_config> call instead.");
566 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568 "add qemu parameters",
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>. Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
575 The first character of C<param> string must be a C<-> (dash).
577 C<value> can be NULL.");
579 ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
581 "set the qemu binary",
583 Set the qemu binary that we will use.
585 The default is chosen when the library was compiled by the
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
593 Note that you should call this function as early as possible
594 after creating the handle. This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results. Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
601 ("get_qemu", (RConstString "qemu", []), -1, [],
602 [InitNone, Always, TestRun (
604 "get the qemu binary",
606 Return the current qemu binary.
608 This is always non-NULL. If it wasn't set already, then this will
609 return the default qemu binary name.");
611 ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
613 "set the search path",
615 Set the path that libguestfs searches for kernel and initrd.img.
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
620 Setting C<path> to C<NULL> restores the default path.");
622 ("get_path", (RConstString "path", []), -1, [],
623 [InitNone, Always, TestRun (
625 "get the search path",
627 Return the current search path.
629 This is always non-NULL. If it wasn't set already, then this will
630 return the default path.");
632 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634 "add options to kernel command line",
636 This function is used to add additional options to the
637 guest kernel command line.
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
645 ("get_append", (RConstOptString "append", []), -1, [],
646 (* This cannot be tested with the current framework. The
647 * function can return NULL in normal operations, which the
648 * test framework interprets as an error.
651 "get the additional kernel options",
653 Return the additional kernel options which are added to the
654 guest kernel command line.
656 If C<NULL> then no options are added.");
658 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
662 If C<autosync> is true, this enables autosync. Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
670 ("get_autosync", (RBool "autosync", []), -1, [],
671 [InitNone, Always, TestRun (
672 [["get_autosync"]])],
675 Get the autosync flag.");
677 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686 ("get_verbose", (RBool "verbose", []), -1, [],
690 This returns the verbose messages flag.");
692 ("is_ready", (RBool "ready", []), -1, [],
693 [InitNone, Always, TestOutputTrue (
695 "is ready to accept commands",
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
700 For more information on states, see L<guestfs(3)>.");
702 ("is_config", (RBool "config", []), -1, [],
703 [InitNone, Always, TestOutputFalse (
705 "is in configuration state",
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
710 For more information on states, see L<guestfs(3)>.");
712 ("is_launching", (RBool "launching", []), -1, [],
713 [InitNone, Always, TestOutputFalse (
714 [["is_launching"]])],
715 "is launching subprocess",
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
720 For more information on states, see L<guestfs(3)>.");
722 ("is_busy", (RBool "busy", []), -1, [],
723 [InitNone, Always, TestOutputFalse (
725 "is busy processing a command",
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
730 For more information on states, see L<guestfs(3)>.");
732 ("get_state", (RInt "state", []), -1, [],
734 "get the current state",
736 This returns the current state as an opaque integer. This is
737 only useful for printing debug and internal error messages.
739 For more information on states, see L<guestfs(3)>.");
741 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742 [InitNone, Always, TestOutputInt (
743 [["set_memsize"; "500"];
744 ["get_memsize"]], 500)],
745 "set memory allocated to the qemu subprocess",
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess. This only has any effect if called before
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
758 ("get_memsize", (RInt "memsize", []), -1, [],
759 [InitNone, Always, TestOutputIntOp (
760 [["get_memsize"]], ">=", 256)],
761 "get memory allocated to the qemu subprocess",
763 This gets the memory size in megabytes allocated to the
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
773 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774 [InitNone, Always, TestOutputIntOp (
775 [["get_pid"]], ">=", 1)],
776 "get PID of qemu subprocess",
778 Return the process ID of the qemu subprocess. If there is no
779 qemu subprocess, then this will return an error.
781 This is an internal call used for debugging and testing.");
783 ("version", (RStruct ("version", "version"), []), -1, [],
784 [InitNone, Always, TestOutputStruct (
785 [["version"]], [CompareWithInt ("major", 1)])],
786 "get the library version number",
788 Return the libguestfs version number that the program is linked
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against. You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
796 This call was added in version C<1.0.58>. In previous
797 versions of libguestfs there was no way to get the version
798 number. From C code you can use dynamic linker functions
799 to find out if this symbol exists (if it doesn't, then
800 it's an earlier version).
802 The call returns a structure with four elements. The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet. The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
811 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
813 I<Note:> Don't use this call to test for availability
814 of features. In enterprise distributions we backport
815 features from later versions into earlier versions,
816 making this an unreliable way to test for features.
817 Use C<guestfs_available> instead.");
819 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
820 [InitNone, Always, TestOutputTrue (
821 [["set_selinux"; "true"];
823 "set SELinux enabled or disabled at appliance boot",
825 This sets the selinux flag that is passed to the appliance
826 at boot time. The default is C<selinux=0> (disabled).
828 Note that if SELinux is enabled, it is always in
829 Permissive mode (C<enforcing=0>).
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
834 ("get_selinux", (RBool "selinux", []), -1, [],
836 "get SELinux enabled flag",
838 This returns the current setting of the selinux flag which
839 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
841 For more information on the architecture of libguestfs,
842 see L<guestfs(3)>.");
844 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
845 [InitNone, Always, TestOutputFalse (
846 [["set_trace"; "false"];
848 "enable or disable command traces",
850 If the command trace flag is set to 1, then commands are
851 printed on stdout before they are executed in a format
852 which is very similar to the one used by guestfish. In
853 other words, you can run a program with this enabled, and
854 you will get out a script which you can feed to guestfish
855 to perform the same set of actions.
857 If you want to trace C API calls into libguestfs (and
858 other libraries) then possibly a better way is to use
859 the external ltrace(1) command.
861 Command traces are disabled unless the environment variable
862 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
864 ("get_trace", (RBool "trace", []), -1, [],
866 "get command trace enabled flag",
868 Return the command trace flag.");
870 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
871 [InitNone, Always, TestOutputFalse (
872 [["set_direct"; "false"];
874 "enable or disable direct appliance mode",
876 If the direct appliance mode flag is enabled, then stdin and
877 stdout are passed directly through to the appliance once it
880 One consequence of this is that log messages aren't caught
881 by the library and handled by C<guestfs_set_log_message_callback>,
882 but go straight to stdout.
884 You probably don't want to use this unless you know what you
887 The default is disabled.");
889 ("get_direct", (RBool "direct", []), -1, [],
891 "get direct appliance mode flag",
893 Return the direct appliance mode flag.");
895 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
896 [InitNone, Always, TestOutputTrue (
897 [["set_recovery_proc"; "true"];
898 ["get_recovery_proc"]])],
899 "enable or disable the recovery process",
901 If this is called with the parameter C<false> then
902 C<guestfs_launch> does not create a recovery process. The
903 purpose of the recovery process is to stop runaway qemu
904 processes in the case where the main program aborts abruptly.
906 This only has any effect if called before C<guestfs_launch>,
907 and the default is true.
909 About the only time when you would want to disable this is
910 if the main process will fork itself into the background
911 (\"daemonize\" itself). In this case the recovery process
912 thinks that the main program has disappeared and so kills
913 qemu, which is not very helpful.");
915 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
917 "get recovery process enabled flag",
919 Return the recovery process enabled flag.");
921 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923 "add a drive specifying the QEMU block emulation to use",
925 This is the same as C<guestfs_add_drive> but it allows you
926 to specify the QEMU interface emulation to use at run time.");
928 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
930 "add a drive read-only specifying the QEMU block emulation to use",
932 This is the same as C<guestfs_add_drive_ro> but it allows you
933 to specify the QEMU interface emulation to use at run time.");
937 (* daemon_functions are any functions which cause some action
938 * to take place in the daemon.
941 let daemon_functions = [
942 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
943 [InitEmpty, Always, TestOutput (
944 [["part_disk"; "/dev/sda"; "mbr"];
945 ["mkfs"; "ext2"; "/dev/sda1"];
946 ["mount"; "/dev/sda1"; "/"];
947 ["write"; "/new"; "new file contents"];
948 ["cat"; "/new"]], "new file contents")],
949 "mount a guest disk at a position in the filesystem",
951 Mount a guest disk at a position in the filesystem. Block devices
952 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
953 the guest. If those block devices contain partitions, they will have
954 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
957 The rules are the same as for L<mount(2)>: A filesystem must
958 first be mounted on C</> before others can be mounted. Other
959 filesystems can only be mounted on directories which already
962 The mounted filesystem is writable, if we have sufficient permissions
963 on the underlying device.
966 When you use this call, the filesystem options C<sync> and C<noatime>
967 are set implicitly. This was originally done because we thought it
968 would improve reliability, but it turns out that I<-o sync> has a
969 very large negative performance impact and negligible effect on
970 reliability. Therefore we recommend that you avoid using
971 C<guestfs_mount> in any code that needs performance, and instead
972 use C<guestfs_mount_options> (use an empty string for the first
973 parameter if you don't want any options).");
975 ("sync", (RErr, []), 2, [],
976 [ InitEmpty, Always, TestRun [["sync"]]],
977 "sync disks, writes are flushed through to the disk image",
979 This syncs the disk, so that any writes are flushed through to the
980 underlying disk image.
982 You should always call this if you have modified a disk image, before
983 closing the handle.");
985 ("touch", (RErr, [Pathname "path"]), 3, [],
986 [InitBasicFS, Always, TestOutputTrue (
988 ["exists"; "/new"]])],
989 "update file timestamps or create a new file",
991 Touch acts like the L<touch(1)> command. It can be used to
992 update the timestamps on a file, or, if the file does not exist,
993 to create a new zero-length file.
995 This command only works on regular files, and will fail on other
996 file types such as directories, symbolic links, block special etc.");
998 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
999 [InitISOFS, Always, TestOutput (
1000 [["cat"; "/known-2"]], "abcdef\n")],
1001 "list the contents of a file",
1003 Return the contents of the file named C<path>.
1005 Note that this function cannot correctly handle binary files
1006 (specifically, files containing C<\\0> character which is treated
1007 as end of string). For those you need to use the C<guestfs_read_file>
1008 or C<guestfs_download> functions which have a more complex interface.");
1010 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1011 [], (* XXX Tricky to test because it depends on the exact format
1012 * of the 'ls -l' command, which changes between F10 and F11.
1014 "list the files in a directory (long format)",
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd) in the format of 'ls -la'.
1019 This command is mostly useful for interactive sessions. It
1020 is I<not> intended that you try to parse the output string.");
1022 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1023 [InitBasicFS, Always, TestOutputList (
1025 ["touch"; "/newer"];
1026 ["touch"; "/newest"];
1027 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1028 "list the files in a directory",
1030 List the files in C<directory> (relative to the root directory,
1031 there is no cwd). The '.' and '..' entries are not returned, but
1032 hidden files are shown.
1034 This command is mostly useful for interactive sessions. Programs
1035 should probably use C<guestfs_readdir> instead.");
1037 ("list_devices", (RStringList "devices", []), 7, [],
1038 [InitEmpty, Always, TestOutputListOfDevices (
1039 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1040 "list the block devices",
1042 List all the block devices.
1044 The full block device names are returned, eg. C</dev/sda>");
1046 ("list_partitions", (RStringList "partitions", []), 8, [],
1047 [InitBasicFS, Always, TestOutputListOfDevices (
1048 [["list_partitions"]], ["/dev/sda1"]);
1049 InitEmpty, Always, TestOutputListOfDevices (
1050 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1052 "list the partitions",
1054 List all the partitions detected on all block devices.
1056 The full partition device names are returned, eg. C</dev/sda1>
1058 This does not return logical volumes. For that you will need to
1059 call C<guestfs_lvs>.");
1061 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1062 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1063 [["pvs"]], ["/dev/sda1"]);
1064 InitEmpty, Always, TestOutputListOfDevices (
1065 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066 ["pvcreate"; "/dev/sda1"];
1067 ["pvcreate"; "/dev/sda2"];
1068 ["pvcreate"; "/dev/sda3"];
1069 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1070 "list the LVM physical volumes (PVs)",
1072 List all the physical volumes detected. This is the equivalent
1073 of the L<pvs(8)> command.
1075 This returns a list of just the device names that contain
1076 PVs (eg. C</dev/sda2>).
1078 See also C<guestfs_pvs_full>.");
1080 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1081 [InitBasicFSonLVM, Always, TestOutputList (
1083 InitEmpty, Always, TestOutputList (
1084 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1085 ["pvcreate"; "/dev/sda1"];
1086 ["pvcreate"; "/dev/sda2"];
1087 ["pvcreate"; "/dev/sda3"];
1088 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1089 ["vgcreate"; "VG2"; "/dev/sda3"];
1090 ["vgs"]], ["VG1"; "VG2"])],
1091 "list the LVM volume groups (VGs)",
1093 List all the volumes groups detected. This is the equivalent
1094 of the L<vgs(8)> command.
1096 This returns a list of just the volume group names that were
1097 detected (eg. C<VolGroup00>).
1099 See also C<guestfs_vgs_full>.");
1101 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1102 [InitBasicFSonLVM, Always, TestOutputList (
1103 [["lvs"]], ["/dev/VG/LV"]);
1104 InitEmpty, Always, TestOutputList (
1105 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1106 ["pvcreate"; "/dev/sda1"];
1107 ["pvcreate"; "/dev/sda2"];
1108 ["pvcreate"; "/dev/sda3"];
1109 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1110 ["vgcreate"; "VG2"; "/dev/sda3"];
1111 ["lvcreate"; "LV1"; "VG1"; "50"];
1112 ["lvcreate"; "LV2"; "VG1"; "50"];
1113 ["lvcreate"; "LV3"; "VG2"; "50"];
1114 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1115 "list the LVM logical volumes (LVs)",
1117 List all the logical volumes detected. This is the equivalent
1118 of the L<lvs(8)> command.
1120 This returns a list of the logical volume device names
1121 (eg. C</dev/VolGroup00/LogVol00>).
1123 See also C<guestfs_lvs_full>.");
1125 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM physical volumes (PVs)",
1129 List all the physical volumes detected. This is the equivalent
1130 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1132 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1133 [], (* XXX how to test? *)
1134 "list the LVM volume groups (VGs)",
1136 List all the volumes groups detected. This is the equivalent
1137 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1139 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1140 [], (* XXX how to test? *)
1141 "list the LVM logical volumes (LVs)",
1143 List all the logical volumes detected. This is the equivalent
1144 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1146 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1147 [InitISOFS, Always, TestOutputList (
1148 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1149 InitISOFS, Always, TestOutputList (
1150 [["read_lines"; "/empty"]], [])],
1151 "read file as lines",
1153 Return the contents of the file named C<path>.
1155 The file contents are returned as a list of lines. Trailing
1156 C<LF> and C<CRLF> character sequences are I<not> returned.
1158 Note that this function cannot correctly handle binary files
1159 (specifically, files containing C<\\0> character which is treated
1160 as end of line). For those you need to use the C<guestfs_read_file>
1161 function which has a more complex interface.");
1163 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1164 [], (* XXX Augeas code needs tests. *)
1165 "create a new Augeas handle",
1167 Create a new Augeas handle for editing configuration files.
1168 If there was any previous Augeas handle associated with this
1169 guestfs session, then it is closed.
1171 You must call this before using any other C<guestfs_aug_*>
1174 C<root> is the filesystem root. C<root> must not be NULL,
1177 The flags are the same as the flags defined in
1178 E<lt>augeas.hE<gt>, the logical I<or> of the following
1183 =item C<AUG_SAVE_BACKUP> = 1
1185 Keep the original file with a C<.augsave> extension.
1187 =item C<AUG_SAVE_NEWFILE> = 2
1189 Save changes into a file with extension C<.augnew>, and
1190 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1192 =item C<AUG_TYPE_CHECK> = 4
1194 Typecheck lenses (can be expensive).
1196 =item C<AUG_NO_STDINC> = 8
1198 Do not use standard load path for modules.
1200 =item C<AUG_SAVE_NOOP> = 16
1202 Make save a no-op, just record what would have been changed.
1204 =item C<AUG_NO_LOAD> = 32
1206 Do not load the tree in C<guestfs_aug_init>.
1210 To close the handle, you can call C<guestfs_aug_close>.
1212 To find out more about Augeas, see L<http://augeas.net/>.");
1214 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "close the current Augeas handle",
1218 Close the current Augeas handle and free up any resources
1219 used by it. After calling this, you have to call
1220 C<guestfs_aug_init> again before you can use any other
1221 Augeas functions.");
1223 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1224 [], (* XXX Augeas code needs tests. *)
1225 "define an Augeas variable",
1227 Defines an Augeas variable C<name> whose value is the result
1228 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1231 On success this returns the number of nodes in C<expr>, or
1232 C<0> if C<expr> evaluates to something which is not a nodeset.");
1234 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1235 [], (* XXX Augeas code needs tests. *)
1236 "define an Augeas node",
1238 Defines a variable C<name> whose value is the result of
1241 If C<expr> evaluates to an empty nodeset, a node is created,
1242 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1243 C<name> will be the nodeset containing that single node.
1245 On success this returns a pair containing the
1246 number of nodes in the nodeset, and a boolean flag
1247 if a node was created.");
1249 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1250 [], (* XXX Augeas code needs tests. *)
1251 "look up the value of an Augeas path",
1253 Look up the value associated with C<path>. If C<path>
1254 matches exactly one node, the C<value> is returned.");
1256 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1257 [], (* XXX Augeas code needs tests. *)
1258 "set Augeas path to value",
1260 Set the value associated with C<path> to C<val>.
1262 In the Augeas API, it is possible to clear a node by setting
1263 the value to NULL. Due to an oversight in the libguestfs API
1264 you cannot do that with this call. Instead you must use the
1265 C<guestfs_aug_clear> call.");
1267 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1268 [], (* XXX Augeas code needs tests. *)
1269 "insert a sibling Augeas node",
1271 Create a new sibling C<label> for C<path>, inserting it into
1272 the tree before or after C<path> (depending on the boolean
1275 C<path> must match exactly one existing node in the tree, and
1276 C<label> must be a label, ie. not contain C</>, C<*> or end
1277 with a bracketed index C<[N]>.");
1279 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1280 [], (* XXX Augeas code needs tests. *)
1281 "remove an Augeas path",
1283 Remove C<path> and all of its children.
1285 On success this returns the number of entries which were removed.");
1287 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1291 Move the node C<src> to C<dest>. C<src> must match exactly
1292 one node. C<dest> is overwritten if it exists.");
1294 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1295 [], (* XXX Augeas code needs tests. *)
1296 "return Augeas nodes which match augpath",
1298 Returns a list of paths which match the path expression C<path>.
1299 The returned paths are sufficiently qualified so that they match
1300 exactly one node in the current tree.");
1302 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1303 [], (* XXX Augeas code needs tests. *)
1304 "write all pending Augeas changes to disk",
1306 This writes all pending changes to disk.
1308 The flags which were passed to C<guestfs_aug_init> affect exactly
1309 how files are saved.");
1311 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1312 [], (* XXX Augeas code needs tests. *)
1313 "load files into the tree",
1315 Load files into the tree.
1317 See C<aug_load> in the Augeas documentation for the full gory
1320 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1321 [], (* XXX Augeas code needs tests. *)
1322 "list Augeas nodes under augpath",
1324 This is just a shortcut for listing C<guestfs_aug_match>
1325 C<path/*> and sorting the resulting nodes into alphabetical order.");
1327 ("rm", (RErr, [Pathname "path"]), 29, [],
1328 [InitBasicFS, Always, TestRun
1331 InitBasicFS, Always, TestLastFail
1333 InitBasicFS, Always, TestLastFail
1338 Remove the single file C<path>.");
1340 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1341 [InitBasicFS, Always, TestRun
1344 InitBasicFS, Always, TestLastFail
1345 [["rmdir"; "/new"]];
1346 InitBasicFS, Always, TestLastFail
1348 ["rmdir"; "/new"]]],
1349 "remove a directory",
1351 Remove the single directory C<path>.");
1353 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1354 [InitBasicFS, Always, TestOutputFalse
1356 ["mkdir"; "/new/foo"];
1357 ["touch"; "/new/foo/bar"];
1359 ["exists"; "/new"]]],
1360 "remove a file or directory recursively",
1362 Remove the file or directory C<path>, recursively removing the
1363 contents if its a directory. This is like the C<rm -rf> shell
1366 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1367 [InitBasicFS, Always, TestOutputTrue
1369 ["is_dir"; "/new"]];
1370 InitBasicFS, Always, TestLastFail
1371 [["mkdir"; "/new/foo/bar"]]],
1372 "create a directory",
1374 Create a directory named C<path>.");
1376 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1377 [InitBasicFS, Always, TestOutputTrue
1378 [["mkdir_p"; "/new/foo/bar"];
1379 ["is_dir"; "/new/foo/bar"]];
1380 InitBasicFS, Always, TestOutputTrue
1381 [["mkdir_p"; "/new/foo/bar"];
1382 ["is_dir"; "/new/foo"]];
1383 InitBasicFS, Always, TestOutputTrue
1384 [["mkdir_p"; "/new/foo/bar"];
1385 ["is_dir"; "/new"]];
1386 (* Regression tests for RHBZ#503133: *)
1387 InitBasicFS, Always, TestRun
1389 ["mkdir_p"; "/new"]];
1390 InitBasicFS, Always, TestLastFail
1392 ["mkdir_p"; "/new"]]],
1393 "create a directory and parents",
1395 Create a directory named C<path>, creating any parent directories
1396 as necessary. This is like the C<mkdir -p> shell command.");
1398 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1399 [], (* XXX Need stat command to test *)
1402 Change the mode (permissions) of C<path> to C<mode>. Only
1403 numeric modes are supported.
1405 I<Note>: When using this command from guestfish, C<mode>
1406 by default would be decimal, unless you prefix it with
1407 C<0> to get octal, ie. use C<0700> not C<700>.
1409 The mode actually set is affected by the umask.");
1411 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1412 [], (* XXX Need stat command to test *)
1413 "change file owner and group",
1415 Change the file owner to C<owner> and group to C<group>.
1417 Only numeric uid and gid are supported. If you want to use
1418 names, you will need to locate and parse the password file
1419 yourself (Augeas support makes this relatively easy).");
1421 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1422 [InitISOFS, Always, TestOutputTrue (
1423 [["exists"; "/empty"]]);
1424 InitISOFS, Always, TestOutputTrue (
1425 [["exists"; "/directory"]])],
1426 "test if file or directory exists",
1428 This returns C<true> if and only if there is a file, directory
1429 (or anything) with the given C<path> name.
1431 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1433 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1434 [InitISOFS, Always, TestOutputTrue (
1435 [["is_file"; "/known-1"]]);
1436 InitISOFS, Always, TestOutputFalse (
1437 [["is_file"; "/directory"]])],
1438 "test if file exists",
1440 This returns C<true> if and only if there is a file
1441 with the given C<path> name. Note that it returns false for
1442 other objects like directories.
1444 See also C<guestfs_stat>.");
1446 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1447 [InitISOFS, Always, TestOutputFalse (
1448 [["is_dir"; "/known-3"]]);
1449 InitISOFS, Always, TestOutputTrue (
1450 [["is_dir"; "/directory"]])],
1451 "test if file exists",
1453 This returns C<true> if and only if there is a directory
1454 with the given C<path> name. Note that it returns false for
1455 other objects like files.
1457 See also C<guestfs_stat>.");
1459 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1460 [InitEmpty, Always, TestOutputListOfDevices (
1461 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462 ["pvcreate"; "/dev/sda1"];
1463 ["pvcreate"; "/dev/sda2"];
1464 ["pvcreate"; "/dev/sda3"];
1465 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1466 "create an LVM physical volume",
1468 This creates an LVM physical volume on the named C<device>,
1469 where C<device> should usually be a partition name such
1472 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1473 [InitEmpty, Always, TestOutputList (
1474 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475 ["pvcreate"; "/dev/sda1"];
1476 ["pvcreate"; "/dev/sda2"];
1477 ["pvcreate"; "/dev/sda3"];
1478 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479 ["vgcreate"; "VG2"; "/dev/sda3"];
1480 ["vgs"]], ["VG1"; "VG2"])],
1481 "create an LVM volume group",
1483 This creates an LVM volume group called C<volgroup>
1484 from the non-empty list of physical volumes C<physvols>.");
1486 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1487 [InitEmpty, Always, TestOutputList (
1488 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1489 ["pvcreate"; "/dev/sda1"];
1490 ["pvcreate"; "/dev/sda2"];
1491 ["pvcreate"; "/dev/sda3"];
1492 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1493 ["vgcreate"; "VG2"; "/dev/sda3"];
1494 ["lvcreate"; "LV1"; "VG1"; "50"];
1495 ["lvcreate"; "LV2"; "VG1"; "50"];
1496 ["lvcreate"; "LV3"; "VG2"; "50"];
1497 ["lvcreate"; "LV4"; "VG2"; "50"];
1498 ["lvcreate"; "LV5"; "VG2"; "50"];
1500 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1501 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1502 "create an LVM logical volume",
1504 This creates an LVM logical volume called C<logvol>
1505 on the volume group C<volgroup>, with C<size> megabytes.");
1507 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1508 [InitEmpty, Always, TestOutput (
1509 [["part_disk"; "/dev/sda"; "mbr"];
1510 ["mkfs"; "ext2"; "/dev/sda1"];
1511 ["mount_options"; ""; "/dev/sda1"; "/"];
1512 ["write"; "/new"; "new file contents"];
1513 ["cat"; "/new"]], "new file contents")],
1514 "make a filesystem",
1516 This creates a filesystem on C<device> (usually a partition
1517 or LVM logical volume). The filesystem type is C<fstype>, for
1520 ("sfdisk", (RErr, [Device "device";
1521 Int "cyls"; Int "heads"; Int "sectors";
1522 StringList "lines"]), 43, [DangerWillRobinson],
1524 "create partitions on a block device",
1526 This is a direct interface to the L<sfdisk(8)> program for creating
1527 partitions on block devices.
1529 C<device> should be a block device, for example C</dev/sda>.
1531 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1532 and sectors on the device, which are passed directly to sfdisk as
1533 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1534 of these, then the corresponding parameter is omitted. Usually for
1535 'large' disks, you can just pass C<0> for these, but for small
1536 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1537 out the right geometry and you will need to tell it.
1539 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1540 information refer to the L<sfdisk(8)> manpage.
1542 To create a single partition occupying the whole disk, you would
1543 pass C<lines> as a single element list, when the single element being
1544 the string C<,> (comma).
1546 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1547 C<guestfs_part_init>");
1549 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1550 (* Regression test for RHBZ#597135. *)
1551 [InitBasicFS, Always, TestLastFail
1552 [["write_file"; "/new"; "abc"; "10000"]]],
1555 This call creates a file called C<path>. The contents of the
1556 file is the string C<content> (which can contain any 8 bit data),
1557 with length C<size>.
1559 As a special case, if C<size> is C<0>
1560 then the length is calculated using C<strlen> (so in this case
1561 the content cannot contain embedded ASCII NULs).
1563 I<NB.> Owing to a bug, writing content containing ASCII NUL
1564 characters does I<not> work, even if the length is specified.");
1566 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567 [InitEmpty, Always, TestOutputListOfDevices (
1568 [["part_disk"; "/dev/sda"; "mbr"];
1569 ["mkfs"; "ext2"; "/dev/sda1"];
1570 ["mount_options"; ""; "/dev/sda1"; "/"];
1571 ["mounts"]], ["/dev/sda1"]);
1572 InitEmpty, Always, TestOutputList (
1573 [["part_disk"; "/dev/sda"; "mbr"];
1574 ["mkfs"; "ext2"; "/dev/sda1"];
1575 ["mount_options"; ""; "/dev/sda1"; "/"];
1578 "unmount a filesystem",
1580 This unmounts the given filesystem. The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1584 ("mounts", (RStringList "devices", []), 46, [],
1585 [InitBasicFS, Always, TestOutputListOfDevices (
1586 [["mounts"]], ["/dev/sda1"])],
1587 "show mounted filesystems",
1589 This returns the list of currently mounted filesystems. It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592 Some internal mounts are not shown.
1594 See also: C<guestfs_mountpoints>");
1596 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597 [InitBasicFS, Always, TestOutputList (
1600 (* check that umount_all can unmount nested mounts correctly: *)
1601 InitEmpty, Always, TestOutputList (
1602 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603 ["mkfs"; "ext2"; "/dev/sda1"];
1604 ["mkfs"; "ext2"; "/dev/sda2"];
1605 ["mkfs"; "ext2"; "/dev/sda3"];
1606 ["mount_options"; ""; "/dev/sda1"; "/"];
1608 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609 ["mkdir"; "/mp1/mp2"];
1610 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611 ["mkdir"; "/mp1/mp2/mp3"];
1614 "unmount all filesystems",
1616 This unmounts all mounted filesystems.
1618 Some internal mounts are not unmounted by this call.");
1620 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622 "remove all LVM LVs, VGs and PVs",
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1627 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628 [InitISOFS, Always, TestOutput (
1629 [["file"; "/empty"]], "empty");
1630 InitISOFS, Always, TestOutput (
1631 [["file"; "/known-1"]], "ASCII text");
1632 InitISOFS, Always, TestLastFail (
1633 [["file"; "/notexists"]]);
1634 InitISOFS, Always, TestOutput (
1635 [["file"; "/abssymlink"]], "symbolic link");
1636 InitISOFS, Always, TestOutput (
1637 [["file"; "/directory"]], "directory")],
1638 "determine file type",
1640 This call uses the standard L<file(1)> command to determine
1641 the type or contents of the file.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zb path>. Note in
1647 particular that the filename is not prepended to the output
1650 This command can also be used on C</dev/> devices
1651 (and partitions, LV names). You can for example use this
1652 to determine if a device contains a filesystem, although
1653 it's usually better to use C<guestfs_vfs_type>.
1655 If the C<path> does not begin with C</dev/> then
1656 this command only works for the content of regular files.
1657 For other file types (directory, symbolic link etc) it
1658 will just return the string C<directory> etc.");
1660 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1661 [InitBasicFS, Always, TestOutput (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command"; "/test-command 1"]], "Result1");
1665 InitBasicFS, Always, TestOutput (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command"; "/test-command 2"]], "Result2\n");
1669 InitBasicFS, Always, TestOutput (
1670 [["upload"; "test-command"; "/test-command"];
1671 ["chmod"; "0o755"; "/test-command"];
1672 ["command"; "/test-command 3"]], "\nResult3");
1673 InitBasicFS, Always, TestOutput (
1674 [["upload"; "test-command"; "/test-command"];
1675 ["chmod"; "0o755"; "/test-command"];
1676 ["command"; "/test-command 4"]], "\nResult4\n");
1677 InitBasicFS, Always, TestOutput (
1678 [["upload"; "test-command"; "/test-command"];
1679 ["chmod"; "0o755"; "/test-command"];
1680 ["command"; "/test-command 5"]], "\nResult5\n\n");
1681 InitBasicFS, Always, TestOutput (
1682 [["upload"; "test-command"; "/test-command"];
1683 ["chmod"; "0o755"; "/test-command"];
1684 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1685 InitBasicFS, Always, TestOutput (
1686 [["upload"; "test-command"; "/test-command"];
1687 ["chmod"; "0o755"; "/test-command"];
1688 ["command"; "/test-command 7"]], "");
1689 InitBasicFS, Always, TestOutput (
1690 [["upload"; "test-command"; "/test-command"];
1691 ["chmod"; "0o755"; "/test-command"];
1692 ["command"; "/test-command 8"]], "\n");
1693 InitBasicFS, Always, TestOutput (
1694 [["upload"; "test-command"; "/test-command"];
1695 ["chmod"; "0o755"; "/test-command"];
1696 ["command"; "/test-command 9"]], "\n\n");
1697 InitBasicFS, Always, TestOutput (
1698 [["upload"; "test-command"; "/test-command"];
1699 ["chmod"; "0o755"; "/test-command"];
1700 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1701 InitBasicFS, Always, TestOutput (
1702 [["upload"; "test-command"; "/test-command"];
1703 ["chmod"; "0o755"; "/test-command"];
1704 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1705 InitBasicFS, Always, TestLastFail (
1706 [["upload"; "test-command"; "/test-command"];
1707 ["chmod"; "0o755"; "/test-command"];
1708 ["command"; "/test-command"]])],
1709 "run a command from the guest filesystem",
1711 This call runs a command from the guest filesystem. The
1712 filesystem must be mounted, and must contain a compatible
1713 operating system (ie. something Linux, with the same
1714 or compatible processor architecture).
1716 The single parameter is an argv-style list of arguments.
1717 The first element is the name of the program to run.
1718 Subsequent elements are parameters. The list must be
1719 non-empty (ie. must contain a program name). Note that
1720 the command runs directly, and is I<not> invoked via
1721 the shell (see C<guestfs_sh>).
1723 The return value is anything printed to I<stdout> by
1726 If the command returns a non-zero exit status, then
1727 this function returns an error message. The error message
1728 string is the content of I<stderr> from the command.
1730 The C<$PATH> environment variable will contain at least
1731 C</usr/bin> and C</bin>. If you require a program from
1732 another location, you should provide the full path in the
1735 Shared libraries and data files required by the program
1736 must be available on filesystems which are mounted in the
1737 correct places. It is the caller's responsibility to ensure
1738 all filesystems that are needed are mounted at the right
1741 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1742 [InitBasicFS, Always, TestOutputList (
1743 [["upload"; "test-command"; "/test-command"];
1744 ["chmod"; "0o755"; "/test-command"];
1745 ["command_lines"; "/test-command 1"]], ["Result1"]);
1746 InitBasicFS, Always, TestOutputList (
1747 [["upload"; "test-command"; "/test-command"];
1748 ["chmod"; "0o755"; "/test-command"];
1749 ["command_lines"; "/test-command 2"]], ["Result2"]);
1750 InitBasicFS, Always, TestOutputList (
1751 [["upload"; "test-command"; "/test-command"];
1752 ["chmod"; "0o755"; "/test-command"];
1753 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1754 InitBasicFS, Always, TestOutputList (
1755 [["upload"; "test-command"; "/test-command"];
1756 ["chmod"; "0o755"; "/test-command"];
1757 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1758 InitBasicFS, Always, TestOutputList (
1759 [["upload"; "test-command"; "/test-command"];
1760 ["chmod"; "0o755"; "/test-command"];
1761 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1762 InitBasicFS, Always, TestOutputList (
1763 [["upload"; "test-command"; "/test-command"];
1764 ["chmod"; "0o755"; "/test-command"];
1765 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1766 InitBasicFS, Always, TestOutputList (
1767 [["upload"; "test-command"; "/test-command"];
1768 ["chmod"; "0o755"; "/test-command"];
1769 ["command_lines"; "/test-command 7"]], []);
1770 InitBasicFS, Always, TestOutputList (
1771 [["upload"; "test-command"; "/test-command"];
1772 ["chmod"; "0o755"; "/test-command"];
1773 ["command_lines"; "/test-command 8"]], [""]);
1774 InitBasicFS, Always, TestOutputList (
1775 [["upload"; "test-command"; "/test-command"];
1776 ["chmod"; "0o755"; "/test-command"];
1777 ["command_lines"; "/test-command 9"]], ["";""]);
1778 InitBasicFS, Always, TestOutputList (
1779 [["upload"; "test-command"; "/test-command"];
1780 ["chmod"; "0o755"; "/test-command"];
1781 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1782 InitBasicFS, Always, TestOutputList (
1783 [["upload"; "test-command"; "/test-command"];
1784 ["chmod"; "0o755"; "/test-command"];
1785 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1786 "run a command, returning lines",
1788 This is the same as C<guestfs_command>, but splits the
1789 result into a list of lines.
1791 See also: C<guestfs_sh_lines>");
1793 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1794 [InitISOFS, Always, TestOutputStruct (
1795 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1796 "get file information",
1798 Returns file information for the given C<path>.
1800 This is the same as the C<stat(2)> system call.");
1802 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1803 [InitISOFS, Always, TestOutputStruct (
1804 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1805 "get file information for a symbolic link",
1807 Returns file information for the given C<path>.
1809 This is the same as C<guestfs_stat> except that if C<path>
1810 is a symbolic link, then the link is stat-ed, not the file it
1813 This is the same as the C<lstat(2)> system call.");
1815 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1816 [InitISOFS, Always, TestOutputStruct (
1817 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1818 "get file system statistics",
1820 Returns file system statistics for any mounted file system.
1821 C<path> should be a file or directory in the mounted file system
1822 (typically it is the mount point itself, but it doesn't need to be).
1824 This is the same as the C<statvfs(2)> system call.");
1826 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1828 "get ext2/ext3/ext4 superblock details",
1830 This returns the contents of the ext2, ext3 or ext4 filesystem
1831 superblock on C<device>.
1833 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1834 manpage for more details. The list of fields returned isn't
1835 clearly defined, and depends on both the version of C<tune2fs>
1836 that libguestfs was built against, and the filesystem itself.");
1838 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1839 [InitEmpty, Always, TestOutputTrue (
1840 [["blockdev_setro"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-only",
1844 Sets the block device named C<device> to read-only.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1849 [InitEmpty, Always, TestOutputFalse (
1850 [["blockdev_setrw"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "set block device to read-write",
1854 Sets the block device named C<device> to read-write.
1856 This uses the L<blockdev(8)> command.");
1858 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1859 [InitEmpty, Always, TestOutputTrue (
1860 [["blockdev_setro"; "/dev/sda"];
1861 ["blockdev_getro"; "/dev/sda"]])],
1862 "is block device set to read-only",
1864 Returns a boolean indicating if the block device is read-only
1865 (true if read-only, false if not).
1867 This uses the L<blockdev(8)> command.");
1869 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1870 [InitEmpty, Always, TestOutputInt (
1871 [["blockdev_getss"; "/dev/sda"]], 512)],
1872 "get sectorsize of block device",
1874 This returns the size of sectors on a block device.
1875 Usually 512, but can be larger for modern devices.
1877 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1883 [InitEmpty, Always, TestOutputInt (
1884 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1885 "get blocksize of block device",
1887 This returns the block size of a device.
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1892 This uses the L<blockdev(8)> command.");
1894 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1896 "set blocksize of block device",
1898 This sets the block size of a device.
1900 (Note this is different from both I<size in blocks> and
1901 I<filesystem block size>).
1903 This uses the L<blockdev(8)> command.");
1905 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1906 [InitEmpty, Always, TestOutputInt (
1907 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1908 "get total size of device in 512-byte sectors",
1910 This returns the size of the device in units of 512-byte sectors
1911 (even if the sectorsize isn't 512 bytes ... weird).
1913 See also C<guestfs_blockdev_getss> for the real sector size of
1914 the device, and C<guestfs_blockdev_getsize64> for the more
1915 useful I<size in bytes>.
1917 This uses the L<blockdev(8)> command.");
1919 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1920 [InitEmpty, Always, TestOutputInt (
1921 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1922 "get total size of device in bytes",
1924 This returns the size of the device in bytes.
1926 See also C<guestfs_blockdev_getsz>.
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_flushbufs"; "/dev/sda"]]],
1933 "flush device buffers",
1935 This tells the kernel to flush internal buffers associated
1938 This uses the L<blockdev(8)> command.");
1940 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1941 [InitEmpty, Always, TestRun
1942 [["blockdev_rereadpt"; "/dev/sda"]]],
1943 "reread partition table",
1945 Reread the partition table on C<device>.
1947 This uses the L<blockdev(8)> command.");
1949 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1950 [InitBasicFS, Always, TestOutput (
1951 (* Pick a file from cwd which isn't likely to change. *)
1952 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1953 ["checksum"; "md5"; "/COPYING.LIB"]],
1954 Digest.to_hex (Digest.file "COPYING.LIB"))],
1955 "upload a file from the local machine",
1957 Upload local file C<filename> to C<remotefilename> on the
1960 C<filename> can also be a named pipe.
1962 See also C<guestfs_download>.");
1964 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1965 [InitBasicFS, Always, TestOutput (
1966 (* Pick a file from cwd which isn't likely to change. *)
1967 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1968 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1969 ["upload"; "testdownload.tmp"; "/upload"];
1970 ["checksum"; "md5"; "/upload"]],
1971 Digest.to_hex (Digest.file "COPYING.LIB"))],
1972 "download a file to the local machine",
1974 Download file C<remotefilename> and save it as C<filename>
1975 on the local machine.
1977 C<filename> can also be a named pipe.
1979 See also C<guestfs_upload>, C<guestfs_cat>.");
1981 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1982 [InitISOFS, Always, TestOutput (
1983 [["checksum"; "crc"; "/known-3"]], "2891671662");
1984 InitISOFS, Always, TestLastFail (
1985 [["checksum"; "crc"; "/notexists"]]);
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1988 InitISOFS, Always, TestOutput (
1989 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1990 InitISOFS, Always, TestOutput (
1991 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1992 InitISOFS, Always, TestOutput (
1993 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1994 InitISOFS, Always, TestOutput (
1995 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1996 InitISOFS, Always, TestOutput (
1997 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1998 (* Test for RHBZ#579608, absolute symbolic links. *)
1999 InitISOFS, Always, TestOutput (
2000 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2001 "compute MD5, SHAx or CRC checksum of file",
2003 This call computes the MD5, SHAx or CRC checksum of the
2006 The type of checksum to compute is given by the C<csumtype>
2007 parameter which must have one of the following values:
2013 Compute the cyclic redundancy check (CRC) specified by POSIX
2014 for the C<cksum> command.
2018 Compute the MD5 hash (using the C<md5sum> program).
2022 Compute the SHA1 hash (using the C<sha1sum> program).
2026 Compute the SHA224 hash (using the C<sha224sum> program).
2030 Compute the SHA256 hash (using the C<sha256sum> program).
2034 Compute the SHA384 hash (using the C<sha384sum> program).
2038 Compute the SHA512 hash (using the C<sha512sum> program).
2042 The checksum is returned as a printable string.
2044 To get the checksum for a device, use C<guestfs_checksum_device>.
2046 To get the checksums for many files, use C<guestfs_checksums_out>.");
2048 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2049 [InitBasicFS, Always, TestOutput (
2050 [["tar_in"; "../images/helloworld.tar"; "/"];
2051 ["cat"; "/hello"]], "hello\n")],
2052 "unpack tarfile to directory",
2054 This command uploads and unpacks local file C<tarfile> (an
2055 I<uncompressed> tar file) into C<directory>.
2057 To upload a compressed tarball, use C<guestfs_tgz_in>
2058 or C<guestfs_txz_in>.");
2060 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2062 "pack directory into tarfile",
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarfile>.
2067 To download a compressed tarball, use C<guestfs_tgz_out>
2068 or C<guestfs_txz_out>.");
2070 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2071 [InitBasicFS, Always, TestOutput (
2072 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2073 ["cat"; "/hello"]], "hello\n")],
2074 "unpack compressed tarball to directory",
2076 This command uploads and unpacks local file C<tarball> (a
2077 I<gzip compressed> tar file) into C<directory>.
2079 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2081 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2083 "pack directory into compressed tarball",
2085 This command packs the contents of C<directory> and downloads
2086 it to local file C<tarball>.
2088 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2090 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2091 [InitBasicFS, Always, TestLastFail (
2093 ["mount_ro"; "/dev/sda1"; "/"];
2094 ["touch"; "/new"]]);
2095 InitBasicFS, Always, TestOutput (
2096 [["write"; "/new"; "data"];
2098 ["mount_ro"; "/dev/sda1"; "/"];
2099 ["cat"; "/new"]], "data")],
2100 "mount a guest disk, read-only",
2102 This is the same as the C<guestfs_mount> command, but it
2103 mounts the filesystem with the read-only (I<-o ro>) flag.");
2105 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2107 "mount a guest disk with mount options",
2109 This is the same as the C<guestfs_mount> command, but it
2110 allows you to set the mount options as for the
2111 L<mount(8)> I<-o> flag.
2113 If the C<options> parameter is an empty string, then
2114 no options are passed (all options default to whatever
2115 the filesystem uses).");
2117 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2119 "mount a guest disk with mount options and vfstype",
2121 This is the same as the C<guestfs_mount> command, but it
2122 allows you to set both the mount options and the vfstype
2123 as for the L<mount(8)> I<-o> and I<-t> flags.");
2125 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2127 "debugging and internals",
2129 The C<guestfs_debug> command exposes some internals of
2130 C<guestfsd> (the guestfs daemon) that runs inside the
2133 There is no comprehensive help for this command. You have
2134 to look at the file C<daemon/debug.c> in the libguestfs source
2135 to find out what you can do.");
2137 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2138 [InitEmpty, Always, TestOutputList (
2139 [["part_disk"; "/dev/sda"; "mbr"];
2140 ["pvcreate"; "/dev/sda1"];
2141 ["vgcreate"; "VG"; "/dev/sda1"];
2142 ["lvcreate"; "LV1"; "VG"; "50"];
2143 ["lvcreate"; "LV2"; "VG"; "50"];
2144 ["lvremove"; "/dev/VG/LV1"];
2145 ["lvs"]], ["/dev/VG/LV2"]);
2146 InitEmpty, Always, TestOutputList (
2147 [["part_disk"; "/dev/sda"; "mbr"];
2148 ["pvcreate"; "/dev/sda1"];
2149 ["vgcreate"; "VG"; "/dev/sda1"];
2150 ["lvcreate"; "LV1"; "VG"; "50"];
2151 ["lvcreate"; "LV2"; "VG"; "50"];
2152 ["lvremove"; "/dev/VG"];
2154 InitEmpty, Always, TestOutputList (
2155 [["part_disk"; "/dev/sda"; "mbr"];
2156 ["pvcreate"; "/dev/sda1"];
2157 ["vgcreate"; "VG"; "/dev/sda1"];
2158 ["lvcreate"; "LV1"; "VG"; "50"];
2159 ["lvcreate"; "LV2"; "VG"; "50"];
2160 ["lvremove"; "/dev/VG"];
2162 "remove an LVM logical volume",
2164 Remove an LVM logical volume C<device>, where C<device> is
2165 the path to the LV, such as C</dev/VG/LV>.
2167 You can also remove all LVs in a volume group by specifying
2168 the VG name, C</dev/VG>.");
2170 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2171 [InitEmpty, Always, TestOutputList (
2172 [["part_disk"; "/dev/sda"; "mbr"];
2173 ["pvcreate"; "/dev/sda1"];
2174 ["vgcreate"; "VG"; "/dev/sda1"];
2175 ["lvcreate"; "LV1"; "VG"; "50"];
2176 ["lvcreate"; "LV2"; "VG"; "50"];
2179 InitEmpty, Always, TestOutputList (
2180 [["part_disk"; "/dev/sda"; "mbr"];
2181 ["pvcreate"; "/dev/sda1"];
2182 ["vgcreate"; "VG"; "/dev/sda1"];
2183 ["lvcreate"; "LV1"; "VG"; "50"];
2184 ["lvcreate"; "LV2"; "VG"; "50"];
2187 "remove an LVM volume group",
2189 Remove an LVM volume group C<vgname>, (for example C<VG>).
2191 This also forcibly removes all logical volumes in the volume
2194 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2195 [InitEmpty, Always, TestOutputListOfDevices (
2196 [["part_disk"; "/dev/sda"; "mbr"];
2197 ["pvcreate"; "/dev/sda1"];
2198 ["vgcreate"; "VG"; "/dev/sda1"];
2199 ["lvcreate"; "LV1"; "VG"; "50"];
2200 ["lvcreate"; "LV2"; "VG"; "50"];
2202 ["pvremove"; "/dev/sda1"];
2204 InitEmpty, Always, TestOutputListOfDevices (
2205 [["part_disk"; "/dev/sda"; "mbr"];
2206 ["pvcreate"; "/dev/sda1"];
2207 ["vgcreate"; "VG"; "/dev/sda1"];
2208 ["lvcreate"; "LV1"; "VG"; "50"];
2209 ["lvcreate"; "LV2"; "VG"; "50"];
2211 ["pvremove"; "/dev/sda1"];
2213 InitEmpty, Always, TestOutputListOfDevices (
2214 [["part_disk"; "/dev/sda"; "mbr"];
2215 ["pvcreate"; "/dev/sda1"];
2216 ["vgcreate"; "VG"; "/dev/sda1"];
2217 ["lvcreate"; "LV1"; "VG"; "50"];
2218 ["lvcreate"; "LV2"; "VG"; "50"];
2220 ["pvremove"; "/dev/sda1"];
2222 "remove an LVM physical volume",
2224 This wipes a physical volume C<device> so that LVM will no longer
2227 The implementation uses the C<pvremove> command which refuses to
2228 wipe physical volumes that contain any volume groups, so you have
2229 to remove those first.");
2231 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2232 [InitBasicFS, Always, TestOutput (
2233 [["set_e2label"; "/dev/sda1"; "testlabel"];
2234 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2235 "set the ext2/3/4 filesystem label",
2237 This sets the ext2/3/4 filesystem label of the filesystem on
2238 C<device> to C<label>. Filesystem labels are limited to
2241 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2242 to return the existing label on a filesystem.");
2244 ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2246 "get the ext2/3/4 filesystem label",
2248 This returns the ext2/3/4 filesystem label of the filesystem on
2251 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2252 (let uuid = uuidgen () in
2253 [InitBasicFS, Always, TestOutput (
2254 [["set_e2uuid"; "/dev/sda1"; uuid];
2255 ["get_e2uuid"; "/dev/sda1"]], uuid);
2256 InitBasicFS, Always, TestOutput (
2257 [["set_e2uuid"; "/dev/sda1"; "clear"];
2258 ["get_e2uuid"; "/dev/sda1"]], "");
2259 (* We can't predict what UUIDs will be, so just check the commands run. *)
2260 InitBasicFS, Always, TestRun (
2261 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2262 InitBasicFS, Always, TestRun (
2263 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2264 "set the ext2/3/4 filesystem UUID",
2266 This sets the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device> to C<uuid>. The format of the UUID and alternatives
2268 such as C<clear>, C<random> and C<time> are described in the
2269 L<tune2fs(8)> manpage.
2271 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2272 to return the existing UUID of a filesystem.");
2274 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2275 (* Regression test for RHBZ#597112. *)
2276 (let uuid = uuidgen () in
2277 [InitBasicFS, Always, TestOutput (
2278 [["mke2journal"; "1024"; "/dev/sdb"];
2279 ["set_e2uuid"; "/dev/sdb"; uuid];
2280 ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2281 "get the ext2/3/4 filesystem UUID",
2283 This returns the ext2/3/4 filesystem UUID of the filesystem on
2286 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2287 [InitBasicFS, Always, TestOutputInt (
2288 [["umount"; "/dev/sda1"];
2289 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2290 InitBasicFS, Always, TestOutputInt (
2291 [["umount"; "/dev/sda1"];
2292 ["zero"; "/dev/sda1"];
2293 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2294 "run the filesystem checker",
2296 This runs the filesystem checker (fsck) on C<device> which
2297 should have filesystem type C<fstype>.
2299 The returned integer is the status. See L<fsck(8)> for the
2300 list of status codes from C<fsck>.
2308 Multiple status codes can be summed together.
2312 A non-zero return code can mean \"success\", for example if
2313 errors have been corrected on the filesystem.
2317 Checking or repairing NTFS volumes is not supported
2322 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2324 ("zero", (RErr, [Device "device"]), 85, [],
2325 [InitBasicFS, Always, TestOutput (
2326 [["umount"; "/dev/sda1"];
2327 ["zero"; "/dev/sda1"];
2328 ["file"; "/dev/sda1"]], "data")],
2329 "write zeroes to the device",
2331 This command writes zeroes over the first few blocks of C<device>.
2333 How many blocks are zeroed isn't specified (but it's I<not> enough
2334 to securely wipe the device). It should be sufficient to remove
2335 any partition tables, filesystem superblocks and so on.
2337 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2339 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2341 * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2342 * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2344 [InitBasicFS, Always, TestOutputTrue (
2345 [["mkdir_p"; "/boot/grub"];
2346 ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2347 ["grub_install"; "/"; "/dev/vda"];
2348 ["is_dir"; "/boot"]])],
2351 This command installs GRUB (the Grand Unified Bootloader) on
2352 C<device>, with the root directory being C<root>.
2354 Note: If grub-install reports the error
2355 \"No suitable drive was found in the generated device map.\"
2356 it may be that you need to create a C</boot/grub/device.map>
2357 file first that contains the mapping between grub device names
2358 and Linux device names. It is usually sufficient to create
2363 replacing C</dev/vda> with the name of the installation device.");
2365 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2366 [InitBasicFS, Always, TestOutput (
2367 [["write"; "/old"; "file content"];
2368 ["cp"; "/old"; "/new"];
2369 ["cat"; "/new"]], "file content");
2370 InitBasicFS, Always, TestOutputTrue (
2371 [["write"; "/old"; "file content"];
2372 ["cp"; "/old"; "/new"];
2373 ["is_file"; "/old"]]);
2374 InitBasicFS, Always, TestOutput (
2375 [["write"; "/old"; "file content"];
2377 ["cp"; "/old"; "/dir/new"];
2378 ["cat"; "/dir/new"]], "file content")],
2381 This copies a file from C<src> to C<dest> where C<dest> is
2382 either a destination filename or destination directory.");
2384 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2385 [InitBasicFS, Always, TestOutput (
2386 [["mkdir"; "/olddir"];
2387 ["mkdir"; "/newdir"];
2388 ["write"; "/olddir/file"; "file content"];
2389 ["cp_a"; "/olddir"; "/newdir"];
2390 ["cat"; "/newdir/olddir/file"]], "file content")],
2391 "copy a file or directory recursively",
2393 This copies a file or directory from C<src> to C<dest>
2394 recursively using the C<cp -a> command.");
2396 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2397 [InitBasicFS, Always, TestOutput (
2398 [["write"; "/old"; "file content"];
2399 ["mv"; "/old"; "/new"];
2400 ["cat"; "/new"]], "file content");
2401 InitBasicFS, Always, TestOutputFalse (
2402 [["write"; "/old"; "file content"];
2403 ["mv"; "/old"; "/new"];
2404 ["is_file"; "/old"]])],
2407 This moves a file from C<src> to C<dest> where C<dest> is
2408 either a destination filename or destination directory.");
2410 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2411 [InitEmpty, Always, TestRun (
2412 [["drop_caches"; "3"]])],
2413 "drop kernel page cache, dentries and inodes",
2415 This instructs the guest kernel to drop its page cache,
2416 and/or dentries and inode caches. The parameter C<whattodrop>
2417 tells the kernel what precisely to drop, see
2418 L<http://linux-mm.org/Drop_Caches>
2420 Setting C<whattodrop> to 3 should drop everything.
2422 This automatically calls L<sync(2)> before the operation,
2423 so that the maximum guest memory is freed.");
2425 ("dmesg", (RString "kmsgs", []), 91, [],
2426 [InitEmpty, Always, TestRun (
2428 "return kernel messages",
2430 This returns the kernel messages (C<dmesg> output) from
2431 the guest kernel. This is sometimes useful for extended
2432 debugging of problems.
2434 Another way to get the same information is to enable
2435 verbose messages with C<guestfs_set_verbose> or by setting
2436 the environment variable C<LIBGUESTFS_DEBUG=1> before
2437 running the program.");
2439 ("ping_daemon", (RErr, []), 92, [],
2440 [InitEmpty, Always, TestRun (
2441 [["ping_daemon"]])],
2442 "ping the guest daemon",
2444 This is a test probe into the guestfs daemon running inside
2445 the qemu subprocess. Calling this function checks that the
2446 daemon responds to the ping message, without affecting the daemon
2447 or attached block device(s) in any other way.");
2449 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2450 [InitBasicFS, Always, TestOutputTrue (
2451 [["write"; "/file1"; "contents of a file"];
2452 ["cp"; "/file1"; "/file2"];
2453 ["equal"; "/file1"; "/file2"]]);
2454 InitBasicFS, Always, TestOutputFalse (
2455 [["write"; "/file1"; "contents of a file"];
2456 ["write"; "/file2"; "contents of another file"];
2457 ["equal"; "/file1"; "/file2"]]);
2458 InitBasicFS, Always, TestLastFail (
2459 [["equal"; "/file1"; "/file2"]])],
2460 "test if two files have equal contents",
2462 This compares the two files C<file1> and C<file2> and returns
2463 true if their content is exactly equal, or false otherwise.
2465 The external L<cmp(1)> program is used for the comparison.");
2467 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2468 [InitISOFS, Always, TestOutputList (
2469 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2470 InitISOFS, Always, TestOutputList (
2471 [["strings"; "/empty"]], []);
2472 (* Test for RHBZ#579608, absolute symbolic links. *)
2473 InitISOFS, Always, TestRun (
2474 [["strings"; "/abssymlink"]])],
2475 "print the printable strings in a file",
2477 This runs the L<strings(1)> command on a file and returns
2478 the list of printable strings found.");
2480 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2481 [InitISOFS, Always, TestOutputList (
2482 [["strings_e"; "b"; "/known-5"]], []);
2483 InitBasicFS, Always, TestOutputList (
2484 [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2485 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2486 "print the printable strings in a file",
2488 This is like the C<guestfs_strings> command, but allows you to
2489 specify the encoding of strings that are looked for in
2490 the source file C<path>.
2492 Allowed encodings are:
2498 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2499 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2503 Single 8-bit-byte characters.
2507 16-bit big endian strings such as those encoded in
2508 UTF-16BE or UCS-2BE.
2510 =item l (lower case letter L)
2512 16-bit little endian such as UTF-16LE and UCS-2LE.
2513 This is useful for examining binaries in Windows guests.
2517 32-bit big endian such as UCS-4BE.
2521 32-bit little endian such as UCS-4LE.
2525 The returned strings are transcoded to UTF-8.");
2527 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2528 [InitISOFS, Always, TestOutput (
2529 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2530 (* Test for RHBZ#501888c2 regression which caused large hexdump
2531 * commands to segfault.
2533 InitISOFS, Always, TestRun (
2534 [["hexdump"; "/100krandom"]]);
2535 (* Test for RHBZ#579608, absolute symbolic links. *)
2536 InitISOFS, Always, TestRun (
2537 [["hexdump"; "/abssymlink"]])],
2538 "dump a file in hexadecimal",
2540 This runs C<hexdump -C> on the given C<path>. The result is
2541 the human-readable, canonical hex dump of the file.");
2543 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2544 [InitNone, Always, TestOutput (
2545 [["part_disk"; "/dev/sda"; "mbr"];
2546 ["mkfs"; "ext3"; "/dev/sda1"];
2547 ["mount_options"; ""; "/dev/sda1"; "/"];
2548 ["write"; "/new"; "test file"];
2549 ["umount"; "/dev/sda1"];
2550 ["zerofree"; "/dev/sda1"];
2551 ["mount_options"; ""; "/dev/sda1"; "/"];
2552 ["cat"; "/new"]], "test file")],
2553 "zero unused inodes and disk blocks on ext2/3 filesystem",
2555 This runs the I<zerofree> program on C<device>. This program
2556 claims to zero unused inodes and disk blocks on an ext2/3
2557 filesystem, thus making it possible to compress the filesystem
2560 You should B<not> run this program if the filesystem is
2563 It is possible that using this program can damage the filesystem
2564 or data on the filesystem.");
2566 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2568 "resize an LVM physical volume",
2570 This resizes (expands or shrinks) an existing LVM physical
2571 volume to match the new size of the underlying device.");
2573 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2574 Int "cyls"; Int "heads"; Int "sectors";
2575 String "line"]), 99, [DangerWillRobinson],
2577 "modify a single partition on a block device",
2579 This runs L<sfdisk(8)> option to modify just the single
2580 partition C<n> (note: C<n> counts from 1).
2582 For other parameters, see C<guestfs_sfdisk>. You should usually
2583 pass C<0> for the cyls/heads/sectors parameters.
2585 See also: C<guestfs_part_add>");
2587 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2589 "display the partition table",
2591 This displays the partition table on C<device>, in the
2592 human-readable output of the L<sfdisk(8)> command. It is
2593 not intended to be parsed.
2595 See also: C<guestfs_part_list>");
2597 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2599 "display the kernel geometry",
2601 This displays the kernel's idea of the geometry of C<device>.
2603 The result is in human-readable format, and not designed to
2606 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2608 "display the disk geometry from the partition table",
2610 This displays the disk geometry of C<device> read from the
2611 partition table. Especially in the case where the underlying
2612 block device has been resized, this can be different from the
2613 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2615 The result is in human-readable format, and not designed to
2618 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2620 "activate or deactivate all volume groups",
2622 This command activates or (if C<activate> is false) deactivates
2623 all logical volumes in all volume groups.
2624 If activated, then they are made known to the
2625 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2626 then those devices disappear.
2628 This command is the same as running C<vgchange -a y|n>");
2630 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2632 "activate or deactivate some volume groups",
2634 This command activates or (if C<activate> is false) deactivates
2635 all logical volumes in the listed volume groups C<volgroups>.
2636 If activated, then they are made known to the
2637 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2638 then those devices disappear.
2640 This command is the same as running C<vgchange -a y|n volgroups...>
2642 Note that if C<volgroups> is an empty list then B<all> volume groups
2643 are activated or deactivated.");
2645 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2646 [InitNone, Always, TestOutput (
2647 [["part_disk"; "/dev/sda"; "mbr"];
2648 ["pvcreate"; "/dev/sda1"];
2649 ["vgcreate"; "VG"; "/dev/sda1"];
2650 ["lvcreate"; "LV"; "VG"; "10"];
2651 ["mkfs"; "ext2"; "/dev/VG/LV"];
2652 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2653 ["write"; "/new"; "test content"];
2655 ["lvresize"; "/dev/VG/LV"; "20"];
2656 ["e2fsck_f"; "/dev/VG/LV"];
2657 ["resize2fs"; "/dev/VG/LV"];
2658 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2659 ["cat"; "/new"]], "test content");
2660 InitNone, Always, TestRun (
2661 (* Make an LV smaller to test RHBZ#587484. *)
2662 [["part_disk"; "/dev/sda"; "mbr"];
2663 ["pvcreate"; "/dev/sda1"];
2664 ["vgcreate"; "VG"; "/dev/sda1"];
2665 ["lvcreate"; "LV"; "VG"; "20"];
2666 ["lvresize"; "/dev/VG/LV"; "10"]])],
2667 "resize an LVM logical volume",
2669 This resizes (expands or shrinks) an existing LVM logical
2670 volume to C<mbytes>. When reducing, data in the reduced part
2673 ("resize2fs", (RErr, [Device "device"]), 106, [],
2674 [], (* lvresize tests this *)
2675 "resize an ext2, ext3 or ext4 filesystem",
2677 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2678 the underlying device.
2680 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2681 on the C<device> before calling this command. For unknown reasons
2682 C<resize2fs> sometimes gives an error about this and sometimes not.
2683 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2684 calling this function.");
2686 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2687 [InitBasicFS, Always, TestOutputList (
2688 [["find"; "/"]], ["lost+found"]);
2689 InitBasicFS, Always, TestOutputList (
2693 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2694 InitBasicFS, Always, TestOutputList (
2695 [["mkdir_p"; "/a/b/c"];
2696 ["touch"; "/a/b/c/d"];
2697 ["find"; "/a/b/"]], ["c"; "c/d"])],
2698 "find all files and directories",
2700 This command lists out all files and directories, recursively,
2701 starting at C<directory>. It is essentially equivalent to
2702 running the shell command C<find directory -print> but some
2703 post-processing happens on the output, described below.
2705 This returns a list of strings I<without any prefix>. Thus
2706 if the directory structure was:
2712 then the returned list from C<guestfs_find> C</tmp> would be
2720 If C<directory> is not a directory, then this command returns
2723 The returned list is sorted.
2725 See also C<guestfs_find0>.");
2727 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2728 [], (* lvresize tests this *)
2729 "check an ext2/ext3 filesystem",
2731 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2732 filesystem checker on C<device>, noninteractively (C<-p>),
2733 even if the filesystem appears to be clean (C<-f>).
2735 This command is only needed because of C<guestfs_resize2fs>
2736 (q.v.). Normally you should use C<guestfs_fsck>.");
2738 ("sleep", (RErr, [Int "secs"]), 109, [],
2739 [InitNone, Always, TestRun (
2741 "sleep for some seconds",
2743 Sleep for C<secs> seconds.");
2745 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2746 [InitNone, Always, TestOutputInt (
2747 [["part_disk"; "/dev/sda"; "mbr"];
2748 ["mkfs"; "ntfs"; "/dev/sda1"];
2749 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2750 InitNone, Always, TestOutputInt (
2751 [["part_disk"; "/dev/sda"; "mbr"];
2752 ["mkfs"; "ext2"; "/dev/sda1"];
2753 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2754 "probe NTFS volume",
2756 This command runs the L<ntfs-3g.probe(8)> command which probes
2757 an NTFS C<device> for mountability. (Not all NTFS volumes can
2758 be mounted read-write, and some cannot be mounted at all).
2760 C<rw> is a boolean flag. Set it to true if you want to test
2761 if the volume can be mounted read-write. Set it to false if
2762 you want to test if the volume can be mounted read-only.
2764 The return value is an integer which C<0> if the operation
2765 would succeed, or some non-zero value documented in the
2766 L<ntfs-3g.probe(8)> manual page.");
2768 ("sh", (RString "output", [String "command"]), 111, [],
2769 [], (* XXX needs tests *)
2770 "run a command via the shell",
2772 This call runs a command from the guest filesystem via the
2775 This is like C<guestfs_command>, but passes the command to:
2777 /bin/sh -c \"command\"
2779 Depending on the guest's shell, this usually results in
2780 wildcards being expanded, shell expressions being interpolated
2783 All the provisos about C<guestfs_command> apply to this call.");
2785 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2786 [], (* XXX needs tests *)
2787 "run a command via the shell returning lines",
2789 This is the same as C<guestfs_sh>, but splits the result
2790 into a list of lines.
2792 See also: C<guestfs_command_lines>");
2794 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2795 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2796 * code in stubs.c, since all valid glob patterns must start with "/".
2797 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2799 [InitBasicFS, Always, TestOutputList (
2800 [["mkdir_p"; "/a/b/c"];
2801 ["touch"; "/a/b/c/d"];
2802 ["touch"; "/a/b/c/e"];
2803 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2804 InitBasicFS, Always, TestOutputList (
2805 [["mkdir_p"; "/a/b/c"];
2806 ["touch"; "/a/b/c/d"];
2807 ["touch"; "/a/b/c/e"];
2808 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809 InitBasicFS, Always, TestOutputList (
2810 [["mkdir_p"; "/a/b/c"];
2811 ["touch"; "/a/b/c/d"];
2812 ["touch"; "/a/b/c/e"];
2813 ["glob_expand"; "/a/*/x/*"]], [])],
2814 "expand a wildcard path",
2816 This command searches for all the pathnames matching
2817 C<pattern> according to the wildcard expansion rules
2820 If no paths match, then this returns an empty list
2821 (note: not an error).
2823 It is just a wrapper around the C L<glob(3)> function
2824 with flags C<GLOB_MARK|GLOB_BRACE>.
2825 See that manual page for more details.");
2827 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2828 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2829 [["scrub_device"; "/dev/sdc"]])],
2830 "scrub (securely wipe) a device",
2832 This command writes patterns over C<device> to make data retrieval
2835 It is an interface to the L<scrub(1)> program. See that
2836 manual page for more details.");
2838 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2839 [InitBasicFS, Always, TestRun (
2840 [["write"; "/file"; "content"];
2841 ["scrub_file"; "/file"]])],
2842 "scrub (securely wipe) a file",
2844 This command writes patterns over a file to make data retrieval
2847 The file is I<removed> after scrubbing.
2849 It is an interface to the L<scrub(1)> program. See that
2850 manual page for more details.");
2852 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2853 [], (* XXX needs testing *)
2854 "scrub (securely wipe) free space",
2856 This command creates the directory C<dir> and then fills it
2857 with files until the filesystem is full, and scrubs the files
2858 as for C<guestfs_scrub_file>, and deletes them.
2859 The intention is to scrub any free space on the partition
2862 It is an interface to the L<scrub(1)> program. See that
2863 manual page for more details.");
2865 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2866 [InitBasicFS, Always, TestRun (
2868 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2869 "create a temporary directory",
2871 This command creates a temporary directory. The
2872 C<template> parameter should be a full pathname for the
2873 temporary directory name with the final six characters being
2876 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2877 the second one being suitable for Windows filesystems.
2879 The name of the temporary directory that was created
2882 The temporary directory is created with mode 0700
2883 and is owned by root.
2885 The caller is responsible for deleting the temporary
2886 directory and its contents after use.
2888 See also: L<mkdtemp(3)>");
2890 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2891 [InitISOFS, Always, TestOutputInt (
2892 [["wc_l"; "/10klines"]], 10000);
2893 (* Test for RHBZ#579608, absolute symbolic links. *)
2894 InitISOFS, Always, TestOutputInt (
2895 [["wc_l"; "/abssymlink"]], 10000)],
2896 "count lines in a file",
2898 This command counts the lines in a file, using the
2899 C<wc -l> external command.");
2901 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2902 [InitISOFS, Always, TestOutputInt (
2903 [["wc_w"; "/10klines"]], 10000)],
2904 "count words in a file",
2906 This command counts the words in a file, using the
2907 C<wc -w> external command.");
2909 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2910 [InitISOFS, Always, TestOutputInt (
2911 [["wc_c"; "/100kallspaces"]], 102400)],
2912 "count characters in a file",
2914 This command counts the characters in a file, using the
2915 C<wc -c> external command.");
2917 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2918 [InitISOFS, Always, TestOutputList (
2919 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2920 (* Test for RHBZ#579608, absolute symbolic links. *)
2921 InitISOFS, Always, TestOutputList (
2922 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2923 "return first 10 lines of a file",
2925 This command returns up to the first 10 lines of a file as
2926 a list of strings.");
2928 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2929 [InitISOFS, Always, TestOutputList (
2930 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2931 InitISOFS, Always, TestOutputList (
2932 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933 InitISOFS, Always, TestOutputList (
2934 [["head_n"; "0"; "/10klines"]], [])],
2935 "return first N lines of a file",
2937 If the parameter C<nrlines> is a positive number, this returns the first
2938 C<nrlines> lines of the file C<path>.
2940 If the parameter C<nrlines> is a negative number, this returns lines
2941 from the file C<path>, excluding the last C<nrlines> lines.
2943 If the parameter C<nrlines> is zero, this returns an empty list.");
2945 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2946 [InitISOFS, Always, TestOutputList (
2947 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2948 "return last 10 lines of a file",
2950 This command returns up to the last 10 lines of a file as
2951 a list of strings.");
2953 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2954 [InitISOFS, Always, TestOutputList (
2955 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2956 InitISOFS, Always, TestOutputList (
2957 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958 InitISOFS, Always, TestOutputList (
2959 [["tail_n"; "0"; "/10klines"]], [])],
2960 "return last N lines of a file",
2962 If the parameter C<nrlines> is a positive number, this returns the last
2963 C<nrlines> lines of the file C<path>.
2965 If the parameter C<nrlines> is a negative number, this returns lines
2966 from the file C<path>, starting with the C<-nrlines>th line.
2968 If the parameter C<nrlines> is zero, this returns an empty list.");
2970 ("df", (RString "output", []), 125, [],
2971 [], (* XXX Tricky to test because it depends on the exact format
2972 * of the 'df' command and other imponderables.
2974 "report file system disk space usage",
2976 This command runs the C<df> command to report disk space used.
2978 This command is mostly useful for interactive sessions. It
2979 is I<not> intended that you try to parse the output string.
2980 Use C<statvfs> from programs.");
2982 ("df_h", (RString "output", []), 126, [],
2983 [], (* XXX Tricky to test because it depends on the exact format
2984 * of the 'df' command and other imponderables.
2986 "report file system disk space usage (human readable)",
2988 This command runs the C<df -h> command to report disk space used
2989 in human-readable format.
2991 This command is mostly useful for interactive sessions. It
2992 is I<not> intended that you try to parse the output string.
2993 Use C<statvfs> from programs.");
2995 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2996 [InitISOFS, Always, TestOutputInt (
2997 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2998 "estimate file space usage",
3000 This command runs the C<du -s> command to estimate file space
3003 C<path> can be a file or a directory. If C<path> is a directory
3004 then the estimate includes the contents of the directory and all
3005 subdirectories (recursively).
3007 The result is the estimated size in I<kilobytes>
3008 (ie. units of 1024 bytes).");
3010 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3011 [InitISOFS, Always, TestOutputList (
3012 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3013 "list files in an initrd",
3015 This command lists out files contained in an initrd.
3017 The files are listed without any initial C</> character. The
3018 files are listed in the order they appear (not necessarily
3019 alphabetical). Directory names are listed as separate items.
3021 Old Linux kernels (2.4 and earlier) used a compressed ext2
3022 filesystem as initrd. We I<only> support the newer initramfs
3023 format (compressed cpio files).");
3025 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3027 "mount a file using the loop device",
3029 This command lets you mount C<file> (a filesystem image
3030 in a file) on a mount point. It is entirely equivalent to
3031 the command C<mount -o loop file mountpoint>.");
3033 ("mkswap", (RErr, [Device "device"]), 130, [],
3034 [InitEmpty, Always, TestRun (
3035 [["part_disk"; "/dev/sda"; "mbr"];
3036 ["mkswap"; "/dev/sda1"]])],
3037 "create a swap partition",
3039 Create a swap partition on C<device>.");
3041 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3042 [InitEmpty, Always, TestRun (
3043 [["part_disk"; "/dev/sda"; "mbr"];
3044 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3045 "create a swap partition with a label",
3047 Create a swap partition on C<device> with label C<label>.
3049 Note that you cannot attach a swap label to a block device
3050 (eg. C</dev/sda>), just to a partition. This appears to be
3051 a limitation of the kernel or swap tools.");
3053 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3054 (let uuid = uuidgen () in
3055 [InitEmpty, Always, TestRun (
3056 [["part_disk"; "/dev/sda"; "mbr"];
3057 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3058 "create a swap partition with an explicit UUID",
3060 Create a swap partition on C<device> with UUID C<uuid>.");
3062 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3063 [InitBasicFS, Always, TestOutputStruct (
3064 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3065 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3066 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3067 InitBasicFS, Always, TestOutputStruct (
3068 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3069 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3070 "make block, character or FIFO devices",
3072 This call creates block or character special devices, or
3073 named pipes (FIFOs).
3075 The C<mode> parameter should be the mode, using the standard
3076 constants. C<devmajor> and C<devminor> are the
3077 device major and minor numbers, only used when creating block
3078 and character special devices.
3080 Note that, just like L<mknod(2)>, the mode must be bitwise
3081 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3082 just creates a regular file). These constants are
3083 available in the standard Linux header files, or you can use
3084 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3085 which are wrappers around this command which bitwise OR
3086 in the appropriate constant for you.
3088 The mode actually set is affected by the umask.");
3090 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3091 [InitBasicFS, Always, TestOutputStruct (
3092 [["mkfifo"; "0o777"; "/node"];
3093 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3094 "make FIFO (named pipe)",
3096 This call creates a FIFO (named pipe) called C<path> with
3097 mode C<mode>. It is just a convenient wrapper around
3100 The mode actually set is affected by the umask.");
3102 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3103 [InitBasicFS, Always, TestOutputStruct (
3104 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3105 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3106 "make block device node",
3108 This call creates a block device node called C<path> with
3109 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3110 It is just a convenient wrapper around C<guestfs_mknod>.
3112 The mode actually set is affected by the umask.");
3114 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3115 [InitBasicFS, Always, TestOutputStruct (
3116 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3117 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3118 "make char device node",
3120 This call creates a char device node called C<path> with
3121 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3122 It is just a convenient wrapper around C<guestfs_mknod>.
3124 The mode actually set is affected by the umask.");
3126 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3127 [InitEmpty, Always, TestOutputInt (
3128 [["umask"; "0o22"]], 0o22)],
3129 "set file mode creation mask (umask)",
3131 This function sets the mask used for creating new files and
3132 device nodes to C<mask & 0777>.
3134 Typical umask values would be C<022> which creates new files
3135 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3136 C<002> which creates new files with permissions like
3137 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3139 The default umask is C<022>. This is important because it
3140 means that directories and device nodes will be created with
3141 C<0644> or C<0755> mode even if you specify C<0777>.
3143 See also C<guestfs_get_umask>,
3144 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3146 This call returns the previous umask.");
3148 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3150 "read directories entries",
3152 This returns the list of directory entries in directory C<dir>.
3154 All entries in the directory are returned, including C<.> and
3155 C<..>. The entries are I<not> sorted, but returned in the same
3156 order as the underlying filesystem.
3158 Also this call returns basic file type information about each
3159 file. The C<ftyp> field will contain one of the following characters:
3197 The L<readdir(3)> call returned a C<d_type> field with an
3202 This function is primarily intended for use by programs. To
3203 get a simple list of names, use C<guestfs_ls>. To get a printable
3204 directory for human consumption, use C<guestfs_ll>.");
3206 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3208 "create partitions on a block device",
3210 This is a simplified interface to the C<guestfs_sfdisk>
3211 command, where partition sizes are specified in megabytes
3212 only (rounded to the nearest cylinder) and you don't need
3213 to specify the cyls, heads and sectors parameters which
3214 were rarely if ever used anyway.
3216 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3217 and C<guestfs_part_disk>");
3219 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3221 "determine file type inside a compressed file",
3223 This command runs C<file> after first decompressing C<path>
3226 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3228 Since 1.0.63, use C<guestfs_file> instead which can now
3229 process compressed files.");
3231 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3233 "list extended attributes of a file or directory",
3235 This call lists the extended attributes of the file or directory
3238 At the system call level, this is a combination of the
3239 L<listxattr(2)> and L<getxattr(2)> calls.
3241 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3243 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3245 "list extended attributes of a file or directory",
3247 This is the same as C<guestfs_getxattrs>, but if C<path>
3248 is a symbolic link, then it returns the extended attributes
3249 of the link itself.");
3251 ("setxattr", (RErr, [String "xattr";
3252 String "val"; Int "vallen"; (* will be BufferIn *)
3253 Pathname "path"]), 143, [Optional "linuxxattrs"],
3255 "set extended attribute of a file or directory",
3257 This call sets the extended attribute named C<xattr>
3258 of the file C<path> to the value C<val> (of length C<vallen>).
3259 The value is arbitrary 8 bit data.
3261 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3263 ("lsetxattr", (RErr, [String "xattr";
3264 String "val"; Int "vallen"; (* will be BufferIn *)
3265 Pathname "path"]), 144, [Optional "linuxxattrs"],
3267 "set extended attribute of a file or directory",
3269 This is the same as C<guestfs_setxattr>, but if C<path>
3270 is a symbolic link, then it sets an extended attribute
3271 of the link itself.");
3273 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3275 "remove extended attribute of a file or directory",
3277 This call removes the extended attribute named C<xattr>
3278 of the file C<path>.
3280 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3282 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3284 "remove extended attribute of a file or directory",
3286 This is the same as C<guestfs_removexattr>, but if C<path>
3287 is a symbolic link, then it removes an extended attribute
3288 of the link itself.");
3290 ("mountpoints", (RHashtable "mps", []), 147, [],
3294 This call is similar to C<guestfs_mounts>. That call returns
3295 a list of devices. This one returns a hash table (map) of
3296 device name to directory where the device is mounted.");
3298 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3299 (* This is a special case: while you would expect a parameter
3300 * of type "Pathname", that doesn't work, because it implies
3301 * NEED_ROOT in the generated calling code in stubs.c, and
3302 * this function cannot use NEED_ROOT.
3305 "create a mountpoint",
3307 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3308 specialized calls that can be used to create extra mountpoints
3309 before mounting the first filesystem.
3311 These calls are I<only> necessary in some very limited circumstances,
3312 mainly the case where you want to mount a mix of unrelated and/or
3313 read-only filesystems together.
3315 For example, live CDs often contain a \"Russian doll\" nest of
3316 filesystems, an ISO outer layer, with a squashfs image inside, with
3317 an ext2/3 image inside that. You can unpack this as follows
3320 add-ro Fedora-11-i686-Live.iso
3323 mkmountpoint /squash
3326 mount-loop /cd/LiveOS/squashfs.img /squash
3327 mount-loop /squash/LiveOS/ext3fs.img /ext3
3329 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3331 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3333 "remove a mountpoint",
3335 This calls removes a mountpoint that was previously created
3336 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3337 for full details.");
3339 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3340 [InitISOFS, Always, TestOutputBuffer (
3341 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3342 (* Test various near large, large and too large files (RHBZ#589039). *)
3343 InitBasicFS, Always, TestLastFail (
3345 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3346 ["read_file"; "/a"]]);
3347 InitBasicFS, Always, TestLastFail (
3349 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3350 ["read_file"; "/a"]]);
3351 InitBasicFS, Always, TestLastFail (
3353 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3354 ["read_file"; "/a"]])],
3357 This calls returns the contents of the file C<path> as a
3360 Unlike C<guestfs_cat>, this function can correctly
3361 handle files that contain embedded ASCII NUL characters.
3362 However unlike C<guestfs_download>, this function is limited
3363 in the total size of file that can be handled.");
3365 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3366 [InitISOFS, Always, TestOutputList (
3367 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3368 InitISOFS, Always, TestOutputList (
3369 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3370 (* Test for RHBZ#579608, absolute symbolic links. *)
3371 InitISOFS, Always, TestOutputList (
3372 [["grep"; "nomatch"; "/abssymlink"]], [])],
3373 "return lines matching a pattern",
3375 This calls the external C<grep> program and returns the
3378 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3379 [InitISOFS, Always, TestOutputList (
3380 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3381 "return lines matching a pattern",
3383 This calls the external C<egrep> program and returns the
3386 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3387 [InitISOFS, Always, TestOutputList (
3388 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389 "return lines matching a pattern",
3391 This calls the external C<fgrep> program and returns the
3394 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3395 [InitISOFS, Always, TestOutputList (
3396 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3397 "return lines matching a pattern",
3399 This calls the external C<grep -i> program and returns the
3402 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3403 [InitISOFS, Always, TestOutputList (
3404 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405 "return lines matching a pattern",
3407 This calls the external C<egrep -i> program and returns the
3410 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3411 [InitISOFS, Always, TestOutputList (
3412 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413 "return lines matching a pattern",
3415 This calls the external C<fgrep -i> program and returns the
3418 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3419 [InitISOFS, Always, TestOutputList (
3420 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3421 "return lines matching a pattern",
3423 This calls the external C<zgrep> program and returns the
3426 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3427 [InitISOFS, Always, TestOutputList (
3428 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429 "return lines matching a pattern",
3431 This calls the external C<zegrep> program and returns the
3434 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3435 [InitISOFS, Always, TestOutputList (
3436 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437 "return lines matching a pattern",
3439 This calls the external C<zfgrep> program and returns the
3442 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3443 [InitISOFS, Always, TestOutputList (
3444 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3445 "return lines matching a pattern",
3447 This calls the external C<zgrep -i> program and returns the
3450 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3451 [InitISOFS, Always, TestOutputList (
3452 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453 "return lines matching a pattern",
3455 This calls the external C<zegrep -i> program and returns the
3458 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3459 [InitISOFS, Always, TestOutputList (
3460 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461 "return lines matching a pattern",
3463 This calls the external C<zfgrep -i> program and returns the
3466 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3467 [InitISOFS, Always, TestOutput (
3468 [["realpath"; "/../directory"]], "/directory")],
3469 "canonicalized absolute pathname",
3471 Return the canonicalized absolute pathname of C<path>. The
3472 returned path has no C<.>, C<..> or symbolic link path elements.");
3474 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3475 [InitBasicFS, Always, TestOutputStruct (
3478 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3479 "create a hard link",
3481 This command creates a hard link using the C<ln> command.");
3483 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3484 [InitBasicFS, Always, TestOutputStruct (
3487 ["ln_f"; "/a"; "/b"];
3488 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3489 "create a hard link",
3491 This command creates a hard link using the C<ln -f> command.
3492 The C<-f> option removes the link (C<linkname>) if it exists already.");
3494 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3495 [InitBasicFS, Always, TestOutputStruct (
3497 ["ln_s"; "a"; "/b"];
3498 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3499 "create a symbolic link",
3501 This command creates a symbolic link using the C<ln -s> command.");
3503 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3504 [InitBasicFS, Always, TestOutput (
3505 [["mkdir_p"; "/a/b"];
3506 ["touch"; "/a/b/c"];
3507 ["ln_sf"; "../d"; "/a/b/c"];
3508 ["readlink"; "/a/b/c"]], "../d")],
3509 "create a symbolic link",
3511 This command creates a symbolic link using the C<ln -sf> command,
3512 The C<-f> option removes the link (C<linkname>) if it exists already.");
3514 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3515 [] (* XXX tested above *),
3516 "read the target of a symbolic link",
3518 This command reads the target of a symbolic link.");
3520 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3521 [InitBasicFS, Always, TestOutputStruct (
3522 [["fallocate"; "/a"; "1000000"];
3523 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3524 "preallocate a file in the guest filesystem",
3526 This command preallocates a file (containing zero bytes) named
3527 C<path> of size C<len> bytes. If the file exists already, it
3530 Do not confuse this with the guestfish-specific
3531 C<alloc> command which allocates a file in the host and
3532 attaches it as a device.");
3534 ("swapon_device", (RErr, [Device "device"]), 170, [],
3535 [InitPartition, Always, TestRun (
3536 [["mkswap"; "/dev/sda1"];
3537 ["swapon_device"; "/dev/sda1"];
3538 ["swapoff_device"; "/dev/sda1"]])],
3539 "enable swap on device",
3541 This command enables the libguestfs appliance to use the
3542 swap device or partition named C<device>. The increased
3543 memory is made available for all commands, for example
3544 those run using C<guestfs_command> or C<guestfs_sh>.
3546 Note that you should not swap to existing guest swap
3547 partitions unless you know what you are doing. They may
3548 contain hibernation information, or other information that
3549 the guest doesn't want you to trash. You also risk leaking
3550 information about the host to the guest this way. Instead,
3551 attach a new host device to the guest and swap on that.");
3553 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3554 [], (* XXX tested by swapon_device *)
3555 "disable swap on device",
3557 This command disables the libguestfs appliance swap
3558 device or partition named C<device>.
3559 See C<guestfs_swapon_device>.");
3561 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3562 [InitBasicFS, Always, TestRun (
3563 [["fallocate"; "/swap"; "8388608"];
3564 ["mkswap_file"; "/swap"];
3565 ["swapon_file"; "/swap"];
3566 ["swapoff_file"; "/swap"]])],
3567 "enable swap on file",
3569 This command enables swap to a file.
3570 See C<guestfs_swapon_device> for other notes.");
3572 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3573 [], (* XXX tested by swapon_file *)
3574 "disable swap on file",
3576 This command disables the libguestfs appliance swap on file.");
3578 ("swapon_label", (RErr, [String "label"]), 174, [],
3579 [InitEmpty, Always, TestRun (
3580 [["part_disk"; "/dev/sdb"; "mbr"];
3581 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3582 ["swapon_label"; "swapit"];
3583 ["swapoff_label"; "swapit"];
3584 ["zero"; "/dev/sdb"];
3585 ["blockdev_rereadpt"; "/dev/sdb"]])],
3586 "enable swap on labeled swap partition",
3588 This command enables swap to a labeled swap partition.
3589 See C<guestfs_swapon_device> for other notes.");
3591 ("swapoff_label", (RErr, [String "label"]), 175, [],
3592 [], (* XXX tested by swapon_label *)
3593 "disable swap on labeled swap partition",
3595 This command disables the libguestfs appliance swap on
3596 labeled swap partition.");
3598 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3599 (let uuid = uuidgen () in
3600 [InitEmpty, Always, TestRun (
3601 [["mkswap_U"; uuid; "/dev/sdb"];
3602 ["swapon_uuid"; uuid];
3603 ["swapoff_uuid"; uuid]])]),
3604 "enable swap on swap partition by UUID",
3606 This command enables swap to a swap partition with the given UUID.
3607 See C<guestfs_swapon_device> for other notes.");
3609 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3610 [], (* XXX tested by swapon_uuid *)
3611 "disable swap on swap partition by UUID",
3613 This command disables the libguestfs appliance swap partition
3614 with the given UUID.");
3616 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3617 [InitBasicFS, Always, TestRun (
3618 [["fallocate"; "/swap"; "8388608"];
3619 ["mkswap_file"; "/swap"]])],
3620 "create a swap file",
3624 This command just writes a swap file signature to an existing
3625 file. To create the file itself, use something like C<guestfs_fallocate>.");
3627 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3628 [InitISOFS, Always, TestRun (
3629 [["inotify_init"; "0"]])],
3630 "create an inotify handle",
3632 This command creates a new inotify handle.
3633 The inotify subsystem can be used to notify events which happen to
3634 objects in the guest filesystem.
3636 C<maxevents> is the maximum number of events which will be
3637 queued up between calls to C<guestfs_inotify_read> or
3638 C<guestfs_inotify_files>.
3639 If this is passed as C<0>, then the kernel (or previously set)
3640 default is used. For Linux 2.6.29 the default was 16384 events.
3641 Beyond this limit, the kernel throws away events, but records
3642 the fact that it threw them away by setting a flag
3643 C<IN_Q_OVERFLOW> in the returned structure list (see
3644 C<guestfs_inotify_read>).
3646 Before any events are generated, you have to add some
3647 watches to the internal watch list. See:
3648 C<guestfs_inotify_add_watch>,
3649 C<guestfs_inotify_rm_watch> and
3650 C<guestfs_inotify_watch_all>.
3652 Queued up events should be read periodically by calling
3653 C<guestfs_inotify_read>
3654 (or C<guestfs_inotify_files> which is just a helpful
3655 wrapper around C<guestfs_inotify_read>). If you don't
3656 read the events out often enough then you risk the internal
3659 The handle should be closed after use by calling
3660 C<guestfs_inotify_close>. This also removes any
3661 watches automatically.
3663 See also L<inotify(7)> for an overview of the inotify interface
3664 as exposed by the Linux kernel, which is roughly what we expose
3665 via libguestfs. Note that there is one global inotify handle
3666 per libguestfs instance.");
3668 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3669 [InitBasicFS, Always, TestOutputList (
3670 [["inotify_init"; "0"];
3671 ["inotify_add_watch"; "/"; "1073741823"];
3674 ["inotify_files"]], ["a"; "b"])],
3675 "add an inotify watch",
3677 Watch C<path> for the events listed in C<mask>.
3679 Note that if C<path> is a directory then events within that
3680 directory are watched, but this does I<not> happen recursively
3681 (in subdirectories).
3683 Note for non-C or non-Linux callers: the inotify events are
3684 defined by the Linux kernel ABI and are listed in
3685 C</usr/include/sys/inotify.h>.");
3687 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3689 "remove an inotify watch",
3691 Remove a previously defined inotify watch.
3692 See C<guestfs_inotify_add_watch>.");
3694 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3696 "return list of inotify events",
3698 Return the complete queue of events that have happened
3699 since the previous read call.
3701 If no events have happened, this returns an empty list.
3703 I<Note>: In order to make sure that all events have been
3704 read, you must call this function repeatedly until it
3705 returns an empty list. The reason is that the call will
3706 read events up to the maximum appliance-to-host message
3707 size and leave remaining events in the queue.");
3709 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3711 "return list of watched files that had events",
3713 This function is a helpful wrapper around C<guestfs_inotify_read>
3714 which just returns a list of pathnames of objects that were
3715 touched. The returned pathnames are sorted and deduplicated.");
3717 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3719 "close the inotify handle",
3721 This closes the inotify handle which was previously
3722 opened by inotify_init. It removes all watches, throws
3723 away any pending events, and deallocates all resources.");
3725 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3727 "set SELinux security context",
3729 This sets the SELinux security context of the daemon
3730 to the string C<context>.
3732 See the documentation about SELINUX in L<guestfs(3)>.");
3734 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3736 "get SELinux security context",
3738 This gets the SELinux security context of the daemon.
3740 See the documentation about SELINUX in L<guestfs(3)>,
3741 and C<guestfs_setcon>");
3743 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3744 [InitEmpty, Always, TestOutput (
3745 [["part_disk"; "/dev/sda"; "mbr"];
3746 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3747 ["mount_options"; ""; "/dev/sda1"; "/"];
3748 ["write"; "/new"; "new file contents"];
3749 ["cat"; "/new"]], "new file contents");
3750 InitEmpty, Always, TestRun (
3751 [["part_disk"; "/dev/sda"; "mbr"];
3752 ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3753 InitEmpty, Always, TestLastFail (
3754 [["part_disk"; "/dev/sda"; "mbr"];
3755 ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3756 InitEmpty, Always, TestLastFail (
3757 [["part_disk"; "/dev/sda"; "mbr"];
3758 ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3759 InitEmpty, IfAvailable "ntfsprogs", TestRun (
3760 [["part_disk"; "/dev/sda"; "mbr"];
3761 ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3762 "make a filesystem with block size",
3764 This call is similar to C<guestfs_mkfs>, but it allows you to
3765 control the block size of the resulting filesystem. Supported
3766 block sizes depend on the filesystem type, but typically they
3767 are C<1024>, C<2048> or C<4096> only.
3769 For VFAT and NTFS the C<blocksize> parameter is treated as
3770 the requested cluster size.");
3772 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3773 [InitEmpty, Always, TestOutput (
3774 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3775 ["mke2journal"; "4096"; "/dev/sda1"];
3776 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3777 ["mount_options"; ""; "/dev/sda2"; "/"];
3778 ["write"; "/new"; "new file contents"];
3779 ["cat"; "/new"]], "new file contents")],
3780 "make ext2/3/4 external journal",
3782 This creates an ext2 external journal on C<device>. It is equivalent
3785 mke2fs -O journal_dev -b blocksize device");
3787 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3788 [InitEmpty, Always, TestOutput (
3789 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3790 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3791 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3792 ["mount_options"; ""; "/dev/sda2"; "/"];
3793 ["write"; "/new"; "new file contents"];
3794 ["cat"; "/new"]], "new file contents")],
3795 "make ext2/3/4 external journal with label",
3797 This creates an ext2 external journal on C<device> with label C<label>.");
3799 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3800 (let uuid = uuidgen () in
3801 [InitEmpty, Always, TestOutput (
3802 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3803 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3804 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3805 ["mount_options"; ""; "/dev/sda2"; "/"];
3806 ["write"; "/new"; "new file contents"];
3807 ["cat"; "/new"]], "new file contents")]),
3808 "make ext2/3/4 external journal with UUID",
3810 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3812 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3814 "make ext2/3/4 filesystem with external journal",
3816 This creates an ext2/3/4 filesystem on C<device> with
3817 an external journal on C<journal>. It is equivalent
3820 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3822 See also C<guestfs_mke2journal>.");
3824 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3826 "make ext2/3/4 filesystem with external journal",
3828 This creates an ext2/3/4 filesystem on C<device> with
3829 an external journal on the journal labeled C<label>.
3831 See also C<guestfs_mke2journal_L>.");
3833 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3835 "make ext2/3/4 filesystem with external journal",
3837 This creates an ext2/3/4 filesystem on C<device> with
3838 an external journal on the journal with UUID C<uuid>.
3840 See also C<guestfs_mke2journal_U>.");
3842 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3843 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3844 "load a kernel module",
3846 This loads a kernel module in the appliance.
3848 The kernel module must have been whitelisted when libguestfs
3849 was built (see C<appliance/kmod.whitelist.in> in the source).");
3851 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3852 [InitNone, Always, TestOutput (
3853 [["echo_daemon"; "This is a test"]], "This is a test"
3855 "echo arguments back to the client",
3857 This command concatenates the list of C<words> passed with single spaces
3858 between them and returns the resulting string.
3860 You can use this command to test the connection through to the daemon.
3862 See also C<guestfs_ping_daemon>.");
3864 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3865 [], (* There is a regression test for this. *)
3866 "find all files and directories, returning NUL-separated list",
3868 This command lists out all files and directories, recursively,
3869 starting at C<directory>, placing the resulting list in the
3870 external file called C<files>.
3872 This command works the same way as C<guestfs_find> with the
3873 following exceptions:
3879 The resulting list is written to an external file.
3883 Items (filenames) in the result are separated
3884 by C<\\0> characters. See L<find(1)> option I<-print0>.
3888 This command is not limited in the number of names that it
3893 The result list is not sorted.
3897 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3898 [InitISOFS, Always, TestOutput (
3899 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3900 InitISOFS, Always, TestOutput (
3901 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3902 InitISOFS, Always, TestOutput (
3903 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3904 InitISOFS, Always, TestLastFail (
3905 [["case_sensitive_path"; "/Known-1/"]]);
3906 InitBasicFS, Always, TestOutput (
3908 ["mkdir"; "/a/bbb"];
3909 ["touch"; "/a/bbb/c"];
3910 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3911 InitBasicFS, Always, TestOutput (
3913 ["mkdir"; "/a/bbb"];
3914 ["touch"; "/a/bbb/c"];
3915 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3916 InitBasicFS, Always, TestLastFail (
3918 ["mkdir"; "/a/bbb"];
3919 ["touch"; "/a/bbb/c"];
3920 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3921 "return true path on case-insensitive filesystem",
3923 This can be used to resolve case insensitive paths on
3924 a filesystem which is case sensitive. The use case is
3925 to resolve paths which you have read from Windows configuration
3926 files or the Windows Registry, to the true path.
3928 The command handles a peculiarity of the Linux ntfs-3g
3929 filesystem driver (and probably others), which is that although
3930 the underlying filesystem is case-insensitive, the driver
3931 exports the filesystem to Linux as case-sensitive.
3933 One consequence of this is that special directories such
3934 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3935 (or other things) depending on the precise details of how
3936 they were created. In Windows itself this would not be
3939 Bug or feature? You decide:
3940 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3942 This function resolves the true case of each element in the
3943 path and returns the case-sensitive path.
3945 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3946 might return C<\"/WINDOWS/system32\"> (the exact return value
3947 would depend on details of how the directories were originally
3948 created under Windows).
3951 This function does not handle drive names, backslashes etc.
3953 See also C<guestfs_realpath>.");
3955 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3956 [InitBasicFS, Always, TestOutput (
3957 [["vfs_type"; "/dev/sda1"]], "ext2")],
3958 "get the Linux VFS type corresponding to a mounted device",
3960 This command gets the filesystem type corresponding to
3961 the filesystem on C<device>.
3963 For most filesystems, the result is the name of the Linux
3964 VFS module which would be used to mount this filesystem
3965 if you mounted it without specifying the filesystem type.
3966 For example a string such as C<ext3> or C<ntfs>.");
3968 ("truncate", (RErr, [Pathname "path"]), 199, [],
3969 [InitBasicFS, Always, TestOutputStruct (
3970 [["write"; "/test"; "some stuff so size is not zero"];
3971 ["truncate"; "/test"];
3972 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3973 "truncate a file to zero size",
3975 This command truncates C<path> to a zero-length file. The
3976 file must exist already.");
3978 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3979 [InitBasicFS, Always, TestOutputStruct (
3980 [["touch"; "/test"];
3981 ["truncate_size"; "/test"; "1000"];
3982 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3983 "truncate a file to a particular size",
3985 This command truncates C<path> to size C<size> bytes. The file
3988 If the current file size is less than C<size> then
3989 the file is extended to the required size with zero bytes.
3990 This creates a sparse file (ie. disk blocks are not allocated
3991 for the file until you write to it). To create a non-sparse
3992 file of zeroes, use C<guestfs_fallocate64> instead.");
3994 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3995 [InitBasicFS, Always, TestOutputStruct (
3996 [["touch"; "/test"];
3997 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3998 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3999 "set timestamp of a file with nanosecond precision",
4001 This command sets the timestamps of a file with nanosecond
4004 C<atsecs, atnsecs> are the last access time (atime) in secs and
4005 nanoseconds from the epoch.
4007 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4008 secs and nanoseconds from the epoch.
4010 If the C<*nsecs> field contains the special value C<-1> then
4011 the corresponding timestamp is set to the current time. (The
4012 C<*secs> field is ignored in this case).
4014 If the C<*nsecs> field contains the special value C<-2> then
4015 the corresponding timestamp is left unchanged. (The
4016 C<*secs> field is ignored in this case).");
4018 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4019 [InitBasicFS, Always, TestOutputStruct (
4020 [["mkdir_mode"; "/test"; "0o111"];
4021 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4022 "create a directory with a particular mode",
4024 This command creates a directory, setting the initial permissions
4025 of the directory to C<mode>.
4027 For common Linux filesystems, the actual mode which is set will
4028 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
4029 interpret the mode in other ways.
4031 See also C<guestfs_mkdir>, C<guestfs_umask>");
4033 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4035 "change file owner and group",
4037 Change the file owner to C<owner> and group to C<group>.
4038 This is like C<guestfs_chown> but if C<path> is a symlink then
4039 the link itself is changed, not the target.
4041 Only numeric uid and gid are supported. If you want to use
4042 names, you will need to locate and parse the password file
4043 yourself (Augeas support makes this relatively easy).");
4045 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4047 "lstat on multiple files",
4049 This call allows you to perform the C<guestfs_lstat> operation
4050 on multiple files, where all files are in the directory C<path>.
4051 C<names> is the list of files from this directory.
4053 On return you get a list of stat structs, with a one-to-one
4054 correspondence to the C<names> list. If any name did not exist
4055 or could not be lstat'd, then the C<ino> field of that structure
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 See also C<guestfs_lxattrlist> for a similarly efficient call
4061 for getting extended attributes. Very long directory listings
4062 might cause the protocol message size to be exceeded, causing
4063 this call to fail. The caller must split up such requests
4064 into smaller groups of names.");
4066 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4068 "lgetxattr on multiple files",
4070 This call allows you to get the extended attributes
4071 of multiple files, where all files are in the directory C<path>.
4072 C<names> is the list of files from this directory.
4074 On return you get a flat list of xattr structs which must be
4075 interpreted sequentially. The first xattr struct always has a zero-length
4076 C<attrname>. C<attrval> in this struct is zero-length
4077 to indicate there was an error doing C<lgetxattr> for this
4078 file, I<or> is a C string which is a decimal number
4079 (the number of following attributes for this file, which could
4080 be C<\"0\">). Then after the first xattr struct are the
4081 zero or more attributes for the first named file.
4082 This repeats for the second and subsequent files.
4084 This call is intended for programs that want to efficiently
4085 list a directory contents without making many round-trips.
4086 See also C<guestfs_lstatlist> for a similarly efficient call
4087 for getting standard stats. Very long directory listings
4088 might cause the protocol message size to be exceeded, causing
4089 this call to fail. The caller must split up such requests
4090 into smaller groups of names.");
4092 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4094 "readlink on multiple files",
4096 This call allows you to do a C<readlink> operation
4097 on multiple files, where all files are in the directory C<path>.
4098 C<names> is the list of files from this directory.
4100 On return you get a list of strings, with a one-to-one
4101 correspondence to the C<names> list. Each string is the
4102 value of the symbolic link.
4104 If the C<readlink(2)> operation fails on any name, then
4105 the corresponding result string is the empty string C<\"\">.
4106 However the whole operation is completed even if there
4107 were C<readlink(2)> errors, and so you can call this
4108 function with names where you don't know if they are
4109 symbolic links already (albeit slightly less efficient).
4111 This call is intended for programs that want to efficiently
4112 list a directory contents without making many round-trips.
4113 Very long directory listings might cause the protocol
4114 message size to be exceeded, causing
4115 this call to fail. The caller must split up such requests
4116 into smaller groups of names.");
4118 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4119 [InitISOFS, Always, TestOutputBuffer (
4120 [["pread"; "/known-4"; "1"; "3"]], "\n");
4121 InitISOFS, Always, TestOutputBuffer (
4122 [["pread"; "/empty"; "0"; "100"]], "")],
4123 "read part of a file",
4125 This command lets you read part of a file. It reads C<count>
4126 bytes of the file, starting at C<offset>, from file C<path>.
4128 This may read fewer bytes than requested. For further details
4129 see the L<pread(2)> system call.
4131 See also C<guestfs_pwrite>.");
4133 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4134 [InitEmpty, Always, TestRun (
4135 [["part_init"; "/dev/sda"; "gpt"]])],
4136 "create an empty partition table",
4138 This creates an empty partition table on C<device> of one of the
4139 partition types listed below. Usually C<parttype> should be
4140 either C<msdos> or C<gpt> (for large disks).
4142 Initially there are no partitions. Following this, you should
4143 call C<guestfs_part_add> for each partition required.
4145 Possible values for C<parttype> are:
4149 =item B<efi> | B<gpt>
4151 Intel EFI / GPT partition table.
4153 This is recommended for >= 2 TB partitions that will be accessed
4154 from Linux and Intel-based Mac OS X. It also has limited backwards
4155 compatibility with the C<mbr> format.
4157 =item B<mbr> | B<msdos>
4159 The standard PC \"Master Boot Record\" (MBR) format used
4160 by MS-DOS and Windows. This partition type will B<only> work
4161 for device sizes up to 2 TB. For large disks we recommend
4166 Other partition table types that may work but are not
4175 =item B<amiga> | B<rdb>
4177 Amiga \"Rigid Disk Block\" format.
4185 DASD, used on IBM mainframes.
4193 Old Mac partition format. Modern Macs use C<gpt>.
4197 NEC PC-98 format, common in Japan apparently.
4205 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4206 [InitEmpty, Always, TestRun (
4207 [["part_init"; "/dev/sda"; "mbr"];
4208 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4209 InitEmpty, Always, TestRun (
4210 [["part_init"; "/dev/sda"; "gpt"];
4211 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4212 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4213 InitEmpty, Always, TestRun (
4214 [["part_init"; "/dev/sda"; "mbr"];
4215 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4216 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4217 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4218 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4219 "add a partition to the device",
4221 This command adds a partition to C<device>. If there is no partition
4222 table on the device, call C<guestfs_part_init> first.
4224 The C<prlogex> parameter is the type of partition. Normally you
4225 should pass C<p> or C<primary> here, but MBR partition tables also
4226 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4229 C<startsect> and C<endsect> are the start and end of the partition
4230 in I<sectors>. C<endsect> may be negative, which means it counts
4231 backwards from the end of the disk (C<-1> is the last sector).
4233 Creating a partition which covers the whole disk is not so easy.
4234 Use C<guestfs_part_disk> to do that.");
4236 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4237 [InitEmpty, Always, TestRun (
4238 [["part_disk"; "/dev/sda"; "mbr"]]);
4239 InitEmpty, Always, TestRun (
4240 [["part_disk"; "/dev/sda"; "gpt"]])],
4241 "partition whole disk with a single primary partition",
4243 This command is simply a combination of C<guestfs_part_init>
4244 followed by C<guestfs_part_add> to create a single primary partition
4245 covering the whole disk.
4247 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4248 but other possible values are described in C<guestfs_part_init>.");
4250 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4251 [InitEmpty, Always, TestRun (
4252 [["part_disk"; "/dev/sda"; "mbr"];
4253 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4254 "make a partition bootable",
4256 This sets the bootable flag on partition numbered C<partnum> on
4257 device C<device>. Note that partitions are numbered from 1.
4259 The bootable flag is used by some operating systems (notably
4260 Windows) to determine which partition to boot from. It is by
4261 no means universally recognized.");
4263 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4264 [InitEmpty, Always, TestRun (
4265 [["part_disk"; "/dev/sda"; "gpt"];
4266 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4267 "set partition name",
4269 This sets the partition name on partition numbered C<partnum> on
4270 device C<device>. Note that partitions are numbered from 1.
4272 The partition name can only be set on certain types of partition
4273 table. This works on C<gpt> but not on C<mbr> partitions.");
4275 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4276 [], (* XXX Add a regression test for this. *)
4277 "list partitions on a device",
4279 This command parses the partition table on C<device> and
4280 returns the list of partitions found.
4282 The fields in the returned structure are:
4288 Partition number, counting from 1.
4292 Start of the partition I<in bytes>. To get sectors you have to
4293 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4297 End of the partition in bytes.
4301 Size of the partition in bytes.
4305 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4306 [InitEmpty, Always, TestOutput (
4307 [["part_disk"; "/dev/sda"; "gpt"];
4308 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4309 "get the partition table type",
4311 This command examines the partition table on C<device> and
4312 returns the partition table type (format) being used.
4314 Common return values include: C<msdos> (a DOS/Windows style MBR
4315 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4316 values are possible, although unusual. See C<guestfs_part_init>
4319 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4320 [InitBasicFS, Always, TestOutputBuffer (
4321 [["fill"; "0x63"; "10"; "/test"];
4322 ["read_file"; "/test"]], "cccccccccc")],
4323 "fill a file with octets",
4325 This command creates a new file called C<path>. The initial
4326 content of the file is C<len> octets of C<c>, where C<c>
4327 must be a number in the range C<[0..255]>.
4329 To fill a file with zero bytes (sparsely), it is
4330 much more efficient to use C<guestfs_truncate_size>.
4331 To create a file with a pattern of repeating bytes
4332 use C<guestfs_fill_pattern>.");
4334 ("available", (RErr, [StringList "groups"]), 216, [],
4335 [InitNone, Always, TestRun [["available"; ""]]],
4336 "test availability of some parts of the API",
4338 This command is used to check the availability of some
4339 groups of functionality in the appliance, which not all builds of
4340 the libguestfs appliance will be able to provide.
4342 The libguestfs groups, and the functions that those
4343 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4344 You can also fetch this list at runtime by calling
4345 C<guestfs_available_all_groups>.
4347 The argument C<groups> is a list of group names, eg:
4348 C<[\"inotify\", \"augeas\"]> would check for the availability of
4349 the Linux inotify functions and Augeas (configuration file
4352 The command returns no error if I<all> requested groups are available.
4354 It fails with an error if one or more of the requested
4355 groups is unavailable in the appliance.
4357 If an unknown group name is included in the
4358 list of groups then an error is always returned.
4366 You must call C<guestfs_launch> before calling this function.
4368 The reason is because we don't know what groups are
4369 supported by the appliance/daemon until it is running and can
4374 If a group of functions is available, this does not necessarily
4375 mean that they will work. You still have to check for errors
4376 when calling individual API functions even if they are
4381 It is usually the job of distro packagers to build
4382 complete functionality into the libguestfs appliance.
4383 Upstream libguestfs, if built from source with all
4384 requirements satisfied, will support everything.
4388 This call was added in version C<1.0.80>. In previous
4389 versions of libguestfs all you could do would be to speculatively
4390 execute a command to find out if the daemon implemented it.
4391 See also C<guestfs_version>.
4395 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4396 [InitBasicFS, Always, TestOutputBuffer (
4397 [["write"; "/src"; "hello, world"];
4398 ["dd"; "/src"; "/dest"];
4399 ["read_file"; "/dest"]], "hello, world")],
4400 "copy from source to destination using dd",
4402 This command copies from one source device or file C<src>
4403 to another destination device or file C<dest>. Normally you
4404 would use this to copy to or from a device or partition, for
4405 example to duplicate a filesystem.
4407 If the destination is a device, it must be as large or larger
4408 than the source file or device, otherwise the copy will fail.
4409 This command cannot do partial copies (see C<guestfs_copy_size>).");
4411 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4412 [InitBasicFS, Always, TestOutputInt (
4413 [["write"; "/file"; "hello, world"];
4414 ["filesize"; "/file"]], 12)],
4415 "return the size of the file in bytes",
4417 This command returns the size of C<file> in bytes.
4419 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4420 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4421 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4423 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4424 [InitBasicFSonLVM, Always, TestOutputList (
4425 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4426 ["lvs"]], ["/dev/VG/LV2"])],
4427 "rename an LVM logical volume",
4429 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4431 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4432 [InitBasicFSonLVM, Always, TestOutputList (
4434 ["vg_activate"; "false"; "VG"];
4435 ["vgrename"; "VG"; "VG2"];
4436 ["vg_activate"; "true"; "VG2"];
4437 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4438 ["vgs"]], ["VG2"])],
4439 "rename an LVM volume group",
4441 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4443 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4444 [InitISOFS, Always, TestOutputBuffer (
4445 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4446 "list the contents of a single file in an initrd",
4448 This command unpacks the file C<filename> from the initrd file
4449 called C<initrdpath>. The filename must be given I<without> the
4450 initial C</> character.
4452 For example, in guestfish you could use the following command
4453 to examine the boot script (usually called C</init>)
4454 contained in a Linux initrd or initramfs image:
4456 initrd-cat /boot/initrd-<version>.img init
4458 See also C<guestfs_initrd_list>.");
4460 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4462 "get the UUID of a physical volume",
4464 This command returns the UUID of the LVM PV C<device>.");
4466 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4468 "get the UUID of a volume group",
4470 This command returns the UUID of the LVM VG named C<vgname>.");
4472 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4474 "get the UUID of a logical volume",
4476 This command returns the UUID of the LVM LV C<device>.");
4478 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4480 "get the PV UUIDs containing the volume group",
4482 Given a VG called C<vgname>, this returns the UUIDs of all
4483 the physical volumes that this volume group resides on.
4485 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4486 calls to associate physical volumes and volume groups.
4488 See also C<guestfs_vglvuuids>.");
4490 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4492 "get the LV UUIDs of all LVs in the volume group",
4494 Given a VG called C<vgname>, this returns the UUIDs of all
4495 the logical volumes created in this volume group.
4497 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4498 calls to associate logical volumes and volume groups.
4500 See also C<guestfs_vgpvuuids>.");
4502 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4503 [InitBasicFS, Always, TestOutputBuffer (
4504 [["write"; "/src"; "hello, world"];
4505 ["copy_size"; "/src"; "/dest"; "5"];
4506 ["read_file"; "/dest"]], "hello")],
4507 "copy size bytes from source to destination using dd",
4509 This command copies exactly C<size> bytes from one source device
4510 or file C<src> to another destination device or file C<dest>.
4512 Note this will fail if the source is too short or if the destination
4513 is not large enough.");
4515 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4516 [InitBasicFSonLVM, Always, TestRun (
4517 [["zero_device"; "/dev/VG/LV"]])],
4518 "write zeroes to an entire device",
4520 This command writes zeroes over the entire C<device>. Compare
4521 with C<guestfs_zero> which just zeroes the first few blocks of
4524 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4525 [InitBasicFS, Always, TestOutput (
4526 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4527 ["cat"; "/hello"]], "hello\n")],
4528 "unpack compressed tarball to directory",
4530 This command uploads and unpacks local file C<tarball> (an
4531 I<xz compressed> tar file) into C<directory>.");
4533 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4535 "pack directory into compressed tarball",
4537 This command packs the contents of C<directory> and downloads
4538 it to local file C<tarball> (as an xz compressed tar archive).");
4540 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4542 "resize an NTFS filesystem",
4544 This command resizes an NTFS filesystem, expanding or
4545 shrinking it to the size of the underlying device.
4546 See also L<ntfsresize(8)>.");
4548 ("vgscan", (RErr, []), 232, [],
4549 [InitEmpty, Always, TestRun (
4551 "rescan for LVM physical volumes, volume groups and logical volumes",
4553 This rescans all block devices and rebuilds the list of LVM
4554 physical volumes, volume groups and logical volumes.");
4556 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4557 [InitEmpty, Always, TestRun (
4558 [["part_init"; "/dev/sda"; "mbr"];
4559 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4560 ["part_del"; "/dev/sda"; "1"]])],
4561 "delete a partition",
4563 This command deletes the partition numbered C<partnum> on C<device>.
4565 Note that in the case of MBR partitioning, deleting an
4566 extended partition also deletes any logical partitions
4569 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4570 [InitEmpty, Always, TestOutputTrue (
4571 [["part_init"; "/dev/sda"; "mbr"];
4572 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4573 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4574 ["part_get_bootable"; "/dev/sda"; "1"]])],
4575 "return true if a partition is bootable",
4577 This command returns true if the partition C<partnum> on
4578 C<device> has the bootable flag set.
4580 See also C<guestfs_part_set_bootable>.");
4582 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4583 [InitEmpty, Always, TestOutputInt (
4584 [["part_init"; "/dev/sda"; "mbr"];
4585 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4586 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4587 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4588 "get the MBR type byte (ID byte) from a partition",
4590 Returns the MBR type byte (also known as the ID byte) from
4591 the numbered partition C<partnum>.
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4597 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4598 [], (* tested by part_get_mbr_id *)
4599 "set the MBR type byte (ID byte) of a partition",
4601 Sets the MBR type byte (also known as the ID byte) of
4602 the numbered partition C<partnum> to C<idbyte>. Note
4603 that the type bytes quoted in most documentation are
4604 in fact hexadecimal numbers, but usually documented
4605 without any leading \"0x\" which might be confusing.
4607 Note that only MBR (old DOS-style) partitions have type bytes.
4608 You will get undefined results for other partition table
4609 types (see C<guestfs_part_get_parttype>).");
4611 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4612 [InitISOFS, Always, TestOutput (
4613 [["checksum_device"; "md5"; "/dev/sdd"]],
4614 (Digest.to_hex (Digest.file "images/test.iso")))],
4615 "compute MD5, SHAx or CRC checksum of the contents of a device",
4617 This call computes the MD5, SHAx or CRC checksum of the
4618 contents of the device named C<device>. For the types of
4619 checksums supported see the C<guestfs_checksum> command.");
4621 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4622 [InitNone, Always, TestRun (
4623 [["part_disk"; "/dev/sda"; "mbr"];
4624 ["pvcreate"; "/dev/sda1"];
4625 ["vgcreate"; "VG"; "/dev/sda1"];
4626 ["lvcreate"; "LV"; "VG"; "10"];
4627 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4628 "expand an LV to fill free space",
4630 This expands an existing logical volume C<lv> so that it fills
4631 C<pc>% of the remaining free space in the volume group. Commonly
4632 you would call this with pc = 100 which expands the logical volume
4633 as much as possible, using all remaining free space in the volume
4636 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4637 [], (* XXX Augeas code needs tests. *)
4638 "clear Augeas path",
4640 Set the value associated with C<path> to C<NULL>. This
4641 is the same as the L<augtool(1)> C<clear> command.");
4643 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4644 [InitEmpty, Always, TestOutputInt (
4645 [["get_umask"]], 0o22)],
4646 "get the current umask",
4648 Return the current umask. By default the umask is C<022>
4649 unless it has been set by calling C<guestfs_umask>.");
4651 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4653 "upload a file to the appliance (internal use only)",
4655 The C<guestfs_debug_upload> command uploads a file to
4656 the libguestfs appliance.
4658 There is no comprehensive help for this command. You have
4659 to look at the file C<daemon/debug.c> in the libguestfs source
4660 to find out what it is for.");
4662 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4663 [InitBasicFS, Always, TestOutput (
4664 [["base64_in"; "../images/hello.b64"; "/hello"];
4665 ["cat"; "/hello"]], "hello\n")],
4666 "upload base64-encoded data to file",
4668 This command uploads base64-encoded data from C<base64file>
4671 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4673 "download file and encode as base64",
4675 This command downloads the contents of C<filename>, writing
4676 it out to local file C<base64file> encoded as base64.");
4678 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4680 "compute MD5, SHAx or CRC checksum of files in a directory",
4682 This command computes the checksums of all regular files in
4683 C<directory> and then emits a list of those checksums to
4684 the local output file C<sumsfile>.
4686 This can be used for verifying the integrity of a virtual
4687 machine. However to be properly secure you should pay
4688 attention to the output of the checksum command (it uses
4689 the ones from GNU coreutils). In particular when the
4690 filename is not printable, coreutils uses a special
4691 backslash syntax. For more information, see the GNU
4692 coreutils info file.");
4694 ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4695 [InitBasicFS, Always, TestOutputBuffer (
4696 [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4697 ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4698 "fill a file with a repeating pattern of bytes",
4700 This function is like C<guestfs_fill> except that it creates
4701 a new file of length C<len> containing the repeating pattern
4702 of bytes in C<pattern>. The pattern is truncated if necessary
4703 to ensure the length of the file is exactly C<len> bytes.");
4705 ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4706 [InitBasicFS, Always, TestOutput (
4707 [["write"; "/new"; "new file contents"];
4708 ["cat"; "/new"]], "new file contents");
4709 InitBasicFS, Always, TestOutput (
4710 [["write"; "/new"; "\nnew file contents\n"];
4711 ["cat"; "/new"]], "\nnew file contents\n");
4712 InitBasicFS, Always, TestOutput (
4713 [["write"; "/new"; "\n\n"];
4714 ["cat"; "/new"]], "\n\n");
4715 InitBasicFS, Always, TestOutput (
4716 [["write"; "/new"; ""];
4717 ["cat"; "/new"]], "");
4718 InitBasicFS, Always, TestOutput (
4719 [["write"; "/new"; "\n\n\n"];
4720 ["cat"; "/new"]], "\n\n\n");
4721 InitBasicFS, Always, TestOutput (
4722 [["write"; "/new"; "\n"];
4723 ["cat"; "/new"]], "\n")],
4724 "create a new file",
4726 This call creates a file called C<path>. The content of the
4727 file is the string C<content> (which can contain any 8 bit data).");
4729 ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4730 [InitBasicFS, Always, TestOutput (
4731 [["write"; "/new"; "new file contents"];
4732 ["pwrite"; "/new"; "data"; "4"];
4733 ["cat"; "/new"]], "new data contents");
4734 InitBasicFS, Always, TestOutput (
4735 [["write"; "/new"; "new file contents"];
4736 ["pwrite"; "/new"; "is extended"; "9"];
4737 ["cat"; "/new"]], "new file is extended");
4738 InitBasicFS, Always, TestOutput (
4739 [["write"; "/new"; "new file contents"];
4740 ["pwrite"; "/new"; ""; "4"];
4741 ["cat"; "/new"]], "new file contents")],
4742 "write to part of a file",
4744 This command writes to part of a file. It writes the data
4745 buffer C<content> to the file C<path> starting at offset C<offset>.
4747 This command implements the L<pwrite(2)> system call, and like
4748 that system call it may not write the full data requested. The
4749 return value is the number of bytes that were actually written
4750 to the file. This could even be 0, although short writes are
4751 unlikely for regular files in ordinary circumstances.
4753 See also C<guestfs_pread>.");
4755 ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4757 "resize an ext2, ext3 or ext4 filesystem (with size)",
4759 This command is the same as C<guestfs_resize2fs> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4762 ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4764 "resize an LVM physical volume (with size)",
4766 This command is the same as C<guestfs_pvresize> except that it
4767 allows you to specify the new size (in bytes) explicitly.");
4769 ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4771 "resize an NTFS filesystem (with size)",
4773 This command is the same as C<guestfs_ntfsresize> except that it
4774 allows you to specify the new size (in bytes) explicitly.");
4776 ("available_all_groups", (RStringList "groups", []), 251, [],
4777 [InitNone, Always, TestRun [["available_all_groups"]]],
4778 "return a list of all optional groups",
4780 This command returns a list of all optional groups that this
4781 daemon knows about. Note this returns both supported and unsupported
4782 groups. To find out which ones the daemon can actually support
4783 you have to call C<guestfs_available> on each member of the
4786 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4788 ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4789 [InitBasicFS, Always, TestOutputStruct (
4790 [["fallocate64"; "/a"; "1000000"];
4791 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4792 "preallocate a file in the guest filesystem",
4794 This command preallocates a file (containing zero bytes) named
4795 C<path> of size C<len> bytes. If the file exists already, it
4798 Note that this call allocates disk blocks for the file.
4799 To create a sparse file use C<guestfs_truncate_size> instead.
4801 The deprecated call C<guestfs_fallocate> does the same,
4802 but owing to an oversight it only allowed 30 bit lengths
4803 to be specified, effectively limiting the maximum size
4804 of files created through that call to 1GB.
4806 Do not confuse this with the guestfish-specific
4807 C<alloc> and C<sparse> commands which create
4808 a file in the host and attach it as a device.");
4810 ("vfs_label", (RString "label", [Device "device"]), 253, [],
4811 [InitBasicFS, Always, TestOutput (
4812 [["set_e2label"; "/dev/sda1"; "LTEST"];
4813 ["vfs_label"; "/dev/sda1"]], "LTEST")],
4814 "get the filesystem label",
4816 This returns the filesystem label of the filesystem on
4819 If the filesystem is unlabeled, this returns the empty string.");
4821 ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4822 (let uuid = uuidgen () in
4823 [InitBasicFS, Always, TestOutput (
4824 [["set_e2uuid"; "/dev/sda1"; uuid];
4825 ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4826 "get the filesystem UUID",
4828 This returns the filesystem UUID of the filesystem on
4831 If the filesystem does not have a UUID, this returns the empty string.");
4835 let all_functions = non_daemon_functions @ daemon_functions
4837 (* In some places we want the functions to be displayed sorted
4838 * alphabetically, so this is useful:
4840 let all_functions_sorted =
4841 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4842 compare n1 n2) all_functions
4844 (* This is used to generate the src/MAX_PROC_NR file which
4845 * contains the maximum procedure number, a surrogate for the
4846 * ABI version number. See src/Makefile.am for the details.
4849 let proc_nrs = List.map (
4850 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4851 ) daemon_functions in
4852 List.fold_left max 0 proc_nrs
4854 (* Field types for structures. *)
4856 | FChar (* C 'char' (really, a 7 bit byte). *)
4857 | FString (* nul-terminated ASCII string, NOT NULL. *)
4858 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4863 | FBytes (* Any int measure that counts bytes. *)
4864 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4865 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4867 (* Because we generate extra parsing code for LVM command line tools,
4868 * we have to pull out the LVM columns separately here.
4878 "pv_attr", FString (* XXX *);
4879 "pv_pe_count", FInt64;
4880 "pv_pe_alloc_count", FInt64;
4883 "pv_mda_count", FInt64;
4884 "pv_mda_free", FBytes;
4885 (* Not in Fedora 10:
4886 "pv_mda_size", FBytes;
4893 "vg_attr", FString (* XXX *);
4896 "vg_sysid", FString;
4897 "vg_extent_size", FBytes;
4898 "vg_extent_count", FInt64;
4899 "vg_free_count", FInt64;
4904 "snap_count", FInt64;
4907 "vg_mda_count", FInt64;
4908 "vg_mda_free", FBytes;
4909 (* Not in Fedora 10:
4910 "vg_mda_size", FBytes;
4916 "lv_attr", FString (* XXX *);
4919 "lv_kernel_major", FInt64;
4920 "lv_kernel_minor", FInt64;
4922 "seg_count", FInt64;
4924 "snap_percent", FOptPercent;
4925 "copy_percent", FOptPercent;
4928 "mirror_log", FString;
4932 (* Names and fields in all structures (in RStruct and RStructList)
4936 (* The old RIntBool return type, only ever used for aug_defnode. Do
4937 * not use this struct in any new code.
4940 "i", FInt32; (* for historical compatibility *)
4941 "b", FInt32; (* for historical compatibility *)
4944 (* LVM PVs, VGs, LVs. *)
4945 "lvm_pv", lvm_pv_cols;
4946 "lvm_vg", lvm_vg_cols;
4947 "lvm_lv", lvm_lv_cols;
4949 (* Column names and types from stat structures.
4950 * NB. Can't use things like 'st_atime' because glibc header files
4951 * define some of these as macros. Ugh.
4982 (* Column names in dirent structure. *)
4985 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4990 (* Version numbers. *)
4998 (* Extended attribute. *)
5000 "attrname", FString;
5004 (* Inotify events. *)
5008 "in_cookie", FUInt32;
5012 (* Partition table entry. *)
5015 "part_start", FBytes;
5017 "part_size", FBytes;
5019 ] (* end of structs *)
5021 (* Ugh, Java has to be different ..
5022 * These names are also used by the Haskell bindings.
5024 let java_structs = [
5025 "int_bool", "IntBool";
5030 "statvfs", "StatVFS";
5032 "version", "Version";
5034 "inotify_event", "INotifyEvent";
5035 "partition", "Partition";
5038 (* What structs are actually returned. *)
5039 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5041 (* Returns a list of RStruct/RStructList structs that are returned
5042 * by any function. Each element of returned list is a pair:
5044 * (structname, RStructOnly)
5045 * == there exists function which returns RStruct (_, structname)
5046 * (structname, RStructListOnly)
5047 * == there exists function which returns RStructList (_, structname)
5048 * (structname, RStructAndList)
5049 * == there are functions returning both RStruct (_, structname)
5050 * and RStructList (_, structname)
5052 let rstructs_used_by functions =
5053 (* ||| is a "logical OR" for rstructs_used_t *)
5057 | _, RStructAndList -> RStructAndList
5058 | RStructOnly, RStructListOnly
5059 | RStructListOnly, RStructOnly -> RStructAndList
5060 | RStructOnly, RStructOnly -> RStructOnly
5061 | RStructListOnly, RStructListOnly -> RStructListOnly
5064 let h = Hashtbl.create 13 in
5066 (* if elem->oldv exists, update entry using ||| operator,
5067 * else just add elem->newv to the hash
5069 let update elem newv =
5070 try let oldv = Hashtbl.find h elem in
5071 Hashtbl.replace h elem (newv ||| oldv)
5072 with Not_found -> Hashtbl.add h elem newv
5076 fun (_, style, _, _, _, _, _) ->
5077 match fst style with
5078 | RStruct (_, structname) -> update structname RStructOnly
5079 | RStructList (_, structname) -> update structname RStructListOnly
5083 (* return key->values as a list of (key,value) *)
5084 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5086 (* Used for testing language bindings. *)
5088 | CallString of string
5089 | CallOptString of string option
5090 | CallStringList of string list
5092 | CallInt64 of int64
5094 | CallBuffer of string
5096 (* Used to memoize the result of pod2text. *)
5097 let pod2text_memo_filename = "src/.pod2text.data"
5098 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5100 let chan = open_in pod2text_memo_filename in
5101 let v = input_value chan in
5105 _ -> Hashtbl.create 13
5106 let pod2text_memo_updated () =
5107 let chan = open_out pod2text_memo_filename in
5108 output_value chan pod2text_memo;
5111 (* Useful functions.
5112 * Note we don't want to use any external OCaml libraries which
5113 * makes this a bit harder than it should be.
5115 module StringMap = Map.Make (String)
5117 let failwithf fs = ksprintf failwith fs
5119 let unique = let i = ref 0 in fun () -> incr i; !i
5121 let replace_char s c1 c2 =
5122 let s2 = String.copy s in
5123 let r = ref false in
5124 for i = 0 to String.length s2 - 1 do
5125 if String.unsafe_get s2 i = c1 then (
5126 String.unsafe_set s2 i c2;
5130 if not !r then s else s2
5134 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5136 let triml ?(test = isspace) str =
5138 let n = ref (String.length str) in
5139 while !n > 0 && test str.[!i]; do
5144 else String.sub str !i !n
5146 let trimr ?(test = isspace) str =
5147 let n = ref (String.length str) in
5148 while !n > 0 && test str.[!n-1]; do
5151 if !n = String.length str then str
5152 else String.sub str 0 !n
5154 let trim ?(test = isspace) str =
5155 trimr ~test (triml ~test str)
5157 let rec find s sub =
5158 let len = String.length s in
5159 let sublen = String.length sub in
5161 if i <= len-sublen then (
5163 if j < sublen then (
5164 if s.[i+j] = sub.[j] then loop2 (j+1)
5170 if r = -1 then loop (i+1) else r
5176 let rec replace_str s s1 s2 =
5177 let len = String.length s in
5178 let sublen = String.length s1 in
5179 let i = find s s1 in
5182 let s' = String.sub s 0 i in
5183 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5184 s' ^ s2 ^ replace_str s'' s1 s2
5187 let rec string_split sep str =
5188 let len = String.length str in
5189 let seplen = String.length sep in
5190 let i = find str sep in
5191 if i = -1 then [str]
5193 let s' = String.sub str 0 i in
5194 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5195 s' :: string_split sep s''
5198 let files_equal n1 n2 =
5199 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5200 match Sys.command cmd with
5203 | i -> failwithf "%s: failed with error code %d" cmd i
5205 let rec filter_map f = function
5209 | Some y -> y :: filter_map f xs
5210 | None -> filter_map f xs
5212 let rec find_map f = function
5213 | [] -> raise Not_found
5217 | None -> find_map f xs
5220 let rec loop i = function
5222 | x :: xs -> f i x; loop (i+1) xs
5227 let rec loop i = function
5229 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5233 let count_chars c str =
5234 let count = ref 0 in
5235 for i = 0 to String.length str - 1 do
5236 if c = String.unsafe_get str i then incr count
5242 for i = 0 to String.length str - 1 do
5243 let c = String.unsafe_get str i in
5248 let map_chars f str =
5249 List.map f (explode str)
5251 let name_of_argt = function
5252 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5253 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5254 | FileIn n | FileOut n | BufferIn n -> n
5256 let java_name_of_struct typ =
5257 try List.assoc typ java_structs
5260 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5262 let cols_of_struct typ =
5263 try List.assoc typ structs
5265 failwithf "cols_of_struct: unknown struct %s" typ
5267 let seq_of_test = function
5268 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5269 | TestOutputListOfDevices (s, _)
5270 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5271 | TestOutputTrue s | TestOutputFalse s
5272 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5273 | TestOutputStruct (s, _)
5274 | TestLastFail s -> s
5276 (* Handling for function flags. *)
5277 let protocol_limit_warning =
5278 "Because of the message protocol, there is a transfer limit
5279 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5281 let danger_will_robinson =
5282 "B<This command is dangerous. Without careful use you
5283 can easily destroy all your data>."
5285 let deprecation_notice flags =
5288 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5290 sprintf "This function is deprecated.
5291 In new code, use the C<%s> call instead.
5293 Deprecated functions will not be removed from the API, but the
5294 fact that they are deprecated indicates that there are problems
5295 with correct use of these functions." alt in
5300 (* Create list of optional groups. *)
5302 let h = Hashtbl.create 13 in
5304 fun (name, _, _, flags, _, _, _) ->
5308 let names = try Hashtbl.find h group with Not_found -> [] in
5309 Hashtbl.replace h group (name :: names)
5313 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5316 fun group -> group, List.sort compare (Hashtbl.find h group)
5318 List.sort (fun x y -> compare (fst x) (fst y)) groups
5320 (* Check function names etc. for consistency. *)
5321 let check_functions () =
5322 let contains_uppercase str =
5323 let len = String.length str in
5325 if i >= len then false
5328 if c >= 'A' && c <= 'Z' then true
5335 (* Check function names. *)
5337 fun (name, _, _, _, _, _, _) ->
5338 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5339 failwithf "function name %s does not need 'guestfs' prefix" name;
5341 failwithf "function name is empty";
5342 if name.[0] < 'a' || name.[0] > 'z' then
5343 failwithf "function name %s must start with lowercase a-z" name;
5344 if String.contains name '-' then
5345 failwithf "function name %s should not contain '-', use '_' instead."
5349 (* Check function parameter/return names. *)
5351 fun (name, style, _, _, _, _, _) ->
5352 let check_arg_ret_name n =
5353 if contains_uppercase n then
5354 failwithf "%s param/ret %s should not contain uppercase chars"
5356 if String.contains n '-' || String.contains n '_' then
5357 failwithf "%s param/ret %s should not contain '-' or '_'"
5360 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;
5361 if n = "int" || n = "char" || n = "short" || n = "long" then
5362 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5363 if n = "i" || n = "n" then
5364 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5365 if n = "argv" || n = "args" then
5366 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5368 (* List Haskell, OCaml and C keywords here.
5369 * http://www.haskell.org/haskellwiki/Keywords
5370 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5371 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5372 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5373 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5374 * Omitting _-containing words, since they're handled above.
5375 * Omitting the OCaml reserved word, "val", is ok,
5376 * and saves us from renaming several parameters.
5379 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5380 "char"; "class"; "const"; "constraint"; "continue"; "data";
5381 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5382 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5383 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5384 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5385 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5387 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5388 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5389 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5390 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5391 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5392 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5393 "volatile"; "when"; "where"; "while";
5395 if List.mem n reserved then
5396 failwithf "%s has param/ret using reserved word %s" name n;
5399 (match fst style with
5401 | RInt n | RInt64 n | RBool n
5402 | RConstString n | RConstOptString n | RString n
5403 | RStringList n | RStruct (n, _) | RStructList (n, _)
5404 | RHashtable n | RBufferOut n ->
5405 check_arg_ret_name n
5407 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5410 (* Check short descriptions. *)
5412 fun (name, _, _, _, _, shortdesc, _) ->
5413 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5414 failwithf "short description of %s should begin with lowercase." name;
5415 let c = shortdesc.[String.length shortdesc-1] in
5416 if c = '\n' || c = '.' then
5417 failwithf "short description of %s should not end with . or \\n." name
5420 (* Check long descriptions. *)
5422 fun (name, _, _, _, _, _, longdesc) ->
5423 if longdesc.[String.length longdesc-1] = '\n' then
5424 failwithf "long description of %s should not end with \\n." name
5427 (* Check proc_nrs. *)
5429 fun (name, _, proc_nr, _, _, _, _) ->
5430 if proc_nr <= 0 then
5431 failwithf "daemon function %s should have proc_nr > 0" name
5435 fun (name, _, proc_nr, _, _, _, _) ->
5436 if proc_nr <> -1 then
5437 failwithf "non-daemon function %s should have proc_nr -1" name
5438 ) non_daemon_functions;
5441 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5444 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5445 let rec loop = function
5448 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5450 | (name1,nr1) :: (name2,nr2) :: _ ->
5451 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5459 (* Ignore functions that have no tests. We generate a
5460 * warning when the user does 'make check' instead.
5462 | name, _, _, _, [], _, _ -> ()
5463 | name, _, _, _, tests, _, _ ->
5467 match seq_of_test test with
5469 failwithf "%s has a test containing an empty sequence" name
5470 | cmds -> List.map List.hd cmds
5472 let funcs = List.flatten funcs in
5474 let tested = List.mem name funcs in
5477 failwithf "function %s has tests but does not test itself" name
5480 (* 'pr' prints to the current output file. *)
5481 let chan = ref Pervasives.stdout
5486 let i = count_chars '\n' str in
5487 lines := !lines + i;
5488 output_string !chan str
5491 let copyright_years =
5492 let this_year = 1900 + (localtime (time ())).tm_year in
5493 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5495 (* Generate a header block in a number of standard styles. *)
5496 type comment_style =
5497 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5498 type license = GPLv2plus | LGPLv2plus
5500 let generate_header ?(extra_inputs = []) comment license =
5501 let inputs = "src/generator.ml" :: extra_inputs in
5502 let c = match comment with
5503 | CStyle -> pr "/* "; " *"
5504 | CPlusPlusStyle -> pr "// "; "//"
5505 | HashStyle -> pr "# "; "#"
5506 | OCamlStyle -> pr "(* "; " *"
5507 | HaskellStyle -> pr "{- "; " " in
5508 pr "libguestfs generated file\n";
5509 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5510 List.iter (pr "%s %s\n" c) inputs;
5511 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5513 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5517 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5518 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5519 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5520 pr "%s (at your option) any later version.\n" c;
5522 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5523 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5524 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5525 pr "%s GNU General Public License for more details.\n" c;
5527 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5528 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5529 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5532 pr "%s This library is free software; you can redistribute it and/or\n" c;
5533 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5534 pr "%s License as published by the Free Software Foundation; either\n" c;
5535 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5537 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5538 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5539 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5540 pr "%s Lesser General Public License for more details.\n" c;
5542 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5543 pr "%s License along with this library; if not, write to the Free Software\n" c;
5544 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5547 | CStyle -> pr " */\n"
5550 | OCamlStyle -> pr " *)\n"
5551 | HaskellStyle -> pr "-}\n"
5555 (* Start of main code generation functions below this line. *)
5557 (* Generate the pod documentation for the C API. *)
5558 let rec generate_actions_pod () =
5560 fun (shortname, style, _, flags, _, _, longdesc) ->
5561 if not (List.mem NotInDocs flags) then (
5562 let name = "guestfs_" ^ shortname in
5563 pr "=head2 %s\n\n" name;
5565 generate_prototype ~extern:false ~handle:"g" name style;
5567 pr "%s\n\n" longdesc;
5568 (match fst style with
5570 pr "This function returns 0 on success or -1 on error.\n\n"
5572 pr "On error this function returns -1.\n\n"
5574 pr "On error this function returns -1.\n\n"
5576 pr "This function returns a C truth value on success or -1 on error.\n\n"
5578 pr "This function returns a string, or NULL on error.
5579 The string is owned by the guest handle and must I<not> be freed.\n\n"
5580 | RConstOptString _ ->
5581 pr "This function returns a string which may be NULL.
5582 There is no way to return an error from this function.
5583 The string is owned by the guest handle and must I<not> be freed.\n\n"
5585 pr "This function returns a string, or NULL on error.
5586 I<The caller must free the returned string after use>.\n\n"
5588 pr "This function returns a NULL-terminated array of strings
5589 (like L<environ(3)>), or NULL if there was an error.
5590 I<The caller must free the strings and the array after use>.\n\n"
5591 | RStruct (_, typ) ->
5592 pr "This function returns a C<struct guestfs_%s *>,
5593 or NULL if there was an error.
5594 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5595 | RStructList (_, typ) ->
5596 pr "This function returns a C<struct guestfs_%s_list *>
5597 (see E<lt>guestfs-structs.hE<gt>),
5598 or NULL if there was an error.
5599 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5601 pr "This function returns a NULL-terminated array of
5602 strings, or NULL if there was an error.
5603 The array of strings will always have length C<2n+1>, where
5604 C<n> keys and values alternate, followed by the trailing NULL entry.
5605 I<The caller must free the strings and the array after use>.\n\n"
5607 pr "This function returns a buffer, or NULL on error.
5608 The size of the returned buffer is written to C<*size_r>.
5609 I<The caller must free the returned buffer after use>.\n\n"
5611 if List.mem ProtocolLimitWarning flags then
5612 pr "%s\n\n" protocol_limit_warning;
5613 if List.mem DangerWillRobinson flags then
5614 pr "%s\n\n" danger_will_robinson;
5615 match deprecation_notice flags with
5617 | Some txt -> pr "%s\n\n" txt
5619 ) all_functions_sorted
5621 and generate_structs_pod () =
5622 (* Structs documentation. *)
5625 pr "=head2 guestfs_%s\n" typ;
5627 pr " struct guestfs_%s {\n" typ;
5630 | name, FChar -> pr " char %s;\n" name
5631 | name, FUInt32 -> pr " uint32_t %s;\n" name
5632 | name, FInt32 -> pr " int32_t %s;\n" name
5633 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5634 | name, FInt64 -> pr " int64_t %s;\n" name
5635 | name, FString -> pr " char *%s;\n" name
5637 pr " /* The next two fields describe a byte array. */\n";
5638 pr " uint32_t %s_len;\n" name;
5639 pr " char *%s;\n" name
5641 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5642 pr " char %s[32];\n" name
5643 | name, FOptPercent ->
5644 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5645 pr " float %s;\n" name
5649 pr " struct guestfs_%s_list {\n" typ;
5650 pr " uint32_t len; /* Number of elements in list. */\n";
5651 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5654 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5655 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5660 and generate_availability_pod () =
5661 (* Availability documentation. *)
5665 fun (group, functions) ->
5666 pr "=item B<%s>\n" group;
5668 pr "The following functions:\n";
5669 List.iter (pr "L</guestfs_%s>\n") functions;
5675 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5676 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5678 * We have to use an underscore instead of a dash because otherwise
5679 * rpcgen generates incorrect code.
5681 * This header is NOT exported to clients, but see also generate_structs_h.
5683 and generate_xdr () =
5684 generate_header CStyle LGPLv2plus;
5686 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5687 pr "typedef string str<>;\n";
5690 (* Internal structures. *)
5694 pr "struct guestfs_int_%s {\n" typ;
5696 | name, FChar -> pr " char %s;\n" name
5697 | name, FString -> pr " string %s<>;\n" name
5698 | name, FBuffer -> pr " opaque %s<>;\n" name
5699 | name, FUUID -> pr " opaque %s[32];\n" name
5700 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5701 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5702 | name, FOptPercent -> pr " float %s;\n" name
5706 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5711 fun (shortname, style, _, _, _, _, _) ->
5712 let name = "guestfs_" ^ shortname in
5714 (match snd style with
5717 pr "struct %s_args {\n" name;
5720 | Pathname n | Device n | Dev_or_Path n | String n ->
5721 pr " string %s<>;\n" n
5722 | OptString n -> pr " str *%s;\n" n
5723 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5724 | Bool n -> pr " bool %s;\n" n
5725 | Int n -> pr " int %s;\n" n
5726 | Int64 n -> pr " hyper %s;\n" n
5728 pr " opaque %s<>;\n" n
5729 | FileIn _ | FileOut _ -> ()
5733 (match fst style with
5736 pr "struct %s_ret {\n" name;
5740 pr "struct %s_ret {\n" name;
5741 pr " hyper %s;\n" n;
5744 pr "struct %s_ret {\n" name;
5747 | RConstString _ | RConstOptString _ ->
5748 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5750 pr "struct %s_ret {\n" name;
5751 pr " string %s<>;\n" n;
5754 pr "struct %s_ret {\n" name;
5755 pr " str %s<>;\n" n;
5757 | RStruct (n, typ) ->
5758 pr "struct %s_ret {\n" name;
5759 pr " guestfs_int_%s %s;\n" typ n;
5761 | RStructList (n, typ) ->
5762 pr "struct %s_ret {\n" name;
5763 pr " guestfs_int_%s_list %s;\n" typ n;
5766 pr "struct %s_ret {\n" name;
5767 pr " str %s<>;\n" n;
5770 pr "struct %s_ret {\n" name;
5771 pr " opaque %s<>;\n" n;
5776 (* Table of procedure numbers. *)
5777 pr "enum guestfs_procedure {\n";
5779 fun (shortname, _, proc_nr, _, _, _, _) ->
5780 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5782 pr " GUESTFS_PROC_NR_PROCS\n";
5786 (* Having to choose a maximum message size is annoying for several
5787 * reasons (it limits what we can do in the API), but it (a) makes
5788 * the protocol a lot simpler, and (b) provides a bound on the size
5789 * of the daemon which operates in limited memory space.
5791 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5794 (* Message header, etc. *)
5796 /* The communication protocol is now documented in the guestfs(3)
5800 const GUESTFS_PROGRAM = 0x2000F5F5;
5801 const GUESTFS_PROTOCOL_VERSION = 1;
5803 /* These constants must be larger than any possible message length. */
5804 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5805 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5807 enum guestfs_message_direction {
5808 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5809 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5812 enum guestfs_message_status {
5813 GUESTFS_STATUS_OK = 0,
5814 GUESTFS_STATUS_ERROR = 1
5817 const GUESTFS_ERROR_LEN = 256;
5819 struct guestfs_message_error {
5820 string error_message<GUESTFS_ERROR_LEN>;
5823 struct guestfs_message_header {
5824 unsigned prog; /* GUESTFS_PROGRAM */
5825 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5826 guestfs_procedure proc; /* GUESTFS_PROC_x */
5827 guestfs_message_direction direction;
5828 unsigned serial; /* message serial number */
5829 guestfs_message_status status;
5832 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5834 struct guestfs_chunk {
5835 int cancel; /* if non-zero, transfer is cancelled */
5836 /* data size is 0 bytes if the transfer has finished successfully */
5837 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5841 (* Generate the guestfs-structs.h file. *)
5842 and generate_structs_h () =
5843 generate_header CStyle LGPLv2plus;
5845 (* This is a public exported header file containing various
5846 * structures. The structures are carefully written to have
5847 * exactly the same in-memory format as the XDR structures that
5848 * we use on the wire to the daemon. The reason for creating
5849 * copies of these structures here is just so we don't have to
5850 * export the whole of guestfs_protocol.h (which includes much
5851 * unrelated and XDR-dependent stuff that we don't want to be
5852 * public, or required by clients).
5854 * To reiterate, we will pass these structures to and from the
5855 * client with a simple assignment or memcpy, so the format
5856 * must be identical to what rpcgen / the RFC defines.
5859 (* Public structures. *)
5862 pr "struct guestfs_%s {\n" typ;
5865 | name, FChar -> pr " char %s;\n" name
5866 | name, FString -> pr " char *%s;\n" name
5868 pr " uint32_t %s_len;\n" name;
5869 pr " char *%s;\n" name
5870 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5871 | name, FUInt32 -> pr " uint32_t %s;\n" name
5872 | name, FInt32 -> pr " int32_t %s;\n" name
5873 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5874 | name, FInt64 -> pr " int64_t %s;\n" name
5875 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5879 pr "struct guestfs_%s_list {\n" typ;
5880 pr " uint32_t len;\n";
5881 pr " struct guestfs_%s *val;\n" typ;
5884 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5885 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5889 (* Generate the guestfs-actions.h file. *)
5890 and generate_actions_h () =
5891 generate_header CStyle LGPLv2plus;
5893 fun (shortname, style, _, _, _, _, _) ->
5894 let name = "guestfs_" ^ shortname in
5895 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5899 (* Generate the guestfs-internal-actions.h file. *)
5900 and generate_internal_actions_h () =
5901 generate_header CStyle LGPLv2plus;
5903 fun (shortname, style, _, _, _, _, _) ->
5904 let name = "guestfs__" ^ shortname in
5905 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5907 ) non_daemon_functions
5909 (* Generate the client-side dispatch stubs. *)
5910 and generate_client_actions () =
5911 generate_header CStyle LGPLv2plus;
5918 #include <inttypes.h>
5920 #include \"guestfs.h\"
5921 #include \"guestfs-internal.h\"
5922 #include \"guestfs-internal-actions.h\"
5923 #include \"guestfs_protocol.h\"
5925 /* Check the return message from a call for validity. */
5927 check_reply_header (guestfs_h *g,
5928 const struct guestfs_message_header *hdr,
5929 unsigned int proc_nr, unsigned int serial)
5931 if (hdr->prog != GUESTFS_PROGRAM) {
5932 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5935 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5936 error (g, \"wrong protocol version (%%d/%%d)\",
5937 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5940 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5941 error (g, \"unexpected message direction (%%d/%%d)\",
5942 hdr->direction, GUESTFS_DIRECTION_REPLY);
5945 if (hdr->proc != proc_nr) {
5946 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5949 if (hdr->serial != serial) {
5950 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5957 /* Check we are in the right state to run a high-level action. */
5959 check_state (guestfs_h *g, const char *caller)
5961 if (!guestfs__is_ready (g)) {
5962 if (guestfs__is_config (g) || guestfs__is_launching (g))
5963 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5966 error (g, \"%%s called from the wrong state, %%d != READY\",
5967 caller, guestfs__get_state (g));
5975 let error_code_of = function
5976 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5977 | RConstString _ | RConstOptString _
5978 | RString _ | RStringList _
5979 | RStruct _ | RStructList _
5980 | RHashtable _ | RBufferOut _ -> "NULL"
5983 (* Generate code to check String-like parameters are not passed in
5984 * as NULL (returning an error if they are).
5986 let check_null_strings shortname style =
5987 let pr_newline = ref false in
5990 (* parameters which should not be NULL *)
6000 pr " if (%s == NULL) {\n" n;
6001 pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6002 pr " \"%s\", \"%s\");\n" shortname n;
6003 pr " return %s;\n" (error_code_of (fst style));
6010 (* not applicable *)
6016 if !pr_newline then pr "\n";
6019 (* Generate code to generate guestfish call traces. *)
6020 let trace_call shortname style =
6021 pr " if (guestfs__get_trace (g)) {\n";
6024 List.exists (function
6025 | StringList _ | DeviceList _ -> true
6026 | _ -> false) (snd style) in
6032 pr " printf (\"%s\");\n" shortname;
6035 | String n (* strings *)
6042 (* guestfish doesn't support string escaping, so neither do we *)
6043 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
6044 | OptString n -> (* string option *)
6045 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6046 pr " else printf (\" null\");\n"
6048 | DeviceList n -> (* string list *)
6049 pr " putchar (' ');\n";
6050 pr " putchar ('\"');\n";
6051 pr " for (i = 0; %s[i]; ++i) {\n" n;
6052 pr " if (i > 0) putchar (' ');\n";
6053 pr " fputs (%s[i], stdout);\n" n;
6055 pr " putchar ('\"');\n";
6056 | Bool n -> (* boolean *)
6057 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
6058 | Int n -> (* int *)
6059 pr " printf (\" %%d\", %s);\n" n
6061 pr " printf (\" %%\" PRIi64, %s);\n" n
6063 pr " putchar ('\\n');\n";
6068 (* For non-daemon functions, generate a wrapper around each function. *)
6070 fun (shortname, style, _, _, _, _, _) ->
6071 let name = "guestfs_" ^ shortname in
6073 generate_prototype ~extern:false ~semicolon:false ~newline:true
6074 ~handle:"g" name style;
6076 check_null_strings shortname style;
6077 trace_call shortname style;
6078 pr " return guestfs__%s " shortname;
6079 generate_c_call_args ~handle:"g" style;
6083 ) non_daemon_functions;
6085 (* Client-side stubs for each function. *)
6087 fun (shortname, style, _, _, _, _, _) ->
6088 let name = "guestfs_" ^ shortname in
6089 let error_code = error_code_of (fst style) in
6091 (* Generate the action stub. *)
6092 generate_prototype ~extern:false ~semicolon:false ~newline:true
6093 ~handle:"g" name style;
6097 (match snd style with
6099 | _ -> pr " struct %s_args args;\n" name
6102 pr " guestfs_message_header hdr;\n";
6103 pr " guestfs_message_error err;\n";
6105 match fst style with
6107 | RConstString _ | RConstOptString _ ->
6108 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6110 | RBool _ | RString _ | RStringList _
6111 | RStruct _ | RStructList _
6112 | RHashtable _ | RBufferOut _ ->
6113 pr " struct %s_ret ret;\n" name;
6116 pr " int serial;\n";
6119 check_null_strings shortname style;
6120 trace_call shortname style;
6121 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
6122 shortname error_code;
6123 pr " guestfs___set_busy (g);\n";
6126 (* Send the main header and arguments. *)
6127 (match snd style with
6129 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6130 (String.uppercase shortname)
6134 | Pathname n | Device n | Dev_or_Path n | String n ->
6135 pr " args.%s = (char *) %s;\n" n n
6137 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
6138 | StringList n | DeviceList n ->
6139 pr " args.%s.%s_val = (char **) %s;\n" n n n;
6140 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6142 pr " args.%s = %s;\n" n n
6144 pr " args.%s = %s;\n" n n
6146 pr " args.%s = %s;\n" n n
6147 | FileIn _ | FileOut _ -> ()
6149 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6150 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6151 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6153 pr " guestfs___end_busy (g);\n";
6154 pr " return %s;\n" error_code;
6156 pr " args.%s.%s_val = (char *) %s;\n" n n n;
6157 pr " args.%s.%s_len = %s_size;\n" n n n
6159 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6160 (String.uppercase shortname);
6161 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6164 pr " if (serial == -1) {\n";
6165 pr " guestfs___end_busy (g);\n";
6166 pr " return %s;\n" error_code;
6170 (* Send any additional files (FileIn) requested. *)
6171 let need_read_reply_label = ref false in
6175 pr " r = guestfs___send_file (g, %s);\n" n;
6176 pr " if (r == -1) {\n";
6177 pr " guestfs___end_busy (g);\n";
6178 pr " return %s;\n" error_code;
6180 pr " if (r == -2) /* daemon cancelled */\n";
6181 pr " goto read_reply;\n";
6182 need_read_reply_label := true;
6187 (* Wait for the reply from the remote end. *)
6188 if !need_read_reply_label then pr " read_reply:\n";
6189 pr " memset (&hdr, 0, sizeof hdr);\n";
6190 pr " memset (&err, 0, sizeof err);\n";
6191 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
6193 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
6197 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6200 pr " if (r == -1) {\n";
6201 pr " guestfs___end_busy (g);\n";
6202 pr " return %s;\n" error_code;
6206 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6207 (String.uppercase shortname);
6208 pr " guestfs___end_busy (g);\n";
6209 pr " return %s;\n" error_code;
6213 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6214 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6215 pr " free (err.error_message);\n";
6216 pr " guestfs___end_busy (g);\n";
6217 pr " return %s;\n" error_code;
6221 (* Expecting to receive further files (FileOut)? *)
6225 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6226 pr " guestfs___end_busy (g);\n";
6227 pr " return %s;\n" error_code;
6233 pr " guestfs___end_busy (g);\n";
6235 (match fst style with
6236 | RErr -> pr " return 0;\n"
6237 | RInt n | RInt64 n | RBool n ->
6238 pr " return ret.%s;\n" n
6239 | RConstString _ | RConstOptString _ ->
6240 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6242 pr " return ret.%s; /* caller will free */\n" n
6243 | RStringList n | RHashtable n ->
6244 pr " /* caller will free this, but we need to add a NULL entry */\n";
6245 pr " ret.%s.%s_val =\n" n n;
6246 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6247 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6249 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6250 pr " return ret.%s.%s_val;\n" n n
6252 pr " /* caller will free this */\n";
6253 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6254 | RStructList (n, _) ->
6255 pr " /* caller will free this */\n";
6256 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6258 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6259 pr " * _val might be NULL here. To make the API saner for\n";
6260 pr " * callers, we turn this case into a unique pointer (using\n";
6261 pr " * malloc(1)).\n";
6263 pr " if (ret.%s.%s_len > 0) {\n" n n;
6264 pr " *size_r = ret.%s.%s_len;\n" n n;
6265 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6267 pr " free (ret.%s.%s_val);\n" n n;
6268 pr " char *p = safe_malloc (g, 1);\n";
6269 pr " *size_r = ret.%s.%s_len;\n" n n;
6277 (* Functions to free structures. *)
6278 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6279 pr " * structure format is identical to the XDR format. See note in\n";
6280 pr " * generator.ml.\n";
6287 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6289 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6295 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6297 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6304 (* Generate daemon/actions.h. *)
6305 and generate_daemon_actions_h () =
6306 generate_header CStyle GPLv2plus;
6308 pr "#include \"../src/guestfs_protocol.h\"\n";
6312 fun (name, style, _, _, _, _, _) ->
6314 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6318 (* Generate the linker script which controls the visibility of
6319 * symbols in the public ABI and ensures no other symbols get
6320 * exported accidentally.
6322 and generate_linker_script () =
6323 generate_header HashStyle GPLv2plus;
6328 "guestfs_get_error_handler";
6329 "guestfs_get_out_of_memory_handler";
6330 "guestfs_last_error";
6331 "guestfs_set_close_callback";
6332 "guestfs_set_error_handler";
6333 "guestfs_set_launch_done_callback";
6334 "guestfs_set_log_message_callback";
6335 "guestfs_set_out_of_memory_handler";
6336 "guestfs_set_subprocess_quit_callback";
6338 (* Unofficial parts of the API: the bindings code use these
6339 * functions, so it is useful to export them.
6341 "guestfs_safe_calloc";
6342 "guestfs_safe_malloc";
6343 "guestfs_safe_strdup";
6344 "guestfs_safe_memdup";
6347 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6351 List.map (fun (typ, _) ->
6352 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6355 let globals = List.sort compare (globals @ functions @ structs) in
6359 List.iter (pr " %s;\n") globals;
6366 (* Generate the server-side stubs. *)
6367 and generate_daemon_actions () =
6368 generate_header CStyle GPLv2plus;
6370 pr "#include <config.h>\n";
6372 pr "#include <stdio.h>\n";
6373 pr "#include <stdlib.h>\n";
6374 pr "#include <string.h>\n";
6375 pr "#include <inttypes.h>\n";
6376 pr "#include <rpc/types.h>\n";
6377 pr "#include <rpc/xdr.h>\n";
6379 pr "#include \"daemon.h\"\n";
6380 pr "#include \"c-ctype.h\"\n";
6381 pr "#include \"../src/guestfs_protocol.h\"\n";
6382 pr "#include \"actions.h\"\n";
6386 fun (name, style, _, _, _, _, _) ->
6387 (* Generate server-side stubs. *)
6388 pr "static void %s_stub (XDR *xdr_in)\n" name;
6391 match fst style with
6392 | RErr | RInt _ -> pr " int r;\n"; "-1"
6393 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6394 | RBool _ -> pr " int r;\n"; "-1"
6395 | RConstString _ | RConstOptString _ ->
6396 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6397 | RString _ -> pr " char *r;\n"; "NULL"
6398 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6399 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6400 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6402 pr " size_t size = 1;\n";
6406 (match snd style with
6409 pr " struct guestfs_%s_args args;\n" name;
6412 | Device n | Dev_or_Path n
6415 | OptString n -> pr " char *%s;\n" n
6416 | StringList n | DeviceList n -> pr " char **%s;\n" n
6417 | Bool n -> pr " int %s;\n" n
6418 | Int n -> pr " int %s;\n" n
6419 | Int64 n -> pr " int64_t %s;\n" n
6420 | FileIn _ | FileOut _ -> ()
6422 pr " const char *%s;\n" n;
6423 pr " size_t %s_size;\n" n
6429 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6431 (match snd style with
6434 pr " memset (&args, 0, sizeof args);\n";
6436 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6438 pr " if (cancel_receive () != -2)\n";
6439 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6443 pr " char *%s = args.%s;\n" n n
6445 let pr_list_handling_code n =
6446 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6447 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6448 pr " if (%s == NULL) {\n" n;
6450 pr " if (cancel_receive () != -2)\n";
6451 pr " reply_with_perror (\"realloc\");\n";
6454 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6455 pr " args.%s.%s_val = %s;\n" n n n;
6461 pr " ABS_PATH (%s, %s, goto done);\n"
6462 n (if is_filein then "cancel_receive ()" else "0");
6465 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6466 n (if is_filein then "cancel_receive ()" else "0");
6469 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6470 n (if is_filein then "cancel_receive ()" else "0");
6471 | String n -> pr_args n
6472 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6474 pr_list_handling_code n;
6476 pr_list_handling_code n;
6477 pr " /* Ensure that each is a device,\n";
6478 pr " * and perform device name translation.\n";
6482 pr " for (i = 0; %s[i] != NULL; ++i)\n" n;
6483 pr " RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6484 (if is_filein then "cancel_receive ()" else "0");
6486 | Bool n -> pr " %s = args.%s;\n" n n
6487 | Int n -> pr " %s = args.%s;\n" n n
6488 | Int64 n -> pr " %s = args.%s;\n" n n
6489 | FileIn _ | FileOut _ -> ()
6491 pr " %s = args.%s.%s_val;\n" n n n;
6492 pr " %s_size = args.%s.%s_len;\n" n n n
6497 (* this is used at least for do_equal *)
6498 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6499 (* Emit NEED_ROOT just once, even when there are two or
6500 more Pathname args *)
6501 pr " NEED_ROOT (%s, goto done);\n"
6502 (if is_filein then "cancel_receive ()" else "0");
6505 (* Don't want to call the impl with any FileIn or FileOut
6506 * parameters, since these go "outside" the RPC protocol.
6509 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6511 pr " r = do_%s " name;
6512 generate_c_call_args (fst style, args');
6515 (match fst style with
6516 | RErr | RInt _ | RInt64 _ | RBool _
6517 | RConstString _ | RConstOptString _
6518 | RString _ | RStringList _ | RHashtable _
6519 | RStruct (_, _) | RStructList (_, _) ->
6520 pr " if (r == %s)\n" error_code;
6521 pr " /* do_%s has already called reply_with_error */\n" name;
6525 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6526 pr " * an ordinary zero-length buffer), so be careful ...\n";
6528 pr " if (size == 1 && r == %s)\n" error_code;
6529 pr " /* do_%s has already called reply_with_error */\n" name;
6534 (* If there are any FileOut parameters, then the impl must
6535 * send its own reply.
6538 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6540 pr " /* do_%s has already sent a reply */\n" name
6542 match fst style with
6543 | RErr -> pr " reply (NULL, NULL);\n"
6544 | RInt n | RInt64 n | RBool n ->
6545 pr " struct guestfs_%s_ret ret;\n" name;
6546 pr " ret.%s = r;\n" n;
6547 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6549 | RConstString _ | RConstOptString _ ->
6550 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6552 pr " struct guestfs_%s_ret ret;\n" name;
6553 pr " ret.%s = r;\n" n;
6554 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6557 | RStringList n | RHashtable n ->
6558 pr " struct guestfs_%s_ret ret;\n" name;
6559 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6560 pr " ret.%s.%s_val = r;\n" n n;
6561 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6563 pr " free_strings (r);\n"
6565 pr " struct guestfs_%s_ret ret;\n" name;
6566 pr " ret.%s = *r;\n" n;
6567 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6569 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6571 | RStructList (n, _) ->
6572 pr " struct guestfs_%s_ret ret;\n" name;
6573 pr " ret.%s = *r;\n" n;
6574 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6576 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6579 pr " struct guestfs_%s_ret ret;\n" name;
6580 pr " ret.%s.%s_val = r;\n" n n;
6581 pr " ret.%s.%s_len = size;\n" n n;
6582 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6587 (* Free the args. *)
6589 (match snd style with
6592 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6599 (* Dispatch function. *)
6600 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6602 pr " switch (proc_nr) {\n";
6605 fun (name, style, _, _, _, _, _) ->
6606 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6607 pr " %s_stub (xdr_in);\n" name;
6612 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";
6617 (* LVM columns and tokenization functions. *)
6618 (* XXX This generates crap code. We should rethink how we
6624 pr "static const char *lvm_%s_cols = \"%s\";\n"
6625 typ (String.concat "," (List.map fst cols));
6628 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6630 pr " char *tok, *p, *next;\n";
6631 pr " size_t i, j;\n";
6634 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6637 pr " if (!str) {\n";
6638 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6641 pr " if (!*str || c_isspace (*str)) {\n";
6642 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6647 fun (name, coltype) ->
6648 pr " if (!tok) {\n";
6649 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6652 pr " p = strchrnul (tok, ',');\n";
6653 pr " if (*p) next = p+1; else next = NULL;\n";
6654 pr " *p = '\\0';\n";
6657 pr " r->%s = strdup (tok);\n" name;
6658 pr " if (r->%s == NULL) {\n" name;
6659 pr " perror (\"strdup\");\n";
6663 pr " for (i = j = 0; i < 32; ++j) {\n";
6664 pr " if (tok[j] == '\\0') {\n";
6665 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6667 pr " } else if (tok[j] != '-')\n";
6668 pr " r->%s[i++] = tok[j];\n" name;
6671 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6672 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6676 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6677 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6681 pr " if (tok[0] == '\\0')\n";
6682 pr " r->%s = -1;\n" name;
6683 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6684 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6687 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6688 assert false (* can never be an LVM column *)
6690 pr " tok = next;\n";
6693 pr " if (tok != NULL) {\n";
6694 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6701 pr "guestfs_int_lvm_%s_list *\n" typ;
6702 pr "parse_command_line_%ss (void)\n" typ;
6704 pr " char *out, *err;\n";
6705 pr " char *p, *pend;\n";
6707 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6708 pr " void *newp;\n";
6710 pr " ret = malloc (sizeof *ret);\n";
6711 pr " if (!ret) {\n";
6712 pr " reply_with_perror (\"malloc\");\n";
6713 pr " return NULL;\n";
6716 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6717 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6719 pr " r = command (&out, &err,\n";
6720 pr " \"lvm\", \"%ss\",\n" typ;
6721 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6722 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6723 pr " if (r == -1) {\n";
6724 pr " reply_with_error (\"%%s\", err);\n";
6725 pr " free (out);\n";
6726 pr " free (err);\n";
6727 pr " free (ret);\n";
6728 pr " return NULL;\n";
6731 pr " free (err);\n";
6733 pr " /* Tokenize each line of the output. */\n";
6736 pr " while (p) {\n";
6737 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6738 pr " if (pend) {\n";
6739 pr " *pend = '\\0';\n";
6743 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6746 pr " if (!*p) { /* Empty line? Skip it. */\n";
6751 pr " /* Allocate some space to store this next entry. */\n";
6752 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6753 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6754 pr " if (newp == NULL) {\n";
6755 pr " reply_with_perror (\"realloc\");\n";
6756 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6757 pr " free (ret);\n";
6758 pr " free (out);\n";
6759 pr " return NULL;\n";
6761 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6763 pr " /* Tokenize the next entry. */\n";
6764 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6765 pr " if (r == -1) {\n";
6766 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6767 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6768 pr " free (ret);\n";
6769 pr " free (out);\n";
6770 pr " return NULL;\n";
6777 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6779 pr " free (out);\n";
6780 pr " return ret;\n";
6783 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6785 (* Generate a list of function names, for debugging in the daemon.. *)
6786 and generate_daemon_names () =
6787 generate_header CStyle GPLv2plus;
6789 pr "#include <config.h>\n";
6791 pr "#include \"daemon.h\"\n";
6794 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6795 pr "const char *function_names[] = {\n";
6797 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6801 (* Generate the optional groups for the daemon to implement
6802 * guestfs_available.
6804 and generate_daemon_optgroups_c () =
6805 generate_header CStyle GPLv2plus;
6807 pr "#include <config.h>\n";
6809 pr "#include \"daemon.h\"\n";
6810 pr "#include \"optgroups.h\"\n";
6813 pr "struct optgroup optgroups[] = {\n";
6816 pr " { \"%s\", optgroup_%s_available },\n" group group
6818 pr " { NULL, NULL }\n";
6821 and generate_daemon_optgroups_h () =
6822 generate_header CStyle GPLv2plus;
6826 pr "extern int optgroup_%s_available (void);\n" group
6829 (* Generate the tests. *)
6830 and generate_tests () =
6831 generate_header CStyle GPLv2plus;
6838 #include <sys/types.h>
6841 #include \"guestfs.h\"
6842 #include \"guestfs-internal.h\"
6844 static guestfs_h *g;
6845 static int suppress_error = 0;
6847 static void print_error (guestfs_h *g, void *data, const char *msg)
6849 if (!suppress_error)
6850 fprintf (stderr, \"%%s\\n\", msg);
6853 /* FIXME: nearly identical code appears in fish.c */
6854 static void print_strings (char *const *argv)
6858 for (argc = 0; argv[argc] != NULL; ++argc)
6859 printf (\"\\t%%s\\n\", argv[argc]);
6863 static void print_table (char const *const *argv)
6867 for (i = 0; argv[i] != NULL; i += 2)
6868 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6873 is_available (const char *group)
6875 const char *groups[] = { group, NULL };
6879 r = guestfs_available (g, (char **) groups);
6886 incr (guestfs_h *g, void *iv)
6888 int *i = (int *) iv;
6894 (* Generate a list of commands which are not tested anywhere. *)
6895 pr "static void no_test_warnings (void)\n";
6898 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6900 fun (_, _, _, _, tests, _, _) ->
6901 let tests = filter_map (
6903 | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6904 | (_, Disabled, _) -> None
6906 let seq = List.concat (List.map seq_of_test tests) in
6907 let cmds_tested = List.map List.hd seq in
6908 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6912 fun (name, _, _, _, _, _, _) ->
6913 if not (Hashtbl.mem hash name) then
6914 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6920 (* Generate the actual tests. Note that we generate the tests
6921 * in reverse order, deliberately, so that (in general) the
6922 * newest tests run first. This makes it quicker and easier to
6927 fun (name, _, _, flags, tests, _, _) ->
6928 mapi (generate_one_test name flags) tests
6929 ) (List.rev all_functions) in
6930 let test_names = List.concat test_names in
6931 let nr_tests = List.length test_names in
6934 int main (int argc, char *argv[])
6937 unsigned long int n_failed = 0;
6938 const char *filename;
6940 int nr_tests, test_num = 0;
6942 setbuf (stdout, NULL);
6944 no_test_warnings ();
6946 g = guestfs_create ();
6948 printf (\"guestfs_create FAILED\\n\");
6949 exit (EXIT_FAILURE);
6952 guestfs_set_error_handler (g, print_error, NULL);
6954 guestfs_set_path (g, \"../appliance\");
6956 filename = \"test1.img\";
6957 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6960 exit (EXIT_FAILURE);
6962 if (lseek (fd, %d, SEEK_SET) == -1) {
6966 exit (EXIT_FAILURE);
6968 if (write (fd, &c, 1) == -1) {
6972 exit (EXIT_FAILURE);
6974 if (close (fd) == -1) {
6977 exit (EXIT_FAILURE);
6979 if (guestfs_add_drive (g, filename) == -1) {
6980 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6981 exit (EXIT_FAILURE);
6984 filename = \"test2.img\";
6985 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6988 exit (EXIT_FAILURE);
6990 if (lseek (fd, %d, SEEK_SET) == -1) {
6994 exit (EXIT_FAILURE);
6996 if (write (fd, &c, 1) == -1) {
7000 exit (EXIT_FAILURE);
7002 if (close (fd) == -1) {
7005 exit (EXIT_FAILURE);
7007 if (guestfs_add_drive (g, filename) == -1) {
7008 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7009 exit (EXIT_FAILURE);
7012 filename = \"test3.img\";
7013 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7016 exit (EXIT_FAILURE);
7018 if (lseek (fd, %d, SEEK_SET) == -1) {
7022 exit (EXIT_FAILURE);
7024 if (write (fd, &c, 1) == -1) {
7028 exit (EXIT_FAILURE);
7030 if (close (fd) == -1) {
7033 exit (EXIT_FAILURE);
7035 if (guestfs_add_drive (g, filename) == -1) {
7036 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7037 exit (EXIT_FAILURE);
7040 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7041 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7042 exit (EXIT_FAILURE);
7045 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7048 if (guestfs_launch (g) == -1) {
7049 printf (\"guestfs_launch FAILED\\n\");
7050 exit (EXIT_FAILURE);
7053 /* Cancel previous alarm. */
7058 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7062 pr " test_num++;\n";
7063 pr " if (guestfs_get_verbose (g))\n";
7064 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
7065 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7066 pr " if (%s () == -1) {\n" test_name;
7067 pr " printf (\"%s FAILED\\n\");\n" test_name;
7068 pr " n_failed++;\n";
7073 pr " /* Check close callback is called. */
7074 int close_sentinel = 1;
7075 guestfs_set_close_callback (g, incr, &close_sentinel);
7079 if (close_sentinel != 2) {
7080 fprintf (stderr, \"close callback was not called\\n\");
7081 exit (EXIT_FAILURE);
7084 unlink (\"test1.img\");
7085 unlink (\"test2.img\");
7086 unlink (\"test3.img\");
7090 pr " if (n_failed > 0) {\n";
7091 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7092 pr " exit (EXIT_FAILURE);\n";
7096 pr " exit (EXIT_SUCCESS);\n";
7099 and generate_one_test name flags i (init, prereq, test) =
7100 let test_name = sprintf "test_%s_%d" name i in
7103 static int %s_skip (void)
7107 str = getenv (\"TEST_ONLY\");
7109 return strstr (str, \"%s\") == NULL;
7110 str = getenv (\"SKIP_%s\");
7111 if (str && STREQ (str, \"1\")) return 1;
7112 str = getenv (\"SKIP_TEST_%s\");
7113 if (str && STREQ (str, \"1\")) return 1;
7117 " test_name name (String.uppercase test_name) (String.uppercase name);
7120 | Disabled | Always | IfAvailable _ -> ()
7121 | If code | Unless code ->
7122 pr "static int %s_prereq (void)\n" test_name;
7130 static int %s (void)
7133 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
7137 " test_name test_name test_name;
7139 (* Optional functions should only be tested if the relevant
7140 * support is available in the daemon.
7145 pr " if (!is_available (\"%s\")) {\n" group;
7146 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7154 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7156 pr " if (! %s_prereq ()) {\n" test_name;
7157 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7161 generate_one_test_body name i test_name init test;
7163 pr " if (%s_prereq ()) {\n" test_name;
7164 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7168 generate_one_test_body name i test_name init test;
7169 | IfAvailable group ->
7170 pr " if (!is_available (\"%s\")) {\n" group;
7171 pr " printf (\" %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7175 generate_one_test_body name i test_name init test;
7177 generate_one_test_body name i test_name init test
7185 and generate_one_test_body name i test_name init test =
7187 | InitNone (* XXX at some point, InitNone and InitEmpty became
7188 * folded together as the same thing. Really we should
7189 * make InitNone do nothing at all, but the tests may
7190 * need to be checked to make sure this is OK.
7193 pr " /* InitNone|InitEmpty for %s */\n" test_name;
7194 List.iter (generate_test_command_call test_name)
7195 [["blockdev_setrw"; "/dev/sda"];
7199 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7200 List.iter (generate_test_command_call test_name)
7201 [["blockdev_setrw"; "/dev/sda"];
7204 ["part_disk"; "/dev/sda"; "mbr"]]
7206 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7207 List.iter (generate_test_command_call test_name)
7208 [["blockdev_setrw"; "/dev/sda"];
7211 ["part_disk"; "/dev/sda"; "mbr"];
7212 ["mkfs"; "ext2"; "/dev/sda1"];
7213 ["mount_options"; ""; "/dev/sda1"; "/"]]
7214 | InitBasicFSonLVM ->
7215 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7217 List.iter (generate_test_command_call test_name)
7218 [["blockdev_setrw"; "/dev/sda"];
7221 ["part_disk"; "/dev/sda"; "mbr"];
7222 ["pvcreate"; "/dev/sda1"];
7223 ["vgcreate"; "VG"; "/dev/sda1"];
7224 ["lvcreate"; "LV"; "VG"; "8"];
7225 ["mkfs"; "ext2"; "/dev/VG/LV"];
7226 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7228 pr " /* InitISOFS for %s */\n" test_name;
7229 List.iter (generate_test_command_call test_name)
7230 [["blockdev_setrw"; "/dev/sda"];
7233 ["mount_ro"; "/dev/sdd"; "/"]]
7236 let get_seq_last = function
7238 failwithf "%s: you cannot use [] (empty list) when expecting a command"
7241 let seq = List.rev seq in
7242 List.rev (List.tl seq), List.hd seq
7247 pr " /* TestRun for %s (%d) */\n" name i;
7248 List.iter (generate_test_command_call test_name) seq
7249 | TestOutput (seq, expected) ->
7250 pr " /* TestOutput for %s (%d) */\n" name i;
7251 pr " const char *expected = \"%s\";\n" (c_quote expected);
7252 let seq, last = get_seq_last seq in
7254 pr " if (STRNEQ (r, expected)) {\n";
7255 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7259 List.iter (generate_test_command_call test_name) seq;
7260 generate_test_command_call ~test test_name last
7261 | TestOutputList (seq, expected) ->
7262 pr " /* TestOutputList for %s (%d) */\n" name i;
7263 let seq, last = get_seq_last seq in
7267 pr " if (!r[%d]) {\n" i;
7268 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7269 pr " print_strings (r);\n";
7273 pr " const char *expected = \"%s\";\n" (c_quote str);
7274 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7275 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7280 pr " if (r[%d] != NULL) {\n" (List.length expected);
7281 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7283 pr " print_strings (r);\n";
7287 List.iter (generate_test_command_call test_name) seq;
7288 generate_test_command_call ~test test_name last
7289 | TestOutputListOfDevices (seq, expected) ->
7290 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7291 let seq, last = get_seq_last seq in
7295 pr " if (!r[%d]) {\n" i;
7296 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7297 pr " print_strings (r);\n";
7301 pr " const char *expected = \"%s\";\n" (c_quote str);
7302 pr " r[%d][5] = 's';\n" i;
7303 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7304 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7309 pr " if (r[%d] != NULL) {\n" (List.length expected);
7310 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7312 pr " print_strings (r);\n";
7316 List.iter (generate_test_command_call test_name) seq;
7317 generate_test_command_call ~test test_name last
7318 | TestOutputInt (seq, expected) ->
7319 pr " /* TestOutputInt for %s (%d) */\n" name i;
7320 let seq, last = get_seq_last seq in
7322 pr " if (r != %d) {\n" expected;
7323 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7329 List.iter (generate_test_command_call test_name) seq;
7330 generate_test_command_call ~test test_name last
7331 | TestOutputIntOp (seq, op, expected) ->
7332 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7333 let seq, last = get_seq_last seq in
7335 pr " if (! (r %s %d)) {\n" op expected;
7336 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7337 test_name op expected;
7342 List.iter (generate_test_command_call test_name) seq;
7343 generate_test_command_call ~test test_name last
7344 | TestOutputTrue seq ->
7345 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7346 let seq, last = get_seq_last seq in
7349 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7354 List.iter (generate_test_command_call test_name) seq;
7355 generate_test_command_call ~test test_name last
7356 | TestOutputFalse seq ->
7357 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7358 let seq, last = get_seq_last seq in
7361 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7366 List.iter (generate_test_command_call test_name) seq;
7367 generate_test_command_call ~test test_name last
7368 | TestOutputLength (seq, expected) ->
7369 pr " /* TestOutputLength for %s (%d) */\n" name i;
7370 let seq, last = get_seq_last seq in
7373 pr " for (j = 0; j < %d; ++j)\n" expected;
7374 pr " if (r[j] == NULL) {\n";
7375 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7377 pr " print_strings (r);\n";
7380 pr " if (r[j] != NULL) {\n";
7381 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7383 pr " print_strings (r);\n";
7387 List.iter (generate_test_command_call test_name) seq;
7388 generate_test_command_call ~test test_name last
7389 | TestOutputBuffer (seq, expected) ->
7390 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7391 pr " const char *expected = \"%s\";\n" (c_quote expected);
7392 let seq, last = get_seq_last seq in
7393 let len = String.length expected in
7395 pr " if (size != %d) {\n" len;
7396 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7399 pr " if (STRNEQLEN (r, expected, size)) {\n";
7400 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7404 List.iter (generate_test_command_call test_name) seq;
7405 generate_test_command_call ~test test_name last
7406 | TestOutputStruct (seq, checks) ->
7407 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7408 let seq, last = get_seq_last seq in
7412 | CompareWithInt (field, expected) ->
7413 pr " if (r->%s != %d) {\n" field expected;
7414 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7415 test_name field expected;
7416 pr " (int) r->%s);\n" field;
7419 | CompareWithIntOp (field, op, expected) ->
7420 pr " if (!(r->%s %s %d)) {\n" field op expected;
7421 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7422 test_name field op expected;
7423 pr " (int) r->%s);\n" field;
7426 | CompareWithString (field, expected) ->
7427 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7428 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7429 test_name field expected;
7430 pr " r->%s);\n" field;
7433 | CompareFieldsIntEq (field1, field2) ->
7434 pr " if (r->%s != r->%s) {\n" field1 field2;
7435 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7436 test_name field1 field2;
7437 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7440 | CompareFieldsStrEq (field1, field2) ->
7441 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7442 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7443 test_name field1 field2;
7444 pr " r->%s, r->%s);\n" field1 field2;
7449 List.iter (generate_test_command_call test_name) seq;
7450 generate_test_command_call ~test test_name last
7451 | TestLastFail seq ->
7452 pr " /* TestLastFail for %s (%d) */\n" name i;
7453 let seq, last = get_seq_last seq in
7454 List.iter (generate_test_command_call test_name) seq;
7455 generate_test_command_call test_name ~expect_error:true last
7457 (* Generate the code to run a command, leaving the result in 'r'.
7458 * If you expect to get an error then you should set expect_error:true.
7460 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7462 | [] -> assert false
7464 (* Look up the command to find out what args/ret it has. *)
7467 let _, style, _, _, _, _, _ =
7468 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7471 failwithf "%s: in test, command %s was not found" test_name name in
7473 if List.length (snd style) <> List.length args then
7474 failwithf "%s: in test, wrong number of args given to %s"
7481 | OptString n, "NULL" -> ()
7484 | Dev_or_Path n, arg
7486 | OptString n, arg ->
7487 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7488 | BufferIn n, arg ->
7489 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7490 pr " size_t %s_size = %d;\n" n (String.length arg)
7494 | FileIn _, _ | FileOut _, _ -> ()
7495 | StringList n, "" | DeviceList n, "" ->
7496 pr " const char *const %s[1] = { NULL };\n" n
7497 | StringList n, arg | DeviceList n, arg ->
7498 let strs = string_split " " arg in
7501 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7503 pr " const char *const %s[] = {\n" n;
7505 fun i _ -> pr " %s_%d,\n" n i
7509 ) (List.combine (snd style) args);
7512 match fst style with
7513 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7514 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7515 | RConstString _ | RConstOptString _ ->
7516 pr " const char *r;\n"; "NULL"
7517 | RString _ -> pr " char *r;\n"; "NULL"
7518 | RStringList _ | RHashtable _ ->
7522 | RStruct (_, typ) ->
7523 pr " struct guestfs_%s *r;\n" typ; "NULL"
7524 | RStructList (_, typ) ->
7525 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7528 pr " size_t size;\n";
7531 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7532 pr " r = guestfs_%s (g" name;
7534 (* Generate the parameters. *)
7537 | OptString _, "NULL" -> pr ", NULL"
7539 | Device n, _ | Dev_or_Path n, _
7544 pr ", %s, %s_size" n n
7545 | FileIn _, arg | FileOut _, arg ->
7546 pr ", \"%s\"" (c_quote arg)
7547 | StringList n, _ | DeviceList n, _ ->
7548 pr ", (char **) %s" n
7551 try int_of_string arg
7552 with Failure "int_of_string" ->
7553 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7557 try Int64.of_string arg
7558 with Failure "int_of_string" ->
7559 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7562 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7563 ) (List.combine (snd style) args);
7565 (match fst style with
7566 | RBufferOut _ -> pr ", &size"
7572 if not expect_error then
7573 pr " if (r == %s)\n" error_code
7575 pr " if (r != %s)\n" error_code;
7578 (* Insert the test code. *)
7584 (match fst style with
7585 | RErr | RInt _ | RInt64 _ | RBool _
7586 | RConstString _ | RConstOptString _ -> ()
7587 | RString _ | RBufferOut _ -> pr " free (r);\n"
7588 | RStringList _ | RHashtable _ ->
7589 pr " for (i = 0; r[i] != NULL; ++i)\n";
7590 pr " free (r[i]);\n";
7592 | RStruct (_, typ) ->
7593 pr " guestfs_free_%s (r);\n" typ
7594 | RStructList (_, typ) ->
7595 pr " guestfs_free_%s_list (r);\n" typ
7601 let str = replace_str str "\r" "\\r" in
7602 let str = replace_str str "\n" "\\n" in
7603 let str = replace_str str "\t" "\\t" in
7604 let str = replace_str str "\000" "\\0" in
7607 (* Generate a lot of different functions for guestfish. *)
7608 and generate_fish_cmds () =
7609 generate_header CStyle GPLv2plus;
7613 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7615 let all_functions_sorted =
7617 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7618 ) all_functions_sorted in
7620 pr "#include <config.h>\n";
7622 pr "#include <stdio.h>\n";
7623 pr "#include <stdlib.h>\n";
7624 pr "#include <string.h>\n";
7625 pr "#include <inttypes.h>\n";
7627 pr "#include <guestfs.h>\n";
7628 pr "#include \"c-ctype.h\"\n";
7629 pr "#include \"full-write.h\"\n";
7630 pr "#include \"xstrtol.h\"\n";
7631 pr "#include \"fish.h\"\n";
7633 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
7634 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7637 (* list_commands function, which implements guestfish -h *)
7638 pr "void list_commands (void)\n";
7640 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7641 pr " list_builtin_commands ();\n";
7643 fun (name, _, _, flags, _, shortdesc, _) ->
7644 let name = replace_char name '_' '-' in
7645 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7647 ) all_functions_sorted;
7648 pr " printf (\" %%s\\n\",";
7649 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7653 (* display_command function, which implements guestfish -h cmd *)
7654 pr "int display_command (const char *cmd)\n";
7657 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7658 let name2 = replace_char name '_' '-' in
7660 try find_map (function FishAlias n -> Some n | _ -> None) flags
7661 with Not_found -> name in
7662 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7664 match snd style with
7668 name2 (String.concat " " (List.map name_of_argt args)) in
7671 if List.mem ProtocolLimitWarning flags then
7672 ("\n\n" ^ protocol_limit_warning)
7675 (* For DangerWillRobinson commands, we should probably have
7676 * guestfish prompt before allowing you to use them (especially
7677 * in interactive mode). XXX
7681 if List.mem DangerWillRobinson flags then
7682 ("\n\n" ^ danger_will_robinson)
7687 match deprecation_notice flags with
7689 | Some txt -> "\n\n" ^ txt in
7691 let describe_alias =
7692 if name <> alias then
7693 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7697 pr "STRCASEEQ (cmd, \"%s\")" name;
7698 if name <> name2 then
7699 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7700 if name <> alias then
7701 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7703 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7705 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7706 "=head1 DESCRIPTION\n\n" ^
7707 longdesc ^ warnings ^ describe_alias);
7712 pr " return display_builtin_command (cmd);\n";
7716 let emit_print_list_function typ =
7717 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7720 pr " unsigned int i;\n";
7722 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7723 pr " printf (\"[%%d] = {\\n\", i);\n";
7724 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7725 pr " printf (\"}\\n\");\n";
7731 (* print_* functions *)
7735 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7737 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7740 pr " unsigned int i;\n";
7746 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7748 pr " printf (\"%%s%s: \", indent);\n" name;
7749 pr " for (i = 0; i < 32; ++i)\n";
7750 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7751 pr " printf (\"\\n\");\n"
7753 pr " printf (\"%%s%s: \", indent);\n" name;
7754 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7755 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7756 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7758 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7759 pr " printf (\"\\n\");\n"
7760 | name, (FUInt64|FBytes) ->
7761 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7764 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7767 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7770 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7773 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7775 | name, FOptPercent ->
7776 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7777 typ name name typ name;
7778 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7784 (* Emit a print_TYPE_list function definition only if that function is used. *)
7787 | typ, (RStructListOnly | RStructAndList) ->
7788 (* generate the function for typ *)
7789 emit_print_list_function typ
7790 | typ, _ -> () (* empty *)
7791 ) (rstructs_used_by all_functions);
7793 (* Emit a print_TYPE function definition only if that function is used. *)
7796 | typ, (RStructOnly | RStructAndList) ->
7797 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7799 pr " print_%s_indent (%s, \"\");\n" typ typ;
7802 | typ, _ -> () (* empty *)
7803 ) (rstructs_used_by all_functions);
7805 (* run_<action> actions *)
7807 fun (name, style, _, flags, _, _, _) ->
7808 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7810 (match fst style with
7813 | RBool _ -> pr " int r;\n"
7814 | RInt64 _ -> pr " int64_t r;\n"
7815 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7816 | RString _ -> pr " char *r;\n"
7817 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7818 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7819 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7822 pr " size_t size;\n";
7828 | OptString n -> pr " const char *%s;\n" n
7832 | FileOut n -> pr " char *%s;\n" n
7834 pr " const char *%s;\n" n;
7835 pr " size_t %s_size;\n" n
7836 | StringList n | DeviceList n -> pr " char **%s;\n" n
7837 | Bool n -> pr " int %s;\n" n
7838 | Int n -> pr " int %s;\n" n
7839 | Int64 n -> pr " int64_t %s;\n" n
7842 (* Check and convert parameters. *)
7843 let argc_expected = List.length (snd style) in
7844 pr " if (argc != %d) {\n" argc_expected;
7845 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7847 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7851 let parse_integer fn fntyp rtyp range name i =
7853 pr " strtol_error xerr;\n";
7854 pr " %s r;\n" fntyp;
7856 pr " xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7857 pr " if (xerr != LONGINT_OK) {\n";
7858 pr " fprintf (stderr,\n";
7859 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7860 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7865 | Some (min, max, comment) ->
7866 pr " /* %s */\n" comment;
7867 pr " if (r < %s || r > %s) {\n" min max;
7868 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7872 pr " /* The check above should ensure this assignment does not overflow. */\n";
7874 pr " %s = r;\n" name;
7883 pr " %s = argv[%d];\n" name i
7885 | Dev_or_Path name ->
7886 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7887 pr " if (%s == NULL) return -1;\n" name
7889 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7892 pr " %s = argv[%d];\n" name i;
7893 pr " %s_size = strlen (argv[%d]);\n" name i
7895 pr " %s = file_in (argv[%d]);\n" name i;
7896 pr " if (%s == NULL) return -1;\n" name
7898 pr " %s = file_out (argv[%d]);\n" name i;
7899 pr " if (%s == NULL) return -1;\n" name
7900 | StringList name | DeviceList name ->
7901 pr " %s = parse_string_list (argv[%d]);\n" name i;
7902 pr " if (%s == NULL) return -1;\n" name;
7904 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7907 let min = "(-(2LL<<30))"
7908 and max = "((2LL<<30)-1)"
7910 "The Int type in the generator is a signed 31 bit int." in
7911 Some (min, max, comment) in
7912 parse_integer "xstrtoll" "long long" "int" range name i
7914 parse_integer "xstrtoll" "long long" "int64_t" None name i
7917 (* Call C API function. *)
7918 pr " r = guestfs_%s " name;
7919 generate_c_call_args ~handle:"g" style;
7924 | Device _ | String _
7925 | OptString _ | Bool _
7928 | Pathname name | Dev_or_Path name | FileOut name ->
7929 pr " free (%s);\n" name
7931 pr " free_file_in (%s);\n" name
7932 | StringList name | DeviceList name ->
7933 pr " free_strings (%s);\n" name
7936 (* Any output flags? *)
7938 let flags = filter_map (
7939 function FishOutput flag -> Some flag | _ -> None
7945 failwithf "%s: more than one FishOutput flag is not allowed" name in
7947 (* Check return value for errors and display command results. *)
7948 (match fst style with
7949 | RErr -> pr " return r;\n"
7951 pr " if (r == -1) return -1;\n";
7952 (match fish_output with
7954 pr " printf (\"%%d\\n\", r);\n";
7955 | Some FishOutputOctal ->
7956 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7957 | Some FishOutputHexadecimal ->
7958 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7961 pr " if (r == -1) return -1;\n";
7962 (match fish_output with
7964 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7965 | Some FishOutputOctal ->
7966 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7967 | Some FishOutputHexadecimal ->
7968 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7971 pr " if (r == -1) return -1;\n";
7972 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7975 pr " if (r == NULL) return -1;\n";
7976 pr " printf (\"%%s\\n\", r);\n";
7978 | RConstOptString _ ->
7979 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7982 pr " if (r == NULL) return -1;\n";
7983 pr " printf (\"%%s\\n\", r);\n";
7987 pr " if (r == NULL) return -1;\n";
7988 pr " print_strings (r);\n";
7989 pr " free_strings (r);\n";
7991 | RStruct (_, typ) ->
7992 pr " if (r == NULL) return -1;\n";
7993 pr " print_%s (r);\n" typ;
7994 pr " guestfs_free_%s (r);\n" typ;
7996 | RStructList (_, typ) ->
7997 pr " if (r == NULL) return -1;\n";
7998 pr " print_%s_list (r);\n" typ;
7999 pr " guestfs_free_%s_list (r);\n" typ;
8002 pr " if (r == NULL) return -1;\n";
8003 pr " print_table (r);\n";
8004 pr " free_strings (r);\n";
8007 pr " if (r == NULL) return -1;\n";
8008 pr " if (full_write (1, r, size) != size) {\n";
8009 pr " perror (\"write\");\n";
8020 (* run_action function *)
8021 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8024 fun (name, _, _, flags, _, _, _) ->
8025 let name2 = replace_char name '_' '-' in
8027 try find_map (function FishAlias n -> Some n | _ -> None) flags
8028 with Not_found -> name in
8030 pr "STRCASEEQ (cmd, \"%s\")" name;
8031 if name <> name2 then
8032 pr " || STRCASEEQ (cmd, \"%s\")" name2;
8033 if name <> alias then
8034 pr " || STRCASEEQ (cmd, \"%s\")" alias;
8036 pr " return run_%s (cmd, argc, argv);\n" name;
8040 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8041 pr " if (command_num == 1)\n";
8042 pr " extended_help_message ();\n";
8049 (* Readline completion for guestfish. *)
8050 and generate_fish_completion () =
8051 generate_header CStyle GPLv2plus;
8055 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8065 #ifdef HAVE_LIBREADLINE
8066 #include <readline/readline.h>
8071 #ifdef HAVE_LIBREADLINE
8073 static const char *const commands[] = {
8074 BUILTIN_COMMANDS_FOR_COMPLETION,
8077 (* Get the commands, including the aliases. They don't need to be
8078 * sorted - the generator() function just does a dumb linear search.
8082 fun (name, _, _, flags, _, _, _) ->
8083 let name2 = replace_char name '_' '-' in
8085 try find_map (function FishAlias n -> Some n | _ -> None) flags
8086 with Not_found -> name in
8088 if name <> alias then [name2; alias] else [name2]
8090 let commands = List.flatten commands in
8092 List.iter (pr " \"%s\",\n") commands;
8098 generator (const char *text, int state)
8100 static size_t index, len;
8105 len = strlen (text);
8108 rl_attempted_completion_over = 1;
8110 while ((name = commands[index]) != NULL) {
8112 if (STRCASEEQLEN (name, text, len))
8113 return strdup (name);
8119 #endif /* HAVE_LIBREADLINE */
8121 #ifdef HAVE_RL_COMPLETION_MATCHES
8122 #define RL_COMPLETION_MATCHES rl_completion_matches
8124 #ifdef HAVE_COMPLETION_MATCHES
8125 #define RL_COMPLETION_MATCHES completion_matches
8127 #endif /* else just fail if we don't have either symbol */
8130 do_completion (const char *text, int start, int end)
8132 char **matches = NULL;
8134 #ifdef HAVE_LIBREADLINE
8135 rl_completion_append_character = ' ';
8138 matches = RL_COMPLETION_MATCHES (text, generator);
8139 else if (complete_dest_paths)
8140 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8147 (* Generate the POD documentation for guestfish. *)
8148 and generate_fish_actions_pod () =
8149 let all_functions_sorted =
8151 fun (_, _, _, flags, _, _, _) ->
8152 not (List.mem NotInFish flags || List.mem NotInDocs flags)
8153 ) all_functions_sorted in
8155 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8158 fun (name, style, _, flags, _, _, longdesc) ->
8160 Str.global_substitute rex (
8163 try Str.matched_group 1 s
8165 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8166 "C<" ^ replace_char sub '_' '-' ^ ">"
8168 let name = replace_char name '_' '-' in
8170 try find_map (function FishAlias n -> Some n | _ -> None) flags
8171 with Not_found -> name in
8173 pr "=head2 %s" name;
8174 if name <> alias then
8181 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8182 | OptString n -> pr " %s" n
8183 | StringList n | DeviceList n -> pr " '%s ...'" n
8184 | Bool _ -> pr " true|false"
8185 | Int n -> pr " %s" n
8186 | Int64 n -> pr " %s" n
8187 | FileIn n | FileOut n -> pr " (%s|-)" n
8188 | BufferIn n -> pr " %s" n
8192 pr "%s\n\n" longdesc;
8194 if List.exists (function FileIn _ | FileOut _ -> true
8195 | _ -> false) (snd style) then
8196 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8198 if List.mem ProtocolLimitWarning flags then
8199 pr "%s\n\n" protocol_limit_warning;
8201 if List.mem DangerWillRobinson flags then
8202 pr "%s\n\n" danger_will_robinson;
8204 match deprecation_notice flags with
8206 | Some txt -> pr "%s\n\n" txt
8207 ) all_functions_sorted
8209 (* Generate a C function prototype. *)
8210 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8211 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8213 ?handle name style =
8214 if extern then pr "extern ";
8215 if static then pr "static ";
8216 (match fst style with
8218 | RInt _ -> pr "int "
8219 | RInt64 _ -> pr "int64_t "
8220 | RBool _ -> pr "int "
8221 | RConstString _ | RConstOptString _ -> pr "const char *"
8222 | RString _ | RBufferOut _ -> pr "char *"
8223 | RStringList _ | RHashtable _ -> pr "char **"
8224 | RStruct (_, typ) ->
8225 if not in_daemon then pr "struct guestfs_%s *" typ
8226 else pr "guestfs_int_%s *" typ
8227 | RStructList (_, typ) ->
8228 if not in_daemon then pr "struct guestfs_%s_list *" typ
8229 else pr "guestfs_int_%s_list *" typ
8231 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8232 pr "%s%s (" prefix name;
8233 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8236 let comma = ref false in
8239 | Some handle -> pr "guestfs_h *%s" handle; comma := true
8243 if single_line then pr ", " else pr ",\n\t\t"
8250 | Device n | Dev_or_Path n
8254 pr "const char *%s" n
8255 | StringList n | DeviceList n ->
8257 pr "char *const *%s" n
8258 | Bool n -> next (); pr "int %s" n
8259 | Int n -> next (); pr "int %s" n
8260 | Int64 n -> next (); pr "int64_t %s" n
8263 if not in_daemon then (next (); pr "const char *%s" n)
8266 pr "const char *%s" n;
8268 pr "size_t %s_size" n
8270 if is_RBufferOut then (next (); pr "size_t *size_r");
8273 if semicolon then pr ";";
8274 if newline then pr "\n"
8276 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8277 and generate_c_call_args ?handle ?(decl = false) style =
8279 let comma = ref false in
8281 if !comma then pr ", ";
8286 | Some handle -> pr "%s" handle; comma := true
8292 pr "%s, %s_size" n n
8295 pr "%s" (name_of_argt arg)
8297 (* For RBufferOut calls, add implicit &size parameter. *)
8299 match fst style with
8307 (* Generate the OCaml bindings interface. *)
8308 and generate_ocaml_mli () =
8309 generate_header OCamlStyle LGPLv2plus;
8312 (** For API documentation you should refer to the C API
8313 in the guestfs(3) manual page. The OCaml API uses almost
8314 exactly the same calls. *)
8317 (** A [guestfs_h] handle. *)
8319 exception Error of string
8320 (** This exception is raised when there is an error. *)
8322 exception Handle_closed of string
8323 (** This exception is raised if you use a {!Guestfs.t} handle
8324 after calling {!close} on it. The string is the name of
8327 val create : unit -> t
8328 (** Create a {!Guestfs.t} handle. *)
8330 val close : t -> unit
8331 (** Close the {!Guestfs.t} handle and free up all resources used
8334 Handles are closed by the garbage collector when they become
8335 unreferenced, but callers can call this in order to provide
8336 predictable cleanup. *)
8339 generate_ocaml_structure_decls ();
8343 fun (name, style, _, _, _, shortdesc, _) ->
8344 generate_ocaml_prototype name style;
8345 pr "(** %s *)\n" shortdesc;
8347 ) all_functions_sorted
8349 (* Generate the OCaml bindings implementation. *)
8350 and generate_ocaml_ml () =
8351 generate_header OCamlStyle LGPLv2plus;
8356 exception Error of string
8357 exception Handle_closed of string
8359 external create : unit -> t = \"ocaml_guestfs_create\"
8360 external close : t -> unit = \"ocaml_guestfs_close\"
8362 (* Give the exceptions names, so they can be raised from the C code. *)
8364 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8365 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8369 generate_ocaml_structure_decls ();
8373 fun (name, style, _, _, _, shortdesc, _) ->
8374 generate_ocaml_prototype ~is_external:true name style;
8375 ) all_functions_sorted
8377 (* Generate the OCaml bindings C implementation. *)
8378 and generate_ocaml_c () =
8379 generate_header CStyle LGPLv2plus;
8386 #include <caml/config.h>
8387 #include <caml/alloc.h>
8388 #include <caml/callback.h>
8389 #include <caml/fail.h>
8390 #include <caml/memory.h>
8391 #include <caml/mlvalues.h>
8392 #include <caml/signals.h>
8394 #include \"guestfs.h\"
8396 #include \"guestfs_c.h\"
8398 /* Copy a hashtable of string pairs into an assoc-list. We return
8399 * the list in reverse order, but hashtables aren't supposed to be
8402 static CAMLprim value
8403 copy_table (char * const * argv)
8406 CAMLlocal5 (rv, pairv, kv, vv, cons);
8410 for (i = 0; argv[i] != NULL; i += 2) {
8411 kv = caml_copy_string (argv[i]);
8412 vv = caml_copy_string (argv[i+1]);
8413 pairv = caml_alloc (2, 0);
8414 Store_field (pairv, 0, kv);
8415 Store_field (pairv, 1, vv);
8416 cons = caml_alloc (2, 0);
8417 Store_field (cons, 1, rv);
8419 Store_field (cons, 0, pairv);
8427 (* Struct copy functions. *)
8429 let emit_ocaml_copy_list_function typ =
8430 pr "static CAMLprim value\n";
8431 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8433 pr " CAMLparam0 ();\n";
8434 pr " CAMLlocal2 (rv, v);\n";
8435 pr " unsigned int i;\n";
8437 pr " if (%ss->len == 0)\n" typ;
8438 pr " CAMLreturn (Atom (0));\n";
8440 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8441 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8442 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8443 pr " caml_modify (&Field (rv, i), v);\n";
8445 pr " CAMLreturn (rv);\n";
8453 let has_optpercent_col =
8454 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8456 pr "static CAMLprim value\n";
8457 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8459 pr " CAMLparam0 ();\n";
8460 if has_optpercent_col then
8461 pr " CAMLlocal3 (rv, v, v2);\n"
8463 pr " CAMLlocal2 (rv, v);\n";
8465 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8470 pr " v = caml_copy_string (%s->%s);\n" typ name
8472 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8473 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8476 pr " v = caml_alloc_string (32);\n";
8477 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8478 | name, (FBytes|FInt64|FUInt64) ->
8479 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8480 | name, (FInt32|FUInt32) ->
8481 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8482 | name, FOptPercent ->
8483 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8484 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8485 pr " v = caml_alloc (1, 0);\n";
8486 pr " Store_field (v, 0, v2);\n";
8487 pr " } else /* None */\n";
8488 pr " v = Val_int (0);\n";
8490 pr " v = Val_int (%s->%s);\n" typ name
8492 pr " Store_field (rv, %d, v);\n" i
8494 pr " CAMLreturn (rv);\n";
8499 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8502 | typ, (RStructListOnly | RStructAndList) ->
8503 (* generate the function for typ *)
8504 emit_ocaml_copy_list_function typ
8505 | typ, _ -> () (* empty *)
8506 ) (rstructs_used_by all_functions);
8510 fun (name, style, _, _, _, _, _) ->
8511 pr "/* Automatically generated wrapper for function\n";
8513 generate_ocaml_prototype name style;
8518 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8520 let needs_extra_vs =
8521 match fst style with RConstOptString _ -> true | _ -> false in
8523 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8524 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8525 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8528 pr "CAMLprim value\n";
8529 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8530 List.iter (pr ", value %s") (List.tl params);
8535 | [p1; p2; p3; p4; p5] ->
8536 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8537 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8538 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8539 pr " CAMLxparam%d (%s);\n"
8540 (List.length rest) (String.concat ", " rest)
8542 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8544 if not needs_extra_vs then
8545 pr " CAMLlocal1 (rv);\n"
8547 pr " CAMLlocal3 (rv, v, v2);\n";
8550 pr " guestfs_h *g = Guestfs_val (gv);\n";
8551 pr " if (g == NULL)\n";
8552 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8558 | Device n | Dev_or_Path n
8562 (* Copy strings in case the GC moves them: RHBZ#604691 *)
8563 pr " char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8565 pr " char *%s =\n" n;
8566 pr " %sv != Val_int (0) ?" n;
8567 pr " guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8569 pr " size_t %s_size = caml_string_length (%sv);\n" n n;
8570 pr " char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8571 | StringList n | DeviceList n ->
8572 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8574 pr " int %s = Bool_val (%sv);\n" n n
8576 pr " int %s = Int_val (%sv);\n" n n
8578 pr " int64_t %s = Int64_val (%sv);\n" n n
8581 match fst style with
8582 | RErr -> pr " int r;\n"; "-1"
8583 | RInt _ -> pr " int r;\n"; "-1"
8584 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8585 | RBool _ -> pr " int r;\n"; "-1"
8586 | RConstString _ | RConstOptString _ ->
8587 pr " const char *r;\n"; "NULL"
8588 | RString _ -> pr " char *r;\n"; "NULL"
8593 | RStruct (_, typ) ->
8594 pr " struct guestfs_%s *r;\n" typ; "NULL"
8595 | RStructList (_, typ) ->
8596 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8603 pr " size_t size;\n";
8607 pr " caml_enter_blocking_section ();\n";
8608 pr " r = guestfs_%s " name;
8609 generate_c_call_args ~handle:"g" style;
8611 pr " caml_leave_blocking_section ();\n";
8613 (* Free strings if we copied them above. *)
8616 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8617 | FileIn n | FileOut n | BufferIn n ->
8618 pr " free (%s);\n" n
8619 | StringList n | DeviceList n ->
8620 pr " ocaml_guestfs_free_strings (%s);\n" n;
8621 | Bool _ | Int _ | Int64 _ -> ()
8624 pr " if (r == %s)\n" error_code;
8625 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8628 (match fst style with
8629 | RErr -> pr " rv = Val_unit;\n"
8630 | RInt _ -> pr " rv = Val_int (r);\n"
8632 pr " rv = caml_copy_int64 (r);\n"
8633 | RBool _ -> pr " rv = Val_bool (r);\n"
8635 pr " rv = caml_copy_string (r);\n"
8636 | RConstOptString _ ->
8637 pr " if (r) { /* Some string */\n";
8638 pr " v = caml_alloc (1, 0);\n";
8639 pr " v2 = caml_copy_string (r);\n";
8640 pr " Store_field (v, 0, v2);\n";
8641 pr " } else /* None */\n";
8642 pr " v = Val_int (0);\n";
8644 pr " rv = caml_copy_string (r);\n";
8647 pr " rv = caml_copy_string_array ((const char **) r);\n";
8648 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8650 | RStruct (_, typ) ->
8651 pr " rv = copy_%s (r);\n" typ;
8652 pr " guestfs_free_%s (r);\n" typ;
8653 | RStructList (_, typ) ->
8654 pr " rv = copy_%s_list (r);\n" typ;
8655 pr " guestfs_free_%s_list (r);\n" typ;
8657 pr " rv = copy_table (r);\n";
8658 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8661 pr " rv = caml_alloc_string (size);\n";
8662 pr " memcpy (String_val (rv), r, size);\n";
8665 pr " CAMLreturn (rv);\n";
8669 if List.length params > 5 then (
8670 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8671 pr "CAMLprim value ";
8672 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8673 pr "CAMLprim value\n";
8674 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8676 pr " return ocaml_guestfs_%s (argv[0]" name;
8677 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8682 ) all_functions_sorted
8684 and generate_ocaml_structure_decls () =
8687 pr "type %s = {\n" typ;
8690 | name, FString -> pr " %s : string;\n" name
8691 | name, FBuffer -> pr " %s : string;\n" name
8692 | name, FUUID -> pr " %s : string;\n" name
8693 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8694 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8695 | name, FChar -> pr " %s : char;\n" name
8696 | name, FOptPercent -> pr " %s : float option;\n" name
8702 and generate_ocaml_prototype ?(is_external = false) name style =
8703 if is_external then pr "external " else pr "val ";
8704 pr "%s : t -> " name;
8707 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8708 | BufferIn _ -> pr "string -> "
8709 | OptString _ -> pr "string option -> "
8710 | StringList _ | DeviceList _ -> pr "string array -> "
8711 | Bool _ -> pr "bool -> "
8712 | Int _ -> pr "int -> "
8713 | Int64 _ -> pr "int64 -> "
8715 (match fst style with
8716 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8717 | RInt _ -> pr "int"
8718 | RInt64 _ -> pr "int64"
8719 | RBool _ -> pr "bool"
8720 | RConstString _ -> pr "string"
8721 | RConstOptString _ -> pr "string option"
8722 | RString _ | RBufferOut _ -> pr "string"
8723 | RStringList _ -> pr "string array"
8724 | RStruct (_, typ) -> pr "%s" typ
8725 | RStructList (_, typ) -> pr "%s array" typ
8726 | RHashtable _ -> pr "(string * string) list"
8728 if is_external then (
8730 if List.length (snd style) + 1 > 5 then
8731 pr "\"ocaml_guestfs_%s_byte\" " name;
8732 pr "\"ocaml_guestfs_%s\"" name
8736 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8737 and generate_perl_xs () =
8738 generate_header CStyle LGPLv2plus;
8741 #include \"EXTERN.h\"
8745 #include <guestfs.h>
8748 #define PRId64 \"lld\"
8752 my_newSVll(long long val) {
8753 #ifdef USE_64_BIT_ALL
8754 return newSViv(val);
8758 len = snprintf(buf, 100, \"%%\" PRId64, val);
8759 return newSVpv(buf, len);
8764 #define PRIu64 \"llu\"
8768 my_newSVull(unsigned long long val) {
8769 #ifdef USE_64_BIT_ALL
8770 return newSVuv(val);
8774 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8775 return newSVpv(buf, len);
8779 /* http://www.perlmonks.org/?node_id=680842 */
8781 XS_unpack_charPtrPtr (SV *arg) {
8786 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8787 croak (\"array reference expected\");
8789 av = (AV *)SvRV (arg);
8790 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8792 croak (\"malloc failed\");
8794 for (i = 0; i <= av_len (av); i++) {
8795 SV **elem = av_fetch (av, i, 0);
8797 if (!elem || !*elem)
8798 croak (\"missing element in list\");
8800 ret[i] = SvPV_nolen (*elem);
8808 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8815 RETVAL = guestfs_create ();
8817 croak (\"could not create guestfs handle\");
8818 guestfs_set_error_handler (RETVAL, NULL, NULL);
8826 /* For the 'g' argument above we do the conversion explicitly and
8827 * don't rely on the typemap, because if the handle has been
8828 * explicitly closed we don't want the typemap conversion to
8831 HV *hv = (HV *) SvRV (sv);
8832 SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8834 guestfs_h *g = (guestfs_h *) SvIV (*svp);
8844 /* Avoid double-free in DESTROY method. */
8845 HV *hv = (HV *) SvRV (ST(0));
8846 (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8851 fun (name, style, _, _, _, _, _) ->
8852 (match fst style with
8853 | RErr -> pr "void\n"
8854 | RInt _ -> pr "SV *\n"
8855 | RInt64 _ -> pr "SV *\n"
8856 | RBool _ -> pr "SV *\n"
8857 | RConstString _ -> pr "SV *\n"
8858 | RConstOptString _ -> pr "SV *\n"
8859 | RString _ -> pr "SV *\n"
8860 | RBufferOut _ -> pr "SV *\n"
8862 | RStruct _ | RStructList _
8864 pr "void\n" (* all lists returned implictly on the stack *)
8866 (* Call and arguments. *)
8869 fun arg -> pr ", %s" (name_of_argt arg)
8872 pr " guestfs_h *g;\n";
8876 | Pathname n | Device n | Dev_or_Path n | String n
8877 | FileIn n | FileOut n ->
8880 pr " char *%s;\n" n;
8881 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8883 (* http://www.perlmonks.org/?node_id=554277
8884 * Note that the implicit handle argument means we have
8885 * to add 1 to the ST(x) operator.
8887 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8888 | StringList n | DeviceList n -> pr " char **%s;\n" n
8889 | Bool n -> pr " int %s;\n" n
8890 | Int n -> pr " int %s;\n" n
8891 | Int64 n -> pr " int64_t %s;\n" n
8894 let do_cleanups () =
8897 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8898 | Bool _ | Int _ | Int64 _
8899 | FileIn _ | FileOut _
8901 | StringList n | DeviceList n -> pr " free (%s);\n" n
8906 (match fst style with
8911 pr " r = guestfs_%s " name;
8912 generate_c_call_args ~handle:"g" style;
8915 pr " if (r == -1)\n";
8916 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8922 pr " %s = guestfs_%s " n name;
8923 generate_c_call_args ~handle:"g" style;
8926 pr " if (%s == -1)\n" n;
8927 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8928 pr " RETVAL = newSViv (%s);\n" n;
8933 pr " int64_t %s;\n" n;
8935 pr " %s = guestfs_%s " n name;
8936 generate_c_call_args ~handle:"g" style;
8939 pr " if (%s == -1)\n" n;
8940 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8941 pr " RETVAL = my_newSVll (%s);\n" n;
8946 pr " const char *%s;\n" n;
8948 pr " %s = guestfs_%s " n name;
8949 generate_c_call_args ~handle:"g" style;
8952 pr " if (%s == NULL)\n" n;
8953 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8954 pr " RETVAL = newSVpv (%s, 0);\n" n;
8957 | RConstOptString n ->
8959 pr " const char *%s;\n" n;
8961 pr " %s = guestfs_%s " n name;
8962 generate_c_call_args ~handle:"g" style;
8965 pr " if (%s == NULL)\n" n;
8966 pr " RETVAL = &PL_sv_undef;\n";
8968 pr " RETVAL = newSVpv (%s, 0);\n" n;
8973 pr " char *%s;\n" n;
8975 pr " %s = guestfs_%s " n name;
8976 generate_c_call_args ~handle:"g" style;
8979 pr " if (%s == NULL)\n" n;
8980 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8981 pr " RETVAL = newSVpv (%s, 0);\n" n;
8982 pr " free (%s);\n" n;
8985 | RStringList n | RHashtable n ->
8987 pr " char **%s;\n" n;
8988 pr " size_t i, n;\n";
8990 pr " %s = guestfs_%s " n name;
8991 generate_c_call_args ~handle:"g" style;
8994 pr " if (%s == NULL)\n" n;
8995 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8996 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8997 pr " EXTEND (SP, n);\n";
8998 pr " for (i = 0; i < n; ++i) {\n";
8999 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9000 pr " free (%s[i]);\n" n;
9002 pr " free (%s);\n" n;
9003 | RStruct (n, typ) ->
9004 let cols = cols_of_struct typ in
9005 generate_perl_struct_code typ cols name style n do_cleanups
9006 | RStructList (n, typ) ->
9007 let cols = cols_of_struct typ in
9008 generate_perl_struct_list_code typ cols name style n do_cleanups
9011 pr " char *%s;\n" n;
9012 pr " size_t size;\n";
9014 pr " %s = guestfs_%s " n name;
9015 generate_c_call_args ~handle:"g" style;
9018 pr " if (%s == NULL)\n" n;
9019 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9020 pr " RETVAL = newSVpvn (%s, size);\n" n;
9021 pr " free (%s);\n" n;
9029 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9031 pr " struct guestfs_%s_list *%s;\n" typ n;
9035 pr " %s = guestfs_%s " n name;
9036 generate_c_call_args ~handle:"g" style;
9039 pr " if (%s == NULL)\n" n;
9040 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9041 pr " EXTEND (SP, %s->len);\n" n;
9042 pr " for (i = 0; i < %s->len; ++i) {\n" n;
9043 pr " hv = newHV ();\n";
9047 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9048 name (String.length name) n name
9050 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9051 name (String.length name) n name
9053 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9054 name (String.length name) n name n name
9055 | name, (FBytes|FUInt64) ->
9056 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9057 name (String.length name) n name
9059 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9060 name (String.length name) n name
9061 | name, (FInt32|FUInt32) ->
9062 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9063 name (String.length name) n name
9065 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9066 name (String.length name) n name
9067 | name, FOptPercent ->
9068 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9069 name (String.length name) n name
9071 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9073 pr " guestfs_free_%s_list (%s);\n" typ n
9075 and generate_perl_struct_code typ cols name style n do_cleanups =
9077 pr " struct guestfs_%s *%s;\n" typ n;
9079 pr " %s = guestfs_%s " n name;
9080 generate_c_call_args ~handle:"g" style;
9083 pr " if (%s == NULL)\n" n;
9084 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9085 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
9087 fun ((name, _) as col) ->
9088 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9092 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9095 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9098 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9100 | name, (FBytes|FUInt64) ->
9101 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9104 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9106 | name, (FInt32|FUInt32) ->
9107 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9110 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9112 | name, FOptPercent ->
9113 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9116 pr " free (%s);\n" n
9118 (* Generate Sys/Guestfs.pm. *)
9119 and generate_perl_pm () =
9120 generate_header HashStyle LGPLv2plus;
9127 Sys::Guestfs - Perl bindings for libguestfs
9133 my $h = Sys::Guestfs->new ();
9134 $h->add_drive ('guest.img');
9136 $h->mount ('/dev/sda1', '/');
9137 $h->touch ('/hello');
9142 The C<Sys::Guestfs> module provides a Perl XS binding to the
9143 libguestfs API for examining and modifying virtual machine
9146 Amongst the things this is good for: making batch configuration
9147 changes to guests, getting disk used/free statistics (see also:
9148 virt-df), migrating between virtualization systems (see also:
9149 virt-p2v), performing partial backups, performing partial guest
9150 clones, cloning guests and changing registry/UUID/hostname info, and
9153 Libguestfs uses Linux kernel and qemu code, and can access any type of
9154 guest filesystem that Linux and qemu can, including but not limited
9155 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9156 schemes, qcow, qcow2, vmdk.
9158 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9159 LVs, what filesystem is in each LV, etc.). It can also run commands
9160 in the context of the guest. Also you can access filesystems over
9163 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9164 functions for using libguestfs from Perl, including integration
9169 All errors turn into calls to C<croak> (see L<Carp(3)>).
9177 package Sys::Guestfs;
9182 # This version number changes whenever a new function
9183 # is added to the libguestfs API. It is not directly
9184 # related to the libguestfs version number.
9185 use vars qw($VERSION);
9189 XSLoader::load ('Sys::Guestfs');
9191 =item $h = Sys::Guestfs->new ();
9193 Create a new guestfs handle.
9199 my $class = ref ($proto) || $proto;
9201 my $g = Sys::Guestfs::_create ();
9202 my $self = { _g => $g };
9203 bless $self, $class;
9209 Explicitly close the guestfs handle.
9211 B<Note:> You should not usually call this function. The handle will
9212 be closed implicitly when its reference count goes to zero (eg.
9213 when it goes out of scope or the program ends). This call is
9214 only required in some exceptional cases, such as where the program
9215 may contain cached references to the handle 'somewhere' and you
9216 really have to have the close happen right away. After calling
9217 C<close> the program must not call any method (including C<close>)
9218 on the handle (but the implicit call to C<DESTROY> that happens
9219 when the final reference is cleaned up is OK).
9225 (* Actions. We only need to print documentation for these as
9226 * they are pulled in from the XS code automatically.
9229 fun (name, style, _, flags, _, _, longdesc) ->
9230 if not (List.mem NotInDocs flags) then (
9231 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9233 generate_perl_prototype name style;
9235 pr "%s\n\n" longdesc;
9236 if List.mem ProtocolLimitWarning flags then
9237 pr "%s\n\n" protocol_limit_warning;
9238 if List.mem DangerWillRobinson flags then
9239 pr "%s\n\n" danger_will_robinson;
9240 match deprecation_notice flags with
9242 | Some txt -> pr "%s\n\n" txt
9244 ) all_functions_sorted;
9256 Copyright (C) %s Red Hat Inc.
9260 Please see the file COPYING.LIB for the full license.
9266 L<http://libguestfs.org>,
9267 L<Sys::Guestfs::Lib(3)>.
9272 and generate_perl_prototype name style =
9273 (match fst style with
9281 | RBufferOut n -> pr "$%s = " n
9283 | RHashtable n -> pr "%%%s = " n
9285 | RStructList (n,_) -> pr "@%s = " n
9288 let comma = ref false in
9291 if !comma then pr ", ";
9294 | Pathname n | Device n | Dev_or_Path n | String n
9295 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9298 | StringList n | DeviceList n ->
9303 (* Generate Python C module. *)
9304 and generate_python_c () =
9305 generate_header CStyle LGPLv2plus;
9308 #define PY_SSIZE_T_CLEAN 1
9311 #if PY_VERSION_HEX < 0x02050000
9312 typedef int Py_ssize_t;
9313 #define PY_SSIZE_T_MAX INT_MAX
9314 #define PY_SSIZE_T_MIN INT_MIN
9321 #include \"guestfs.h\"
9329 get_handle (PyObject *obj)
9332 assert (obj != Py_None);
9333 return ((Pyguestfs_Object *) obj)->g;
9337 put_handle (guestfs_h *g)
9341 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9344 /* This list should be freed (but not the strings) after use. */
9346 get_string_list (PyObject *obj)
9353 if (!PyList_Check (obj)) {
9354 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9358 Py_ssize_t slen = PyList_Size (obj);
9360 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9363 len = (size_t) slen;
9364 r = malloc (sizeof (char *) * (len+1));
9366 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9370 for (i = 0; i < len; ++i)
9371 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9378 put_string_list (char * const * const argv)
9383 for (argc = 0; argv[argc] != NULL; ++argc)
9386 list = PyList_New (argc);
9387 for (i = 0; i < argc; ++i)
9388 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9394 put_table (char * const * const argv)
9396 PyObject *list, *item;
9399 for (argc = 0; argv[argc] != NULL; ++argc)
9402 list = PyList_New (argc >> 1);
9403 for (i = 0; i < argc; i += 2) {
9404 item = PyTuple_New (2);
9405 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9406 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9407 PyList_SetItem (list, i >> 1, item);
9414 free_strings (char **argv)
9418 for (argc = 0; argv[argc] != NULL; ++argc)
9424 py_guestfs_create (PyObject *self, PyObject *args)
9428 g = guestfs_create ();
9430 PyErr_SetString (PyExc_RuntimeError,
9431 \"guestfs.create: failed to allocate handle\");
9434 guestfs_set_error_handler (g, NULL, NULL);
9435 return put_handle (g);
9439 py_guestfs_close (PyObject *self, PyObject *args)
9444 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9446 g = get_handle (py_g);
9450 Py_INCREF (Py_None);
9456 let emit_put_list_function typ =
9457 pr "static PyObject *\n";
9458 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9460 pr " PyObject *list;\n";
9463 pr " list = PyList_New (%ss->len);\n" typ;
9464 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9465 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9466 pr " return list;\n";
9471 (* Structures, turned into Python dictionaries. *)
9474 pr "static PyObject *\n";
9475 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9477 pr " PyObject *dict;\n";
9479 pr " dict = PyDict_New ();\n";
9483 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9484 pr " PyString_FromString (%s->%s));\n"
9487 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9488 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9491 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9492 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9494 | name, (FBytes|FUInt64) ->
9495 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9496 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9499 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9500 pr " PyLong_FromLongLong (%s->%s));\n"
9503 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9504 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9507 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9508 pr " PyLong_FromLong (%s->%s));\n"
9510 | name, FOptPercent ->
9511 pr " if (%s->%s >= 0)\n" typ name;
9512 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9513 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9516 pr " Py_INCREF (Py_None);\n";
9517 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9520 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9521 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9523 pr " return dict;\n";
9529 (* Emit a put_TYPE_list function definition only if that function is used. *)
9532 | typ, (RStructListOnly | RStructAndList) ->
9533 (* generate the function for typ *)
9534 emit_put_list_function typ
9535 | typ, _ -> () (* empty *)
9536 ) (rstructs_used_by all_functions);
9538 (* Python wrapper functions. *)
9540 fun (name, style, _, _, _, _, _) ->
9541 pr "static PyObject *\n";
9542 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9545 pr " PyObject *py_g;\n";
9546 pr " guestfs_h *g;\n";
9547 pr " PyObject *py_r;\n";
9550 match fst style with
9551 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9552 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9553 | RConstString _ | RConstOptString _ ->
9554 pr " const char *r;\n"; "NULL"
9555 | RString _ -> pr " char *r;\n"; "NULL"
9556 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9557 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9558 | RStructList (_, typ) ->
9559 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9562 pr " size_t size;\n";
9567 | Pathname n | Device n | Dev_or_Path n | String n
9568 | FileIn n | FileOut n ->
9569 pr " const char *%s;\n" n
9570 | OptString n -> pr " const char *%s;\n" n
9572 pr " const char *%s;\n" n;
9573 pr " Py_ssize_t %s_size;\n" n
9574 | StringList n | DeviceList n ->
9575 pr " PyObject *py_%s;\n" n;
9576 pr " char **%s;\n" n
9577 | Bool n -> pr " int %s;\n" n
9578 | Int n -> pr " int %s;\n" n
9579 | Int64 n -> pr " long long %s;\n" n
9584 (* Convert the parameters. *)
9585 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9588 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9589 | OptString _ -> pr "z"
9590 | StringList _ | DeviceList _ -> pr "O"
9591 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9593 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9594 * emulate C's int/long/long long in Python?
9596 | BufferIn _ -> pr "s#"
9598 pr ":guestfs_%s\",\n" name;
9602 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9603 | OptString n -> pr ", &%s" n
9604 | StringList n | DeviceList n -> pr ", &py_%s" n
9605 | Bool n -> pr ", &%s" n
9606 | Int n -> pr ", &%s" n
9607 | Int64 n -> pr ", &%s" n
9608 | BufferIn n -> pr ", &%s, &%s_size" n n
9612 pr " return NULL;\n";
9614 pr " g = get_handle (py_g);\n";
9617 | Pathname _ | Device _ | Dev_or_Path _ | String _
9618 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9620 | StringList n | DeviceList n ->
9621 pr " %s = get_string_list (py_%s);\n" n n;
9622 pr " if (!%s) return NULL;\n" n
9627 pr " r = guestfs_%s " name;
9628 generate_c_call_args ~handle:"g" style;
9633 | Pathname _ | Device _ | Dev_or_Path _ | String _
9634 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9636 | StringList n | DeviceList n ->
9637 pr " free (%s);\n" n
9640 pr " if (r == %s) {\n" error_code;
9641 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9642 pr " return NULL;\n";
9646 (match fst style with
9648 pr " Py_INCREF (Py_None);\n";
9649 pr " py_r = Py_None;\n"
9651 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9652 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9653 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9654 | RConstOptString _ ->
9656 pr " py_r = PyString_FromString (r);\n";
9658 pr " Py_INCREF (Py_None);\n";
9659 pr " py_r = Py_None;\n";
9662 pr " py_r = PyString_FromString (r);\n";
9665 pr " py_r = put_string_list (r);\n";
9666 pr " free_strings (r);\n"
9667 | RStruct (_, typ) ->
9668 pr " py_r = put_%s (r);\n" typ;
9669 pr " guestfs_free_%s (r);\n" typ
9670 | RStructList (_, typ) ->
9671 pr " py_r = put_%s_list (r);\n" typ;
9672 pr " guestfs_free_%s_list (r);\n" typ
9674 pr " py_r = put_table (r);\n";
9675 pr " free_strings (r);\n"
9677 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9681 pr " return py_r;\n";
9686 (* Table of functions. *)
9687 pr "static PyMethodDef methods[] = {\n";
9688 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9689 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9691 fun (name, _, _, _, _, _, _) ->
9692 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9695 pr " { NULL, NULL, 0, NULL }\n";
9699 (* Init function. *)
9702 initlibguestfsmod (void)
9704 static int initialized = 0;
9706 if (initialized) return;
9707 Py_InitModule ((char *) \"libguestfsmod\", methods);
9712 (* Generate Python module. *)
9713 and generate_python_py () =
9714 generate_header HashStyle LGPLv2plus;
9717 u\"\"\"Python bindings for libguestfs
9720 g = guestfs.GuestFS ()
9721 g.add_drive (\"guest.img\")
9723 parts = g.list_partitions ()
9725 The guestfs module provides a Python binding to the libguestfs API
9726 for examining and modifying virtual machine disk images.
9728 Amongst the things this is good for: making batch configuration
9729 changes to guests, getting disk used/free statistics (see also:
9730 virt-df), migrating between virtualization systems (see also:
9731 virt-p2v), performing partial backups, performing partial guest
9732 clones, cloning guests and changing registry/UUID/hostname info, and
9735 Libguestfs uses Linux kernel and qemu code, and can access any type of
9736 guest filesystem that Linux and qemu can, including but not limited
9737 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9738 schemes, qcow, qcow2, vmdk.
9740 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9741 LVs, what filesystem is in each LV, etc.). It can also run commands
9742 in the context of the guest. Also you can access filesystems over
9745 Errors which happen while using the API are turned into Python
9746 RuntimeError exceptions.
9748 To create a guestfs handle you usually have to perform the following
9751 # Create the handle, call add_drive at least once, and possibly
9752 # several times if the guest has multiple block devices:
9753 g = guestfs.GuestFS ()
9754 g.add_drive (\"guest.img\")
9756 # Launch the qemu subprocess and wait for it to become ready:
9759 # Now you can issue commands, for example:
9764 import libguestfsmod
9767 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9769 def __init__ (self):
9770 \"\"\"Create a new libguestfs handle.\"\"\"
9771 self._o = libguestfsmod.create ()
9774 libguestfsmod.close (self._o)
9779 fun (name, style, _, flags, _, _, longdesc) ->
9781 generate_py_call_args ~handle:"self" (snd style);
9784 if not (List.mem NotInDocs flags) then (
9785 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9787 match fst style with
9788 | RErr | RInt _ | RInt64 _ | RBool _
9789 | RConstOptString _ | RConstString _
9790 | RString _ | RBufferOut _ -> doc
9792 doc ^ "\n\nThis function returns a list of strings."
9793 | RStruct (_, typ) ->
9794 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9795 | RStructList (_, typ) ->
9796 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9798 doc ^ "\n\nThis function returns a dictionary." in
9800 if List.mem ProtocolLimitWarning flags then
9801 doc ^ "\n\n" ^ protocol_limit_warning
9804 if List.mem DangerWillRobinson flags then
9805 doc ^ "\n\n" ^ danger_will_robinson
9808 match deprecation_notice flags with
9810 | Some txt -> doc ^ "\n\n" ^ txt in
9811 let doc = pod2text ~width:60 name doc in
9812 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9813 let doc = String.concat "\n " doc in
9814 pr " u\"\"\"%s\"\"\"\n" doc;
9816 pr " return libguestfsmod.%s " name;
9817 generate_py_call_args ~handle:"self._o" (snd style);
9822 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9823 and generate_py_call_args ~handle args =
9825 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9828 (* Useful if you need the longdesc POD text as plain text. Returns a
9831 * Because this is very slow (the slowest part of autogeneration),
9832 * we memoize the results.
9834 and pod2text ~width name longdesc =
9835 let key = width, name, longdesc in
9836 try Hashtbl.find pod2text_memo key
9838 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9839 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9841 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9842 let chan = open_process_in cmd in
9843 let lines = ref [] in
9845 let line = input_line chan in
9846 if i = 1 then (* discard the first line of output *)
9849 let line = triml line in
9850 lines := line :: !lines;
9853 let lines = try loop 1 with End_of_file -> List.rev !lines in
9855 (match close_process_in chan with
9858 failwithf "pod2text: process exited with non-zero status (%d)" i
9859 | WSIGNALED i | WSTOPPED i ->
9860 failwithf "pod2text: process signalled or stopped by signal %d" i
9862 Hashtbl.add pod2text_memo key lines;
9863 pod2text_memo_updated ();
9866 (* Generate ruby bindings. *)
9867 and generate_ruby_c () =
9868 generate_header CStyle LGPLv2plus;
9876 #include \"guestfs.h\"
9878 #include \"extconf.h\"
9880 /* For Ruby < 1.9 */
9882 #define RARRAY_LEN(r) (RARRAY((r))->len)
9885 static VALUE m_guestfs; /* guestfs module */
9886 static VALUE c_guestfs; /* guestfs_h handle */
9887 static VALUE e_Error; /* used for all errors */
9889 static void ruby_guestfs_free (void *p)
9892 guestfs_close ((guestfs_h *) p);
9895 static VALUE ruby_guestfs_create (VALUE m)
9899 g = guestfs_create ();
9901 rb_raise (e_Error, \"failed to create guestfs handle\");
9903 /* Don't print error messages to stderr by default. */
9904 guestfs_set_error_handler (g, NULL, NULL);
9906 /* Wrap it, and make sure the close function is called when the
9909 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9912 static VALUE ruby_guestfs_close (VALUE gv)
9915 Data_Get_Struct (gv, guestfs_h, g);
9917 ruby_guestfs_free (g);
9918 DATA_PTR (gv) = NULL;
9926 fun (name, style, _, _, _, _, _) ->
9927 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9928 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9931 pr " guestfs_h *g;\n";
9932 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9934 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9940 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9941 pr " Check_Type (%sv, T_STRING);\n" n;
9942 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9944 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9945 pr " \"%s\", \"%s\");\n" n name
9947 pr " Check_Type (%sv, T_STRING);\n" n;
9948 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
9950 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9951 pr " \"%s\", \"%s\");\n" n name;
9952 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
9954 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9955 | StringList n | DeviceList n ->
9956 pr " char **%s;\n" n;
9957 pr " Check_Type (%sv, T_ARRAY);\n" n;
9959 pr " size_t i, len;\n";
9960 pr " len = RARRAY_LEN (%sv);\n" n;
9961 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9963 pr " for (i = 0; i < len; ++i) {\n";
9964 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9965 pr " %s[i] = StringValueCStr (v);\n" n;
9967 pr " %s[len] = NULL;\n" n;
9970 pr " int %s = RTEST (%sv);\n" n n
9972 pr " int %s = NUM2INT (%sv);\n" n n
9974 pr " long long %s = NUM2LL (%sv);\n" n n
9979 match fst style with
9980 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9981 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9982 | RConstString _ | RConstOptString _ ->
9983 pr " const char *r;\n"; "NULL"
9984 | RString _ -> pr " char *r;\n"; "NULL"
9985 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9986 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9987 | RStructList (_, typ) ->
9988 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9991 pr " size_t size;\n";
9995 pr " r = guestfs_%s " name;
9996 generate_c_call_args ~handle:"g" style;
10001 | Pathname _ | Device _ | Dev_or_Path _ | String _
10002 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10004 | StringList n | DeviceList n ->
10005 pr " free (%s);\n" n
10008 pr " if (r == %s)\n" error_code;
10009 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10012 (match fst style with
10014 pr " return Qnil;\n"
10015 | RInt _ | RBool _ ->
10016 pr " return INT2NUM (r);\n"
10018 pr " return ULL2NUM (r);\n"
10019 | RConstString _ ->
10020 pr " return rb_str_new2 (r);\n";
10021 | RConstOptString _ ->
10023 pr " return rb_str_new2 (r);\n";
10025 pr " return Qnil;\n";
10027 pr " VALUE rv = rb_str_new2 (r);\n";
10029 pr " return rv;\n";
10031 pr " size_t i, len = 0;\n";
10032 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
10033 pr " VALUE rv = rb_ary_new2 (len);\n";
10034 pr " for (i = 0; r[i] != NULL; ++i) {\n";
10035 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10036 pr " free (r[i]);\n";
10040 | RStruct (_, typ) ->
10041 let cols = cols_of_struct typ in
10042 generate_ruby_struct_code typ cols
10043 | RStructList (_, typ) ->
10044 let cols = cols_of_struct typ in
10045 generate_ruby_struct_list_code typ cols
10047 pr " VALUE rv = rb_hash_new ();\n";
10049 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
10050 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10051 pr " free (r[i]);\n";
10052 pr " free (r[i+1]);\n";
10057 pr " VALUE rv = rb_str_new (r, size);\n";
10059 pr " return rv;\n";
10067 /* Initialize the module. */
10068 void Init__guestfs ()
10070 m_guestfs = rb_define_module (\"Guestfs\");
10071 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10072 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10074 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10075 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10078 (* Define the rest of the methods. *)
10080 fun (name, style, _, _, _, _, _) ->
10081 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
10082 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10087 (* Ruby code to return a struct. *)
10088 and generate_ruby_struct_code typ cols =
10089 pr " VALUE rv = rb_hash_new ();\n";
10093 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10095 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10097 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10098 | name, (FBytes|FUInt64) ->
10099 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10101 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10103 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10105 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10106 | name, FOptPercent ->
10107 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10108 | name, FChar -> (* XXX wrong? *)
10109 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10111 pr " guestfs_free_%s (r);\n" typ;
10114 (* Ruby code to return a struct list. *)
10115 and generate_ruby_struct_list_code typ cols =
10116 pr " VALUE rv = rb_ary_new2 (r->len);\n";
10118 pr " for (i = 0; i < r->len; ++i) {\n";
10119 pr " VALUE hv = rb_hash_new ();\n";
10123 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10125 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
10127 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10128 | name, (FBytes|FUInt64) ->
10129 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10131 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10133 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10135 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10136 | name, FOptPercent ->
10137 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10138 | name, FChar -> (* XXX wrong? *)
10139 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10141 pr " rb_ary_push (rv, hv);\n";
10143 pr " guestfs_free_%s_list (r);\n" typ;
10146 (* Generate Java bindings GuestFS.java file. *)
10147 and generate_java_java () =
10148 generate_header CStyle LGPLv2plus;
10151 package com.redhat.et.libguestfs;
10153 import java.util.HashMap;
10154 import com.redhat.et.libguestfs.LibGuestFSException;
10155 import com.redhat.et.libguestfs.PV;
10156 import com.redhat.et.libguestfs.VG;
10157 import com.redhat.et.libguestfs.LV;
10158 import com.redhat.et.libguestfs.Stat;
10159 import com.redhat.et.libguestfs.StatVFS;
10160 import com.redhat.et.libguestfs.IntBool;
10161 import com.redhat.et.libguestfs.Dirent;
10164 * The GuestFS object is a libguestfs handle.
10168 public class GuestFS {
10169 // Load the native code.
10171 System.loadLibrary (\"guestfs_jni\");
10175 * The native guestfs_h pointer.
10180 * Create a libguestfs handle.
10182 * @throws LibGuestFSException
10184 public GuestFS () throws LibGuestFSException
10188 private native long _create () throws LibGuestFSException;
10191 * Close a libguestfs handle.
10193 * You can also leave handles to be collected by the garbage
10194 * collector, but this method ensures that the resources used
10195 * by the handle are freed up immediately. If you call any
10196 * other methods after closing the handle, you will get an
10199 * @throws LibGuestFSException
10201 public void close () throws LibGuestFSException
10207 private native void _close (long g) throws LibGuestFSException;
10209 public void finalize () throws LibGuestFSException
10217 fun (name, style, _, flags, _, shortdesc, longdesc) ->
10218 if not (List.mem NotInDocs flags); then (
10219 let doc = replace_str longdesc "C<guestfs_" "C<g." in
10221 if List.mem ProtocolLimitWarning flags then
10222 doc ^ "\n\n" ^ protocol_limit_warning
10225 if List.mem DangerWillRobinson flags then
10226 doc ^ "\n\n" ^ danger_will_robinson
10229 match deprecation_notice flags with
10231 | Some txt -> doc ^ "\n\n" ^ txt in
10232 let doc = pod2text ~width:60 name doc in
10233 let doc = List.map ( (* RHBZ#501883 *)
10236 | nonempty -> nonempty
10238 let doc = String.concat "\n * " doc in
10241 pr " * %s\n" shortdesc;
10244 pr " * @throws LibGuestFSException\n";
10248 generate_java_prototype ~public:true ~semicolon:false name style;
10251 pr " if (g == 0)\n";
10252 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
10255 if fst style <> RErr then pr "return ";
10257 generate_java_call_args ~handle:"g" (snd style);
10261 generate_java_prototype ~privat:true ~native:true name style;
10268 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10269 and generate_java_call_args ~handle args =
10271 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10274 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10275 ?(semicolon=true) name style =
10276 if privat then pr "private ";
10277 if public then pr "public ";
10278 if native then pr "native ";
10281 (match fst style with
10282 | RErr -> pr "void ";
10283 | RInt _ -> pr "int ";
10284 | RInt64 _ -> pr "long ";
10285 | RBool _ -> pr "boolean ";
10286 | RConstString _ | RConstOptString _ | RString _
10287 | RBufferOut _ -> pr "String ";
10288 | RStringList _ -> pr "String[] ";
10289 | RStruct (_, typ) ->
10290 let name = java_name_of_struct typ in
10292 | RStructList (_, typ) ->
10293 let name = java_name_of_struct typ in
10295 | RHashtable _ -> pr "HashMap<String,String> ";
10298 if native then pr "_%s " name else pr "%s " name;
10300 let needs_comma = ref false in
10303 needs_comma := true
10309 if !needs_comma then pr ", ";
10310 needs_comma := true;
10314 | Device n | Dev_or_Path n
10322 | StringList n | DeviceList n ->
10333 pr " throws LibGuestFSException";
10334 if semicolon then pr ";"
10336 and generate_java_struct jtyp cols () =
10337 generate_header CStyle LGPLv2plus;
10340 package com.redhat.et.libguestfs;
10343 * Libguestfs %s structure.
10355 | name, FBuffer -> pr " public String %s;\n" name
10356 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10357 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10358 | name, FChar -> pr " public char %s;\n" name
10359 | name, FOptPercent ->
10360 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10361 pr " public float %s;\n" name
10366 and generate_java_c () =
10367 generate_header CStyle LGPLv2plus;
10371 #include <stdlib.h>
10372 #include <string.h>
10374 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10375 #include \"guestfs.h\"
10377 /* Note that this function returns. The exception is not thrown
10378 * until after the wrapper function returns.
10381 throw_exception (JNIEnv *env, const char *msg)
10384 cl = (*env)->FindClass (env,
10385 \"com/redhat/et/libguestfs/LibGuestFSException\");
10386 (*env)->ThrowNew (env, cl, msg);
10389 JNIEXPORT jlong JNICALL
10390 Java_com_redhat_et_libguestfs_GuestFS__1create
10391 (JNIEnv *env, jobject obj)
10395 g = guestfs_create ();
10397 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10400 guestfs_set_error_handler (g, NULL, NULL);
10401 return (jlong) (long) g;
10404 JNIEXPORT void JNICALL
10405 Java_com_redhat_et_libguestfs_GuestFS__1close
10406 (JNIEnv *env, jobject obj, jlong jg)
10408 guestfs_h *g = (guestfs_h *) (long) jg;
10415 fun (name, style, _, _, _, _, _) ->
10417 (match fst style with
10418 | RErr -> pr "void ";
10419 | RInt _ -> pr "jint ";
10420 | RInt64 _ -> pr "jlong ";
10421 | RBool _ -> pr "jboolean ";
10422 | RConstString _ | RConstOptString _ | RString _
10423 | RBufferOut _ -> pr "jstring ";
10424 | RStruct _ | RHashtable _ ->
10426 | RStringList _ | RStructList _ ->
10427 pr "jobjectArray ";
10430 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10431 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10433 pr " (JNIEnv *env, jobject obj, jlong jg";
10437 | Device n | Dev_or_Path n
10442 pr ", jstring j%s" n
10444 pr ", jbyteArray j%s" n
10445 | StringList n | DeviceList n ->
10446 pr ", jobjectArray j%s" n
10448 pr ", jboolean j%s" n
10456 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10457 let error_code, no_ret =
10458 match fst style with
10459 | RErr -> pr " int r;\n"; "-1", ""
10461 | RInt _ -> pr " int r;\n"; "-1", "0"
10462 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10463 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10464 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10466 pr " jstring jr;\n";
10467 pr " char *r;\n"; "NULL", "NULL"
10469 pr " jobjectArray jr;\n";
10470 pr " int r_len;\n";
10471 pr " jclass cl;\n";
10472 pr " jstring jstr;\n";
10473 pr " char **r;\n"; "NULL", "NULL"
10474 | RStruct (_, typ) ->
10475 pr " jobject jr;\n";
10476 pr " jclass cl;\n";
10477 pr " jfieldID fl;\n";
10478 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10479 | RStructList (_, typ) ->
10480 pr " jobjectArray jr;\n";
10481 pr " jclass cl;\n";
10482 pr " jfieldID fl;\n";
10483 pr " jobject jfl;\n";
10484 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10485 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10487 pr " jstring jr;\n";
10489 pr " size_t size;\n";
10494 | Device n | Dev_or_Path n
10499 pr " const char *%s;\n" n
10501 pr " jbyte *%s;\n" n;
10502 pr " size_t %s_size;\n" n
10503 | StringList n | DeviceList n ->
10504 pr " int %s_len;\n" n;
10505 pr " const char **%s;\n" n
10510 pr " int64_t %s;\n" n
10514 (match fst style with
10515 | RStringList _ | RStructList _ -> true
10516 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10517 | RConstOptString _
10518 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10519 List.exists (function
10520 | StringList _ -> true
10521 | DeviceList _ -> true
10522 | _ -> false) (snd style) in
10528 (* Get the parameters. *)
10532 | Device n | Dev_or_Path n
10536 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10538 (* This is completely undocumented, but Java null becomes
10539 * a NULL parameter.
10541 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10543 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10544 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10545 | StringList n | DeviceList n ->
10546 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10547 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10548 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10549 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10551 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10553 pr " %s[%s_len] = NULL;\n" n n;
10557 pr " %s = j%s;\n" n n
10560 (* Make the call. *)
10561 pr " r = guestfs_%s " name;
10562 generate_c_call_args ~handle:"g" style;
10565 (* Release the parameters. *)
10569 | Device n | Dev_or_Path n
10573 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10575 pr " if (j%s)\n" n;
10576 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10578 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10579 | StringList n | DeviceList n ->
10580 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10581 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10583 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10585 pr " free (%s);\n" n
10591 (* Check for errors. *)
10592 pr " if (r == %s) {\n" error_code;
10593 pr " throw_exception (env, guestfs_last_error (g));\n";
10594 pr " return %s;\n" no_ret;
10597 (* Return value. *)
10598 (match fst style with
10600 | RInt _ -> pr " return (jint) r;\n"
10601 | RBool _ -> pr " return (jboolean) r;\n"
10602 | RInt64 _ -> pr " return (jlong) r;\n"
10603 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10604 | RConstOptString _ ->
10605 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10607 pr " jr = (*env)->NewStringUTF (env, r);\n";
10611 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10612 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10613 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10614 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10615 pr " for (i = 0; i < r_len; ++i) {\n";
10616 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10617 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10618 pr " free (r[i]);\n";
10622 | RStruct (_, typ) ->
10623 let jtyp = java_name_of_struct typ in
10624 let cols = cols_of_struct typ in
10625 generate_java_struct_return typ jtyp cols
10626 | RStructList (_, typ) ->
10627 let jtyp = java_name_of_struct typ in
10628 let cols = cols_of_struct typ in
10629 generate_java_struct_list_return typ jtyp cols
10632 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10633 pr " return NULL;\n"
10635 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10644 and generate_java_struct_return typ jtyp cols =
10645 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10646 pr " jr = (*env)->AllocObject (env, cl);\n";
10650 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10651 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10654 pr " char s[33];\n";
10655 pr " memcpy (s, r->%s, 32);\n" name;
10656 pr " s[32] = 0;\n";
10657 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10658 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10662 pr " int len = r->%s_len;\n" name;
10663 pr " char s[len+1];\n";
10664 pr " memcpy (s, r->%s, len);\n" name;
10665 pr " s[len] = 0;\n";
10666 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10667 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10669 | name, (FBytes|FUInt64|FInt64) ->
10670 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10671 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10672 | name, (FUInt32|FInt32) ->
10673 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10674 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10675 | name, FOptPercent ->
10676 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10677 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10679 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10680 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10685 and generate_java_struct_list_return typ jtyp cols =
10686 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10687 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10688 pr " for (i = 0; i < r->len; ++i) {\n";
10689 pr " jfl = (*env)->AllocObject (env, cl);\n";
10693 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10694 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10697 pr " char s[33];\n";
10698 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10699 pr " s[32] = 0;\n";
10700 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10701 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10705 pr " int len = r->val[i].%s_len;\n" name;
10706 pr " char s[len+1];\n";
10707 pr " memcpy (s, r->val[i].%s, len);\n" name;
10708 pr " s[len] = 0;\n";
10709 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10710 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10712 | name, (FBytes|FUInt64|FInt64) ->
10713 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10714 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10715 | name, (FUInt32|FInt32) ->
10716 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10717 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10718 | name, FOptPercent ->
10719 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10720 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10722 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10723 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10725 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10727 pr " guestfs_free_%s_list (r);\n" typ;
10730 and generate_java_makefile_inc () =
10731 generate_header HashStyle GPLv2plus;
10733 pr "java_built_sources = \\\n";
10736 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10738 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10740 and generate_haskell_hs () =
10741 generate_header HaskellStyle LGPLv2plus;
10743 (* XXX We only know how to generate partial FFI for Haskell
10744 * at the moment. Please help out!
10746 let can_generate style =
10750 | RInt64 _, _ -> true
10752 | RConstString _, _
10753 | RConstOptString _, _
10759 | RBufferOut _, _ -> false in
10762 {-# INCLUDE <guestfs.h> #-}
10763 {-# LANGUAGE ForeignFunctionInterface #-}
10768 (* List out the names of the actions we want to export. *)
10770 fun (name, style, _, _, _, _, _) ->
10771 if can_generate style then pr ",\n %s" name
10777 -- Unfortunately some symbols duplicate ones already present
10778 -- in Prelude. We don't know which, so we hard-code a list
10780 import Prelude hiding (truncate)
10784 import Foreign.C.Types
10786 import Control.Exception
10787 import Data.Typeable
10789 data GuestfsS = GuestfsS -- represents the opaque C struct
10790 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10791 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10793 -- XXX define properly later XXX
10797 data IntBool = IntBool
10799 data StatVFS = StatVFS
10800 data Hashtable = Hashtable
10802 foreign import ccall unsafe \"guestfs_create\" c_create
10804 foreign import ccall unsafe \"&guestfs_close\" c_close
10805 :: FunPtr (GuestfsP -> IO ())
10806 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10807 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10809 create :: IO GuestfsH
10812 c_set_error_handler p nullPtr nullPtr
10813 h <- newForeignPtr c_close p
10816 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10817 :: GuestfsP -> IO CString
10819 -- last_error :: GuestfsH -> IO (Maybe String)
10820 -- last_error h = do
10821 -- str <- withForeignPtr h (\\p -> c_last_error p)
10822 -- maybePeek peekCString str
10824 last_error :: GuestfsH -> IO (String)
10826 str <- withForeignPtr h (\\p -> c_last_error p)
10827 if (str == nullPtr)
10828 then return \"no error\"
10829 else peekCString str
10833 (* Generate wrappers for each foreign function. *)
10835 fun (name, style, _, _, _, _, _) ->
10836 if can_generate style then (
10837 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10839 generate_haskell_prototype ~handle:"GuestfsP" style;
10843 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10845 pr "%s %s = do\n" name
10846 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10848 (* Convert pointer arguments using with* functions. *)
10853 | Pathname n | Device n | Dev_or_Path n | String n ->
10854 pr "withCString %s $ \\%s -> " n n
10856 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10857 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10858 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10859 | Bool _ | Int _ | Int64 _ -> ()
10861 (* Convert integer arguments. *)
10865 | Bool n -> sprintf "(fromBool %s)" n
10866 | Int n -> sprintf "(fromIntegral %s)" n
10867 | Int64 n -> sprintf "(fromIntegral %s)" n
10868 | FileIn n | FileOut n
10869 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10870 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10872 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10873 (String.concat " " ("p" :: args));
10874 (match fst style with
10875 | RErr | RInt _ | RInt64 _ | RBool _ ->
10876 pr " if (r == -1)\n";
10878 pr " err <- last_error h\n";
10880 | RConstString _ | RConstOptString _ | RString _
10881 | RStringList _ | RStruct _
10882 | RStructList _ | RHashtable _ | RBufferOut _ ->
10883 pr " if (r == nullPtr)\n";
10885 pr " err <- last_error h\n";
10888 (match fst style with
10890 pr " else return ()\n"
10892 pr " else return (fromIntegral r)\n"
10894 pr " else return (fromIntegral r)\n"
10896 pr " else return (toBool r)\n"
10898 | RConstOptString _
10905 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10911 and generate_haskell_prototype ~handle ?(hs = false) style =
10912 pr "%s -> " handle;
10913 let string = if hs then "String" else "CString" in
10914 let int = if hs then "Int" else "CInt" in
10915 let bool = if hs then "Bool" else "CInt" in
10916 let int64 = if hs then "Integer" else "Int64" in
10920 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10922 if hs then pr "String"
10923 else pr "CString -> CInt"
10924 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10925 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10926 | Bool _ -> pr "%s" bool
10927 | Int _ -> pr "%s" int
10928 | Int64 _ -> pr "%s" int
10929 | FileIn _ -> pr "%s" string
10930 | FileOut _ -> pr "%s" string
10935 (match fst style with
10936 | RErr -> if not hs then pr "CInt"
10937 | RInt _ -> pr "%s" int
10938 | RInt64 _ -> pr "%s" int64
10939 | RBool _ -> pr "%s" bool
10940 | RConstString _ -> pr "%s" string
10941 | RConstOptString _ -> pr "Maybe %s" string
10942 | RString _ -> pr "%s" string
10943 | RStringList _ -> pr "[%s]" string
10944 | RStruct (_, typ) ->
10945 let name = java_name_of_struct typ in
10947 | RStructList (_, typ) ->
10948 let name = java_name_of_struct typ in
10950 | RHashtable _ -> pr "Hashtable"
10951 | RBufferOut _ -> pr "%s" string
10955 and generate_csharp () =
10956 generate_header CPlusPlusStyle LGPLv2plus;
10958 (* XXX Make this configurable by the C# assembly users. *)
10959 let library = "libguestfs.so.0" in
10962 // These C# bindings are highly experimental at present.
10964 // Firstly they only work on Linux (ie. Mono). In order to get them
10965 // to work on Windows (ie. .Net) you would need to port the library
10966 // itself to Windows first.
10968 // The second issue is that some calls are known to be incorrect and
10969 // can cause Mono to segfault. Particularly: calls which pass or
10970 // return string[], or return any structure value. This is because
10971 // we haven't worked out the correct way to do this from C#.
10973 // The third issue is that when compiling you get a lot of warnings.
10974 // We are not sure whether the warnings are important or not.
10976 // Fourthly we do not routinely build or test these bindings as part
10977 // of the make && make check cycle, which means that regressions might
10980 // Suggestions and patches are welcome.
10984 // gmcs Libguestfs.cs
10985 // mono Libguestfs.exe
10987 // (You'll probably want to add a Test class / static main function
10988 // otherwise this won't do anything useful).
10992 using System.Runtime.InteropServices;
10993 using System.Runtime.Serialization;
10994 using System.Collections;
10998 class Error : System.ApplicationException
11000 public Error (string message) : base (message) {}
11001 protected Error (SerializationInfo info, StreamingContext context) {}
11008 [DllImport (\"%s\")]
11009 static extern IntPtr guestfs_create ();
11013 _handle = guestfs_create ();
11014 if (_handle == IntPtr.Zero)
11015 throw new Error (\"could not create guestfs handle\");
11018 [DllImport (\"%s\")]
11019 static extern void guestfs_close (IntPtr h);
11023 guestfs_close (_handle);
11026 [DllImport (\"%s\")]
11027 static extern string guestfs_last_error (IntPtr h);
11029 " library library library;
11031 (* Generate C# structure bindings. We prefix struct names with
11032 * underscore because C# cannot have conflicting struct names and
11033 * method names (eg. "class stat" and "stat").
11037 pr " [StructLayout (LayoutKind.Sequential)]\n";
11038 pr " public class _%s {\n" typ;
11041 | name, FChar -> pr " char %s;\n" name
11042 | name, FString -> pr " string %s;\n" name
11044 pr " uint %s_len;\n" name;
11045 pr " string %s;\n" name
11047 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11048 pr " string %s;\n" name
11049 | name, FUInt32 -> pr " uint %s;\n" name
11050 | name, FInt32 -> pr " int %s;\n" name
11051 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
11052 | name, FInt64 -> pr " long %s;\n" name
11053 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
11059 (* Generate C# function bindings. *)
11061 fun (name, style, _, _, _, shortdesc, _) ->
11062 let rec csharp_return_type () =
11063 match fst style with
11065 | RBool n -> "bool"
11067 | RInt64 n -> "long"
11069 | RConstOptString n
11071 | RBufferOut n -> "string"
11072 | RStruct (_,n) -> "_" ^ n
11073 | RHashtable n -> "Hashtable"
11074 | RStringList n -> "string[]"
11075 | RStructList (_,n) -> sprintf "_%s[]" n
11077 and c_return_type () =
11078 match fst style with
11082 | RInt64 _ -> "long"
11084 | RConstOptString _
11086 | RBufferOut _ -> "string"
11087 | RStruct (_,n) -> "_" ^ n
11089 | RStringList _ -> "string[]"
11090 | RStructList (_,n) -> sprintf "_%s[]" n
11092 and c_error_comparison () =
11093 match fst style with
11097 | RInt64 _ -> "== -1"
11099 | RConstOptString _
11105 | RStructList (_,_) -> "== null"
11107 and generate_extern_prototype () =
11108 pr " static extern %s guestfs_%s (IntPtr h"
11109 (c_return_type ()) name;
11112 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11113 | FileIn n | FileOut n
11115 pr ", [In] string %s" n
11116 | StringList n | DeviceList n ->
11117 pr ", [In] string[] %s" n
11127 and generate_public_prototype () =
11128 pr " public %s %s (" (csharp_return_type ()) name;
11129 let comma = ref false in
11131 if !comma then pr ", ";
11136 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11137 | FileIn n | FileOut n
11139 next (); pr "string %s" n
11140 | StringList n | DeviceList n ->
11141 next (); pr "string[] %s" n
11143 next (); pr "bool %s" n
11145 next (); pr "int %s" n
11147 next (); pr "long %s" n
11151 and generate_call () =
11152 pr "guestfs_%s (_handle" name;
11153 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11157 pr " [DllImport (\"%s\")]\n" library;
11158 generate_extern_prototype ();
11160 pr " /// <summary>\n";
11161 pr " /// %s\n" shortdesc;
11162 pr " /// </summary>\n";
11163 generate_public_prototype ();
11165 pr " %s r;\n" (c_return_type ());
11168 pr " if (r %s)\n" (c_error_comparison ());
11169 pr " throw new Error (guestfs_last_error (_handle));\n";
11170 (match fst style with
11173 pr " return r != 0 ? true : false;\n"
11175 pr " Hashtable rr = new Hashtable ();\n";
11176 pr " for (size_t i = 0; i < r.Length; i += 2)\n";
11177 pr " rr.Add (r[i], r[i+1]);\n";
11179 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11180 | RString _ | RBufferOut _ | RStruct _ | RStringList _
11186 ) all_functions_sorted;
11192 and generate_bindtests () =
11193 generate_header CStyle LGPLv2plus;
11197 #include <stdlib.h>
11198 #include <inttypes.h>
11199 #include <string.h>
11201 #include \"guestfs.h\"
11202 #include \"guestfs-internal.h\"
11203 #include \"guestfs-internal-actions.h\"
11204 #include \"guestfs_protocol.h\"
11206 #define error guestfs_error
11207 #define safe_calloc guestfs_safe_calloc
11208 #define safe_malloc guestfs_safe_malloc
11211 print_strings (char *const *argv)
11216 for (argc = 0; argv[argc] != NULL; ++argc) {
11217 if (argc > 0) printf (\", \");
11218 printf (\"\\\"%%s\\\"\", argv[argc]);
11223 /* The test0 function prints its parameters to stdout. */
11227 match test_functions with
11228 | [] -> assert false
11229 | test0 :: tests -> test0, tests in
11232 let (name, style, _, _, _, _, _) = test0 in
11233 generate_prototype ~extern:false ~semicolon:false ~newline:true
11234 ~handle:"g" ~prefix:"guestfs__" name style;
11239 | Device n | Dev_or_Path n
11242 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
11246 pr " for (i = 0; i < %s_size; ++i)\n" n;
11247 pr " printf (\"<%%02x>\", %s[i]);\n" n;
11248 pr " printf (\"\\n\");\n";
11250 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11251 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
11252 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11253 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
11254 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11256 pr " /* Java changes stdout line buffering so we need this: */\n";
11257 pr " fflush (stdout);\n";
11263 fun (name, style, _, _, _, _, _) ->
11264 if String.sub name (String.length name - 3) 3 <> "err" then (
11265 pr "/* Test normal return. */\n";
11266 generate_prototype ~extern:false ~semicolon:false ~newline:true
11267 ~handle:"g" ~prefix:"guestfs__" name style;
11269 (match fst style with
11274 pr " sscanf (val, \"%%d\", &r);\n";
11277 pr " int64_t r;\n";
11278 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
11281 pr " return STREQ (val, \"true\");\n"
11283 | RConstOptString _ ->
11284 (* Can't return the input string here. Return a static
11285 * string so we ensure we get a segfault if the caller
11286 * tries to free it.
11288 pr " return \"static string\";\n"
11290 pr " return strdup (val);\n"
11292 pr " char **strs;\n";
11294 pr " sscanf (val, \"%%d\", &n);\n";
11295 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11296 pr " for (i = 0; i < n; ++i) {\n";
11297 pr " strs[i] = safe_malloc (g, 16);\n";
11298 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
11300 pr " strs[n] = NULL;\n";
11301 pr " return strs;\n"
11302 | RStruct (_, typ) ->
11303 pr " struct guestfs_%s *r;\n" typ;
11304 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11306 | RStructList (_, typ) ->
11307 pr " struct guestfs_%s_list *r;\n" typ;
11308 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11309 pr " sscanf (val, \"%%d\", &r->len);\n";
11310 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11313 pr " char **strs;\n";
11315 pr " sscanf (val, \"%%d\", &n);\n";
11316 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11317 pr " for (i = 0; i < n; ++i) {\n";
11318 pr " strs[i*2] = safe_malloc (g, 16);\n";
11319 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11320 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11321 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11323 pr " strs[n*2] = NULL;\n";
11324 pr " return strs;\n"
11326 pr " return strdup (val);\n"
11331 pr "/* Test error return. */\n";
11332 generate_prototype ~extern:false ~semicolon:false ~newline:true
11333 ~handle:"g" ~prefix:"guestfs__" name style;
11335 pr " error (g, \"error\");\n";
11336 (match fst style with
11337 | RErr | RInt _ | RInt64 _ | RBool _ ->
11339 | RConstString _ | RConstOptString _
11340 | RString _ | RStringList _ | RStruct _
11344 pr " return NULL;\n"
11351 and generate_ocaml_bindtests () =
11352 generate_header OCamlStyle GPLv2plus;
11356 let g = Guestfs.create () in
11360 String.concat " " (
11363 | CallString s -> "\"" ^ s ^ "\""
11364 | CallOptString None -> "None"
11365 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11366 | CallStringList xs ->
11367 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11368 | CallInt i when i >= 0 -> string_of_int i
11369 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11370 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11371 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11372 | CallBool b -> string_of_bool b
11373 | CallBuffer s -> sprintf "%S" s
11378 generate_lang_bindtests (
11379 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11382 pr "print_endline \"EOF\"\n"
11384 and generate_perl_bindtests () =
11385 pr "#!/usr/bin/perl -w\n";
11386 generate_header HashStyle GPLv2plus;
11393 my $g = Sys::Guestfs->new ();
11397 String.concat ", " (
11400 | CallString s -> "\"" ^ s ^ "\""
11401 | CallOptString None -> "undef"
11402 | CallOptString (Some s) -> sprintf "\"%s\"" s
11403 | CallStringList xs ->
11404 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11405 | CallInt i -> string_of_int i
11406 | CallInt64 i -> Int64.to_string i
11407 | CallBool b -> if b then "1" else "0"
11408 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11413 generate_lang_bindtests (
11414 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11417 pr "print \"EOF\\n\"\n"
11419 and generate_python_bindtests () =
11420 generate_header HashStyle GPLv2plus;
11425 g = guestfs.GuestFS ()
11429 String.concat ", " (
11432 | CallString s -> "\"" ^ s ^ "\""
11433 | CallOptString None -> "None"
11434 | CallOptString (Some s) -> sprintf "\"%s\"" s
11435 | CallStringList xs ->
11436 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11437 | CallInt i -> string_of_int i
11438 | CallInt64 i -> Int64.to_string i
11439 | CallBool b -> if b then "1" else "0"
11440 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11445 generate_lang_bindtests (
11446 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11449 pr "print \"EOF\"\n"
11451 and generate_ruby_bindtests () =
11452 generate_header HashStyle GPLv2plus;
11457 g = Guestfs::create()
11461 String.concat ", " (
11464 | CallString s -> "\"" ^ s ^ "\""
11465 | CallOptString None -> "nil"
11466 | CallOptString (Some s) -> sprintf "\"%s\"" s
11467 | CallStringList xs ->
11468 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11469 | CallInt i -> string_of_int i
11470 | CallInt64 i -> Int64.to_string i
11471 | CallBool b -> string_of_bool b
11472 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11477 generate_lang_bindtests (
11478 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11481 pr "print \"EOF\\n\"\n"
11483 and generate_java_bindtests () =
11484 generate_header CStyle GPLv2plus;
11487 import com.redhat.et.libguestfs.*;
11489 public class Bindtests {
11490 public static void main (String[] argv)
11493 GuestFS g = new GuestFS ();
11497 String.concat ", " (
11500 | CallString s -> "\"" ^ s ^ "\""
11501 | CallOptString None -> "null"
11502 | CallOptString (Some s) -> sprintf "\"%s\"" s
11503 | CallStringList xs ->
11505 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11506 | CallInt i -> string_of_int i
11507 | CallInt64 i -> Int64.to_string i
11508 | CallBool b -> string_of_bool b
11510 "new byte[] { " ^ String.concat "," (
11511 map_chars (fun c -> string_of_int (Char.code c)) s
11517 generate_lang_bindtests (
11518 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11522 System.out.println (\"EOF\");
11524 catch (Exception exn) {
11525 System.err.println (exn);
11532 and generate_haskell_bindtests () =
11533 generate_header HaskellStyle GPLv2plus;
11536 module Bindtests where
11537 import qualified Guestfs
11540 g <- Guestfs.create
11544 String.concat " " (
11547 | CallString s -> "\"" ^ s ^ "\""
11548 | CallOptString None -> "Nothing"
11549 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11550 | CallStringList xs ->
11551 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11552 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11553 | CallInt i -> string_of_int i
11554 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11555 | CallInt64 i -> Int64.to_string i
11556 | CallBool true -> "True"
11557 | CallBool false -> "False"
11558 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11563 generate_lang_bindtests (
11564 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11567 pr " putStrLn \"EOF\"\n"
11569 (* Language-independent bindings tests - we do it this way to
11570 * ensure there is parity in testing bindings across all languages.
11572 and generate_lang_bindtests call =
11573 call "test0" [CallString "abc"; CallOptString (Some "def");
11574 CallStringList []; CallBool false;
11575 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11576 CallBuffer "abc\000abc"];
11577 call "test0" [CallString "abc"; CallOptString None;
11578 CallStringList []; CallBool false;
11579 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11580 CallBuffer "abc\000abc"];
11581 call "test0" [CallString ""; CallOptString (Some "def");
11582 CallStringList []; CallBool false;
11583 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11584 CallBuffer "abc\000abc"];
11585 call "test0" [CallString ""; CallOptString (Some "");
11586 CallStringList []; CallBool false;
11587 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11588 CallBuffer "abc\000abc"];
11589 call "test0" [CallString "abc"; CallOptString (Some "def");
11590 CallStringList ["1"]; CallBool false;
11591 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11592 CallBuffer "abc\000abc"];
11593 call "test0" [CallString "abc"; CallOptString (Some "def");
11594 CallStringList ["1"; "2"]; CallBool false;
11595 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11596 CallBuffer "abc\000abc"];
11597 call "test0" [CallString "abc"; CallOptString (Some "def");
11598 CallStringList ["1"]; CallBool true;
11599 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11600 CallBuffer "abc\000abc"];
11601 call "test0" [CallString "abc"; CallOptString (Some "def");
11602 CallStringList ["1"]; CallBool false;
11603 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11604 CallBuffer "abc\000abc"];
11605 call "test0" [CallString "abc"; CallOptString (Some "def");
11606 CallStringList ["1"]; CallBool false;
11607 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11608 CallBuffer "abc\000abc"];
11609 call "test0" [CallString "abc"; CallOptString (Some "def");
11610 CallStringList ["1"]; CallBool false;
11611 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11612 CallBuffer "abc\000abc"];
11613 call "test0" [CallString "abc"; CallOptString (Some "def");
11614 CallStringList ["1"]; CallBool false;
11615 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11616 CallBuffer "abc\000abc"];
11617 call "test0" [CallString "abc"; CallOptString (Some "def");
11618 CallStringList ["1"]; CallBool false;
11619 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11620 CallBuffer "abc\000abc"];
11621 call "test0" [CallString "abc"; CallOptString (Some "def");
11622 CallStringList ["1"]; CallBool false;
11623 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11624 CallBuffer "abc\000abc"]
11626 (* XXX Add here tests of the return and error functions. *)
11628 (* Code to generator bindings for virt-inspector. Currently only
11629 * implemented for OCaml code (for virt-p2v 2.0).
11631 let rng_input = "inspector/virt-inspector.rng"
11633 (* Read the input file and parse it into internal structures. This is
11634 * by no means a complete RELAX NG parser, but is just enough to be
11635 * able to parse the specific input file.
11638 | Element of string * rng list (* <element name=name/> *)
11639 | Attribute of string * rng list (* <attribute name=name/> *)
11640 | Interleave of rng list (* <interleave/> *)
11641 | ZeroOrMore of rng (* <zeroOrMore/> *)
11642 | OneOrMore of rng (* <oneOrMore/> *)
11643 | Optional of rng (* <optional/> *)
11644 | Choice of string list (* <choice><value/>*</choice> *)
11645 | Value of string (* <value>str</value> *)
11646 | Text (* <text/> *)
11648 let rec string_of_rng = function
11649 | Element (name, xs) ->
11650 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11651 | Attribute (name, xs) ->
11652 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11653 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11654 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11655 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11656 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11657 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11658 | Value value -> "Value \"" ^ value ^ "\""
11661 and string_of_rng_list xs =
11662 String.concat ", " (List.map string_of_rng xs)
11664 let rec parse_rng ?defines context = function
11666 | Xml.Element ("element", ["name", name], children) :: rest ->
11667 Element (name, parse_rng ?defines context children)
11668 :: parse_rng ?defines context rest
11669 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11670 Attribute (name, parse_rng ?defines context children)
11671 :: parse_rng ?defines context rest
11672 | Xml.Element ("interleave", [], children) :: rest ->
11673 Interleave (parse_rng ?defines context children)
11674 :: parse_rng ?defines context rest
11675 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11676 let rng = parse_rng ?defines context [child] in
11678 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11680 failwithf "%s: <zeroOrMore> contains more than one child element"
11683 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11684 let rng = parse_rng ?defines context [child] in
11686 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11688 failwithf "%s: <oneOrMore> contains more than one child element"
11691 | Xml.Element ("optional", [], [child]) :: rest ->
11692 let rng = parse_rng ?defines context [child] in
11694 | [child] -> Optional child :: parse_rng ?defines context rest
11696 failwithf "%s: <optional> contains more than one child element"
11699 | Xml.Element ("choice", [], children) :: rest ->
11700 let values = List.map (
11701 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11703 failwithf "%s: can't handle anything except <value> in <choice>"
11707 :: parse_rng ?defines context rest
11708 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11709 Value value :: parse_rng ?defines context rest
11710 | Xml.Element ("text", [], []) :: rest ->
11711 Text :: parse_rng ?defines context rest
11712 | Xml.Element ("ref", ["name", name], []) :: rest ->
11713 (* Look up the reference. Because of limitations in this parser,
11714 * we can't handle arbitrarily nested <ref> yet. You can only
11715 * use <ref> from inside <start>.
11717 (match defines with
11719 failwithf "%s: contains <ref>, but no refs are defined yet" context
11721 let rng = StringMap.find name map in
11722 rng @ parse_rng ?defines context rest
11725 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11728 let xml = Xml.parse_file rng_input in
11730 | Xml.Element ("grammar", _,
11731 Xml.Element ("start", _, gram) :: defines) ->
11732 (* The <define/> elements are referenced in the <start> section,
11733 * so build a map of those first.
11735 let defines = List.fold_left (
11737 function Xml.Element ("define", ["name", name], defn) ->
11738 StringMap.add name defn map
11740 failwithf "%s: expected <define name=name/>" rng_input
11741 ) StringMap.empty defines in
11742 let defines = StringMap.mapi parse_rng defines in
11744 (* Parse the <start> clause, passing the defines. *)
11745 parse_rng ~defines "<start>" gram
11747 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11750 let name_of_field = function
11751 | Element (name, _) | Attribute (name, _)
11752 | ZeroOrMore (Element (name, _))
11753 | OneOrMore (Element (name, _))
11754 | Optional (Element (name, _)) -> name
11755 | Optional (Attribute (name, _)) -> name
11756 | Text -> (* an unnamed field in an element *)
11759 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11761 (* At the moment this function only generates OCaml types. However we
11762 * should parameterize it later so it can generate types/structs in a
11763 * variety of languages.
11765 let generate_types xs =
11766 (* A simple type is one that can be printed out directly, eg.
11767 * "string option". A complex type is one which has a name and has
11768 * to be defined via another toplevel definition, eg. a struct.
11770 * generate_type generates code for either simple or complex types.
11771 * In the simple case, it returns the string ("string option"). In
11772 * the complex case, it returns the name ("mountpoint"). In the
11773 * complex case it has to print out the definition before returning,
11774 * so it should only be called when we are at the beginning of a
11775 * new line (BOL context).
11777 let rec generate_type = function
11778 | Text -> (* string *)
11780 | Choice values -> (* [`val1|`val2|...] *)
11781 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11782 | ZeroOrMore rng -> (* <rng> list *)
11783 let t, is_simple = generate_type rng in
11784 t ^ " list (* 0 or more *)", is_simple
11785 | OneOrMore rng -> (* <rng> list *)
11786 let t, is_simple = generate_type rng in
11787 t ^ " list (* 1 or more *)", is_simple
11788 (* virt-inspector hack: bool *)
11789 | Optional (Attribute (name, [Value "1"])) ->
11791 | Optional rng -> (* <rng> list *)
11792 let t, is_simple = generate_type rng in
11793 t ^ " option", is_simple
11794 (* type name = { fields ... } *)
11795 | Element (name, fields) when is_attrs_interleave fields ->
11796 generate_type_struct name (get_attrs_interleave fields)
11797 | Element (name, [field]) (* type name = field *)
11798 | Attribute (name, [field]) ->
11799 let t, is_simple = generate_type field in
11800 if is_simple then (t, true)
11802 pr "type %s = %s\n" name t;
11805 | Element (name, fields) -> (* type name = { fields ... } *)
11806 generate_type_struct name fields
11808 failwithf "generate_type failed at: %s" (string_of_rng rng)
11810 and is_attrs_interleave = function
11811 | [Interleave _] -> true
11812 | Attribute _ :: fields -> is_attrs_interleave fields
11813 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11816 and get_attrs_interleave = function
11817 | [Interleave fields] -> fields
11818 | ((Attribute _) as field) :: fields
11819 | ((Optional (Attribute _)) as field) :: fields ->
11820 field :: get_attrs_interleave fields
11821 | _ -> assert false
11823 and generate_types xs =
11824 List.iter (fun x -> ignore (generate_type x)) xs
11826 and generate_type_struct name fields =
11827 (* Calculate the types of the fields first. We have to do this
11828 * before printing anything so we are still in BOL context.
11830 let types = List.map fst (List.map generate_type fields) in
11832 (* Special case of a struct containing just a string and another
11833 * field. Turn it into an assoc list.
11836 | ["string"; other] ->
11837 let fname1, fname2 =
11839 | [f1; f2] -> name_of_field f1, name_of_field f2
11840 | _ -> assert false in
11841 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11845 pr "type %s = {\n" name;
11847 fun (field, ftype) ->
11848 let fname = name_of_field field in
11849 pr " %s_%s : %s;\n" name fname ftype
11850 ) (List.combine fields types);
11852 (* Return the name of this type, and
11853 * false because it's not a simple type.
11860 let generate_parsers xs =
11861 (* As for generate_type above, generate_parser makes a parser for
11862 * some type, and returns the name of the parser it has generated.
11863 * Because it (may) need to print something, it should always be
11864 * called in BOL context.
11866 let rec generate_parser = function
11867 | Text -> (* string *)
11868 "string_child_or_empty"
11869 | Choice values -> (* [`val1|`val2|...] *)
11870 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11872 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11873 | ZeroOrMore rng -> (* <rng> list *)
11874 let pa = generate_parser rng in
11875 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11876 | OneOrMore rng -> (* <rng> list *)
11877 let pa = generate_parser rng in
11878 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11879 (* virt-inspector hack: bool *)
11880 | Optional (Attribute (name, [Value "1"])) ->
11881 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11882 | Optional rng -> (* <rng> list *)
11883 let pa = generate_parser rng in
11884 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11885 (* type name = { fields ... } *)
11886 | Element (name, fields) when is_attrs_interleave fields ->
11887 generate_parser_struct name (get_attrs_interleave fields)
11888 | Element (name, [field]) -> (* type name = field *)
11889 let pa = generate_parser field in
11890 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11891 pr "let %s =\n" parser_name;
11893 pr "let parse_%s = %s\n" name parser_name;
11895 | Attribute (name, [field]) ->
11896 let pa = generate_parser field in
11897 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11898 pr "let %s =\n" parser_name;
11900 pr "let parse_%s = %s\n" name parser_name;
11902 | Element (name, fields) -> (* type name = { fields ... } *)
11903 generate_parser_struct name ([], fields)
11905 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11907 and is_attrs_interleave = function
11908 | [Interleave _] -> true
11909 | Attribute _ :: fields -> is_attrs_interleave fields
11910 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11913 and get_attrs_interleave = function
11914 | [Interleave fields] -> [], fields
11915 | ((Attribute _) as field) :: fields
11916 | ((Optional (Attribute _)) as field) :: fields ->
11917 let attrs, interleaves = get_attrs_interleave fields in
11918 (field :: attrs), interleaves
11919 | _ -> assert false
11921 and generate_parsers xs =
11922 List.iter (fun x -> ignore (generate_parser x)) xs
11924 and generate_parser_struct name (attrs, interleaves) =
11925 (* Generate parsers for the fields first. We have to do this
11926 * before printing anything so we are still in BOL context.
11928 let fields = attrs @ interleaves in
11929 let pas = List.map generate_parser fields in
11931 (* Generate an intermediate tuple from all the fields first.
11932 * If the type is just a string + another field, then we will
11933 * return this directly, otherwise it is turned into a record.
11935 * RELAX NG note: This code treats <interleave> and plain lists of
11936 * fields the same. In other words, it doesn't bother enforcing
11937 * any ordering of fields in the XML.
11939 pr "let parse_%s x =\n" name;
11940 pr " let t = (\n ";
11941 let comma = ref false in
11944 if !comma then pr ",\n ";
11947 | Optional (Attribute (fname, [field])), pa ->
11949 | Optional (Element (fname, [field])), pa ->
11950 pr "%s (optional_child %S x)" pa fname
11951 | Attribute (fname, [Text]), _ ->
11952 pr "attribute %S x" fname
11953 | (ZeroOrMore _ | OneOrMore _), pa ->
11958 let fname = name_of_field field in
11959 pr "%s (child %S x)" pa fname
11960 ) (List.combine fields pas);
11964 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11968 pr " (Obj.magic t : %s)\n" name
11972 | (Optional (Attribute (fname, [field])), pa) ->
11973 pr " %s_%s =\n" name fname;
11975 | (Optional (Element (fname, [field])), pa) ->
11976 pr " %s_%s =\n" name fname;
11977 pr " (let x = optional_child %S x in\n" fname;
11980 let fname = name_of_field field in
11981 pr " %s_%s =\n" name fname;
11982 pr " (let x = child %S x in\n" fname;
11984 ) (List.combine fields pas);
11988 sprintf "parse_%s" name
11991 generate_parsers xs
11993 (* Generate ocaml/guestfs_inspector.mli. *)
11994 let generate_ocaml_inspector_mli () =
11995 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11998 (** This is an OCaml language binding to the external [virt-inspector]
12001 For more information, please read the man page [virt-inspector(1)].
12006 generate_types grammar;
12007 pr "(** The nested information returned from the {!inspect} function. *)\n";
12011 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12012 (** To inspect a libvirt domain called [name], pass a singleton
12013 list: [inspect [name]]. When using libvirt only, you may
12014 optionally pass a libvirt URI using [inspect ~connect:uri ...].
12016 To inspect a disk image or images, pass a list of the filenames
12017 of the disk images: [inspect filenames]
12019 This function inspects the given guest or disk images and
12020 returns a list of operating system(s) found and a large amount
12021 of information about them. In the vast majority of cases,
12022 a virtual machine only contains a single operating system.
12024 If the optional [~xml] parameter is given, then this function
12025 skips running the external virt-inspector program and just
12026 parses the given XML directly (which is expected to be XML
12027 produced from a previous run of virt-inspector). The list of
12028 names and connect URI are ignored in this case.
12030 This function can throw a wide variety of exceptions, for example
12031 if the external virt-inspector program cannot be found, or if
12032 it doesn't generate valid XML.
12036 (* Generate ocaml/guestfs_inspector.ml. *)
12037 let generate_ocaml_inspector_ml () =
12038 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12043 generate_types grammar;
12047 (* Misc functions which are used by the parser code below. *)
12048 let first_child = function
12049 | Xml.Element (_, _, c::_) -> c
12050 | Xml.Element (name, _, []) ->
12051 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12052 | Xml.PCData str ->
12053 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12055 let string_child_or_empty = function
12056 | Xml.Element (_, _, [Xml.PCData s]) -> s
12057 | Xml.Element (_, _, []) -> \"\"
12058 | Xml.Element (x, _, _) ->
12059 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12061 | Xml.PCData str ->
12062 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12064 let optional_child name xml =
12065 let children = Xml.children xml in
12067 Some (List.find (function
12068 | Xml.Element (n, _, _) when n = name -> true
12069 | _ -> false) children)
12073 let child name xml =
12074 match optional_child name xml with
12077 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12079 let attribute name xml =
12080 try Xml.attrib xml name
12081 with Xml.No_attribute _ ->
12082 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12086 generate_parsers grammar;
12090 (* Run external virt-inspector, then use parser to parse the XML. *)
12091 let inspect ?connect ?xml names =
12095 if names = [] then invalid_arg \"inspect: no names given\";
12096 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12097 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12099 let cmd = List.map Filename.quote cmd in
12100 let cmd = String.concat \" \" cmd in
12101 let chan = open_process_in cmd in
12102 let xml = Xml.parse_in chan in
12103 (match close_process_in chan with
12105 | WEXITED _ -> failwith \"external virt-inspector command failed\"
12106 | WSIGNALED i | WSTOPPED i ->
12107 failwith (\"external virt-inspector command died or stopped on sig \" ^
12112 Xml.parse_string doc in
12113 parse_operatingsystems xml
12116 and generate_max_proc_nr () =
12117 pr "%d\n" max_proc_nr
12119 let output_to filename k =
12120 let filename_new = filename ^ ".new" in
12121 chan := open_out filename_new;
12124 chan := Pervasives.stdout;
12126 (* Is the new file different from the current file? *)
12127 if Sys.file_exists filename && files_equal filename filename_new then
12128 unlink filename_new (* same, so skip it *)
12130 (* different, overwrite old one *)
12131 (try chmod filename 0o644 with Unix_error _ -> ());
12132 rename filename_new filename;
12133 chmod filename 0o444;
12134 printf "written %s\n%!" filename;
12137 let perror msg = function
12138 | Unix_error (err, _, _) ->
12139 eprintf "%s: %s\n" msg (error_message err)
12141 eprintf "%s: %s\n" msg (Printexc.to_string exn)
12143 (* Main program. *)
12146 try openfile "HACKING" [O_RDWR] 0
12148 | Unix_error (ENOENT, _, _) ->
12150 You are probably running this from the wrong directory.
12151 Run it from the top source directory using the command
12156 perror "open: HACKING" exn;
12159 (* Acquire a lock so parallel builds won't try to run the generator
12160 * twice at the same time. Subsequent builds will wait for the first
12161 * one to finish. Note the lock is released implicitly when the
12164 (try lockf lock_fd F_LOCK 1
12166 perror "lock: HACKING" exn;
12169 check_functions ();
12171 output_to "src/guestfs_protocol.x" generate_xdr;
12172 output_to "src/guestfs-structs.h" generate_structs_h;
12173 output_to "src/guestfs-actions.h" generate_actions_h;
12174 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12175 output_to "src/actions.c" generate_client_actions;
12176 output_to "src/bindtests.c" generate_bindtests;
12177 output_to "src/guestfs-structs.pod" generate_structs_pod;
12178 output_to "src/guestfs-actions.pod" generate_actions_pod;
12179 output_to "src/guestfs-availability.pod" generate_availability_pod;
12180 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12181 output_to "src/libguestfs.syms" generate_linker_script;
12182 output_to "daemon/actions.h" generate_daemon_actions_h;
12183 output_to "daemon/stubs.c" generate_daemon_actions;
12184 output_to "daemon/names.c" generate_daemon_names;
12185 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12186 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12187 output_to "capitests/tests.c" generate_tests;
12188 output_to "fish/cmds.c" generate_fish_cmds;
12189 output_to "fish/completion.c" generate_fish_completion;
12190 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12191 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12192 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12193 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12194 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12195 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12196 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12197 output_to "perl/Guestfs.xs" generate_perl_xs;
12198 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12199 output_to "perl/bindtests.pl" generate_perl_bindtests;
12200 output_to "python/guestfs-py.c" generate_python_c;
12201 output_to "python/guestfs.py" generate_python_py;
12202 output_to "python/bindtests.py" generate_python_bindtests;
12203 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12204 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12205 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12209 let cols = cols_of_struct typ in
12210 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12211 output_to filename (generate_java_struct jtyp cols);
12214 output_to "java/Makefile.inc" generate_java_makefile_inc;
12215 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12216 output_to "java/Bindtests.java" generate_java_bindtests;
12217 output_to "haskell/Guestfs.hs" generate_haskell_hs;
12218 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12219 output_to "csharp/Libguestfs.cs" generate_csharp;
12221 (* Always generate this file last, and unconditionally. It's used
12222 * by the Makefile to know when we must re-run the generator.
12224 let chan = open_out "src/stamp-generator" in
12225 fprintf chan "1\n";
12228 printf "generated %d lines of code\n" !lines