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 for the guestfish -N (prepared disk images) option.
5097 * Note that the longdescs are indented by 2 spaces.
5101 "create a blank disk",
5102 [ "size", "100M", "the size of the disk image" ],
5103 " Create a blank disk, size 100MB (by default).
5105 The default size can be changed by supplying an optional parameter.");
5108 "create a partitioned disk",
5109 [ "size", "100M", "the size of the disk image";
5110 "partition", "mbr", "partition table type" ],
5111 " Create a disk with a single partition. By default the size of the disk
5112 is 100MB (the available space in the partition will be a tiny bit smaller)
5113 and the partition table will be MBR (old DOS-style).
5115 These defaults can be changed by supplying optional parameters.");
5118 "create a filesystem",
5119 [ "filesystem", "ext2", "the type of filesystem to use";
5120 "size", "100M", "the size of the disk image";
5121 "partition", "mbr", "partition table type" ],
5122 " Create a disk with a single partition, with the partition containing
5123 an empty filesystem. This defaults to creating a 100MB disk (the available
5124 space in the filesystem will be a tiny bit smaller) with an MBR (old
5125 DOS-style) partition table and an ext2 filesystem.
5127 These defaults can be changed by supplying optional parameters.");
5130 (* Used to memoize the result of pod2text. *)
5131 let pod2text_memo_filename = "src/.pod2text.data"
5132 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5134 let chan = open_in pod2text_memo_filename in
5135 let v = input_value chan in
5139 _ -> Hashtbl.create 13
5140 let pod2text_memo_updated () =
5141 let chan = open_out pod2text_memo_filename in
5142 output_value chan pod2text_memo;
5145 (* Useful functions.
5146 * Note we don't want to use any external OCaml libraries which
5147 * makes this a bit harder than it should be.
5149 module StringMap = Map.Make (String)
5151 let failwithf fs = ksprintf failwith fs
5153 let unique = let i = ref 0 in fun () -> incr i; !i
5155 let replace_char s c1 c2 =
5156 let s2 = String.copy s in
5157 let r = ref false in
5158 for i = 0 to String.length s2 - 1 do
5159 if String.unsafe_get s2 i = c1 then (
5160 String.unsafe_set s2 i c2;
5164 if not !r then s else s2
5168 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5170 let triml ?(test = isspace) str =
5172 let n = ref (String.length str) in
5173 while !n > 0 && test str.[!i]; do
5178 else String.sub str !i !n
5180 let trimr ?(test = isspace) str =
5181 let n = ref (String.length str) in
5182 while !n > 0 && test str.[!n-1]; do
5185 if !n = String.length str then str
5186 else String.sub str 0 !n
5188 let trim ?(test = isspace) str =
5189 trimr ~test (triml ~test str)
5191 let rec find s sub =
5192 let len = String.length s in
5193 let sublen = String.length sub in
5195 if i <= len-sublen then (
5197 if j < sublen then (
5198 if s.[i+j] = sub.[j] then loop2 (j+1)
5204 if r = -1 then loop (i+1) else r
5210 let rec replace_str s s1 s2 =
5211 let len = String.length s in
5212 let sublen = String.length s1 in
5213 let i = find s s1 in
5216 let s' = String.sub s 0 i in
5217 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5218 s' ^ s2 ^ replace_str s'' s1 s2
5221 let rec string_split sep str =
5222 let len = String.length str in
5223 let seplen = String.length sep in
5224 let i = find str sep in
5225 if i = -1 then [str]
5227 let s' = String.sub str 0 i in
5228 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5229 s' :: string_split sep s''
5232 let files_equal n1 n2 =
5233 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5234 match Sys.command cmd with
5237 | i -> failwithf "%s: failed with error code %d" cmd i
5239 let rec filter_map f = function
5243 | Some y -> y :: filter_map f xs
5244 | None -> filter_map f xs
5246 let rec find_map f = function
5247 | [] -> raise Not_found
5251 | None -> find_map f xs
5254 let rec loop i = function
5256 | x :: xs -> f i x; loop (i+1) xs
5261 let rec loop i = function
5263 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5267 let count_chars c str =
5268 let count = ref 0 in
5269 for i = 0 to String.length str - 1 do
5270 if c = String.unsafe_get str i then incr count
5276 for i = 0 to String.length str - 1 do
5277 let c = String.unsafe_get str i in
5282 let map_chars f str =
5283 List.map f (explode str)
5285 let name_of_argt = function
5286 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5287 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5288 | FileIn n | FileOut n | BufferIn n -> n
5290 let java_name_of_struct typ =
5291 try List.assoc typ java_structs
5294 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5296 let cols_of_struct typ =
5297 try List.assoc typ structs
5299 failwithf "cols_of_struct: unknown struct %s" typ
5301 let seq_of_test = function
5302 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5303 | TestOutputListOfDevices (s, _)
5304 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5305 | TestOutputTrue s | TestOutputFalse s
5306 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5307 | TestOutputStruct (s, _)
5308 | TestLastFail s -> s
5310 (* Handling for function flags. *)
5311 let protocol_limit_warning =
5312 "Because of the message protocol, there is a transfer limit
5313 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5315 let danger_will_robinson =
5316 "B<This command is dangerous. Without careful use you
5317 can easily destroy all your data>."
5319 let deprecation_notice flags =
5322 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5324 sprintf "This function is deprecated.
5325 In new code, use the C<%s> call instead.
5327 Deprecated functions will not be removed from the API, but the
5328 fact that they are deprecated indicates that there are problems
5329 with correct use of these functions." alt in
5334 (* Create list of optional groups. *)
5336 let h = Hashtbl.create 13 in
5338 fun (name, _, _, flags, _, _, _) ->
5342 let names = try Hashtbl.find h group with Not_found -> [] in
5343 Hashtbl.replace h group (name :: names)
5347 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5350 fun group -> group, List.sort compare (Hashtbl.find h group)
5352 List.sort (fun x y -> compare (fst x) (fst y)) groups
5354 (* Check function names etc. for consistency. *)
5355 let check_functions () =
5356 let contains_uppercase str =
5357 let len = String.length str in
5359 if i >= len then false
5362 if c >= 'A' && c <= 'Z' then true
5369 (* Check function names. *)
5371 fun (name, _, _, _, _, _, _) ->
5372 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5373 failwithf "function name %s does not need 'guestfs' prefix" name;
5375 failwithf "function name is empty";
5376 if name.[0] < 'a' || name.[0] > 'z' then
5377 failwithf "function name %s must start with lowercase a-z" name;
5378 if String.contains name '-' then
5379 failwithf "function name %s should not contain '-', use '_' instead."
5383 (* Check function parameter/return names. *)
5385 fun (name, style, _, _, _, _, _) ->
5386 let check_arg_ret_name n =
5387 if contains_uppercase n then
5388 failwithf "%s param/ret %s should not contain uppercase chars"
5390 if String.contains n '-' || String.contains n '_' then
5391 failwithf "%s param/ret %s should not contain '-' or '_'"
5394 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;
5395 if n = "int" || n = "char" || n = "short" || n = "long" then
5396 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5397 if n = "i" || n = "n" then
5398 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5399 if n = "argv" || n = "args" then
5400 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5402 (* List Haskell, OCaml and C keywords here.
5403 * http://www.haskell.org/haskellwiki/Keywords
5404 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5405 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5406 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5407 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5408 * Omitting _-containing words, since they're handled above.
5409 * Omitting the OCaml reserved word, "val", is ok,
5410 * and saves us from renaming several parameters.
5413 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5414 "char"; "class"; "const"; "constraint"; "continue"; "data";
5415 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5416 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5417 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5418 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5419 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5421 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5422 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5423 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5424 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5425 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5426 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5427 "volatile"; "when"; "where"; "while";
5429 if List.mem n reserved then
5430 failwithf "%s has param/ret using reserved word %s" name n;
5433 (match fst style with
5435 | RInt n | RInt64 n | RBool n
5436 | RConstString n | RConstOptString n | RString n
5437 | RStringList n | RStruct (n, _) | RStructList (n, _)
5438 | RHashtable n | RBufferOut n ->
5439 check_arg_ret_name n
5441 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5444 (* Check short descriptions. *)
5446 fun (name, _, _, _, _, shortdesc, _) ->
5447 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5448 failwithf "short description of %s should begin with lowercase." name;
5449 let c = shortdesc.[String.length shortdesc-1] in
5450 if c = '\n' || c = '.' then
5451 failwithf "short description of %s should not end with . or \\n." name
5454 (* Check long descriptions. *)
5456 fun (name, _, _, _, _, _, longdesc) ->
5457 if longdesc.[String.length longdesc-1] = '\n' then
5458 failwithf "long description of %s should not end with \\n." name
5461 (* Check proc_nrs. *)
5463 fun (name, _, proc_nr, _, _, _, _) ->
5464 if proc_nr <= 0 then
5465 failwithf "daemon function %s should have proc_nr > 0" name
5469 fun (name, _, proc_nr, _, _, _, _) ->
5470 if proc_nr <> -1 then
5471 failwithf "non-daemon function %s should have proc_nr -1" name
5472 ) non_daemon_functions;
5475 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5478 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5479 let rec loop = function
5482 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5484 | (name1,nr1) :: (name2,nr2) :: _ ->
5485 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5493 (* Ignore functions that have no tests. We generate a
5494 * warning when the user does 'make check' instead.
5496 | name, _, _, _, [], _, _ -> ()
5497 | name, _, _, _, tests, _, _ ->
5501 match seq_of_test test with
5503 failwithf "%s has a test containing an empty sequence" name
5504 | cmds -> List.map List.hd cmds
5506 let funcs = List.flatten funcs in
5508 let tested = List.mem name funcs in
5511 failwithf "function %s has tests but does not test itself" name
5514 (* 'pr' prints to the current output file. *)
5515 let chan = ref Pervasives.stdout
5520 let i = count_chars '\n' str in
5521 lines := !lines + i;
5522 output_string !chan str
5525 let copyright_years =
5526 let this_year = 1900 + (localtime (time ())).tm_year in
5527 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5529 (* Generate a header block in a number of standard styles. *)
5530 type comment_style =
5531 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5532 type license = GPLv2plus | LGPLv2plus
5534 let generate_header ?(extra_inputs = []) comment license =
5535 let inputs = "src/generator.ml" :: extra_inputs in
5536 let c = match comment with
5537 | CStyle -> pr "/* "; " *"
5538 | CPlusPlusStyle -> pr "// "; "//"
5539 | HashStyle -> pr "# "; "#"
5540 | OCamlStyle -> pr "(* "; " *"
5541 | HaskellStyle -> pr "{- "; " " in
5542 pr "libguestfs generated file\n";
5543 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5544 List.iter (pr "%s %s\n" c) inputs;
5545 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5547 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5551 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5552 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5553 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5554 pr "%s (at your option) any later version.\n" c;
5556 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5557 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5558 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5559 pr "%s GNU General Public License for more details.\n" c;
5561 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5562 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5563 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5566 pr "%s This library is free software; you can redistribute it and/or\n" c;
5567 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5568 pr "%s License as published by the Free Software Foundation; either\n" c;
5569 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5571 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5572 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5573 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5574 pr "%s Lesser General Public License for more details.\n" c;
5576 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5577 pr "%s License along with this library; if not, write to the Free Software\n" c;
5578 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5581 | CStyle -> pr " */\n"
5584 | OCamlStyle -> pr " *)\n"
5585 | HaskellStyle -> pr "-}\n"
5589 (* Start of main code generation functions below this line. *)
5591 (* Generate the pod documentation for the C API. *)
5592 let rec generate_actions_pod () =
5594 fun (shortname, style, _, flags, _, _, longdesc) ->
5595 if not (List.mem NotInDocs flags) then (
5596 let name = "guestfs_" ^ shortname in
5597 pr "=head2 %s\n\n" name;
5599 generate_prototype ~extern:false ~handle:"g" name style;
5601 pr "%s\n\n" longdesc;
5602 (match fst style with
5604 pr "This function returns 0 on success or -1 on error.\n\n"
5606 pr "On error this function returns -1.\n\n"
5608 pr "On error this function returns -1.\n\n"
5610 pr "This function returns a C truth value on success or -1 on error.\n\n"
5612 pr "This function returns a string, or NULL on error.
5613 The string is owned by the guest handle and must I<not> be freed.\n\n"
5614 | RConstOptString _ ->
5615 pr "This function returns a string which may be NULL.
5616 There is no way to return an error from this function.
5617 The string is owned by the guest handle and must I<not> be freed.\n\n"
5619 pr "This function returns a string, or NULL on error.
5620 I<The caller must free the returned string after use>.\n\n"
5622 pr "This function returns a NULL-terminated array of strings
5623 (like L<environ(3)>), or NULL if there was an error.
5624 I<The caller must free the strings and the array after use>.\n\n"
5625 | RStruct (_, typ) ->
5626 pr "This function returns a C<struct guestfs_%s *>,
5627 or NULL if there was an error.
5628 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5629 | RStructList (_, typ) ->
5630 pr "This function returns a C<struct guestfs_%s_list *>
5631 (see E<lt>guestfs-structs.hE<gt>),
5632 or NULL if there was an error.
5633 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5635 pr "This function returns a NULL-terminated array of
5636 strings, or NULL if there was an error.
5637 The array of strings will always have length C<2n+1>, where
5638 C<n> keys and values alternate, followed by the trailing NULL entry.
5639 I<The caller must free the strings and the array after use>.\n\n"
5641 pr "This function returns a buffer, or NULL on error.
5642 The size of the returned buffer is written to C<*size_r>.
5643 I<The caller must free the returned buffer after use>.\n\n"
5645 if List.mem ProtocolLimitWarning flags then
5646 pr "%s\n\n" protocol_limit_warning;
5647 if List.mem DangerWillRobinson flags then
5648 pr "%s\n\n" danger_will_robinson;
5649 match deprecation_notice flags with
5651 | Some txt -> pr "%s\n\n" txt
5653 ) all_functions_sorted
5655 and generate_structs_pod () =
5656 (* Structs documentation. *)
5659 pr "=head2 guestfs_%s\n" typ;
5661 pr " struct guestfs_%s {\n" typ;
5664 | name, FChar -> pr " char %s;\n" name
5665 | name, FUInt32 -> pr " uint32_t %s;\n" name
5666 | name, FInt32 -> pr " int32_t %s;\n" name
5667 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5668 | name, FInt64 -> pr " int64_t %s;\n" name
5669 | name, FString -> pr " char *%s;\n" name
5671 pr " /* The next two fields describe a byte array. */\n";
5672 pr " uint32_t %s_len;\n" name;
5673 pr " char *%s;\n" name
5675 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5676 pr " char %s[32];\n" name
5677 | name, FOptPercent ->
5678 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5679 pr " float %s;\n" name
5683 pr " struct guestfs_%s_list {\n" typ;
5684 pr " uint32_t len; /* Number of elements in list. */\n";
5685 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5688 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5689 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5694 and generate_availability_pod () =
5695 (* Availability documentation. *)
5699 fun (group, functions) ->
5700 pr "=item B<%s>\n" group;
5702 pr "The following functions:\n";
5703 List.iter (pr "L</guestfs_%s>\n") functions;
5709 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5710 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5712 * We have to use an underscore instead of a dash because otherwise
5713 * rpcgen generates incorrect code.
5715 * This header is NOT exported to clients, but see also generate_structs_h.
5717 and generate_xdr () =
5718 generate_header CStyle LGPLv2plus;
5720 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5721 pr "typedef string guestfs_str<>;\n";
5724 (* Internal structures. *)
5728 pr "struct guestfs_int_%s {\n" typ;
5730 | name, FChar -> pr " char %s;\n" name
5731 | name, FString -> pr " string %s<>;\n" name
5732 | name, FBuffer -> pr " opaque %s<>;\n" name
5733 | name, FUUID -> pr " opaque %s[32];\n" name
5734 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5735 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5736 | name, FOptPercent -> pr " float %s;\n" name
5740 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5745 fun (shortname, style, _, _, _, _, _) ->
5746 let name = "guestfs_" ^ shortname in
5748 (match snd style with
5751 pr "struct %s_args {\n" name;
5754 | Pathname n | Device n | Dev_or_Path n | String n ->
5755 pr " string %s<>;\n" n
5756 | OptString n -> pr " guestfs_str *%s;\n" n
5757 | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n
5758 | Bool n -> pr " bool %s;\n" n
5759 | Int n -> pr " int %s;\n" n
5760 | Int64 n -> pr " hyper %s;\n" n
5762 pr " opaque %s<>;\n" n
5763 | FileIn _ | FileOut _ -> ()
5767 (match fst style with
5770 pr "struct %s_ret {\n" name;
5774 pr "struct %s_ret {\n" name;
5775 pr " hyper %s;\n" n;
5778 pr "struct %s_ret {\n" name;
5781 | RConstString _ | RConstOptString _ ->
5782 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5784 pr "struct %s_ret {\n" name;
5785 pr " string %s<>;\n" n;
5788 pr "struct %s_ret {\n" name;
5789 pr " guestfs_str %s<>;\n" n;
5791 | RStruct (n, typ) ->
5792 pr "struct %s_ret {\n" name;
5793 pr " guestfs_int_%s %s;\n" typ n;
5795 | RStructList (n, typ) ->
5796 pr "struct %s_ret {\n" name;
5797 pr " guestfs_int_%s_list %s;\n" typ n;
5800 pr "struct %s_ret {\n" name;
5801 pr " guestfs_str %s<>;\n" n;
5804 pr "struct %s_ret {\n" name;
5805 pr " opaque %s<>;\n" n;
5810 (* Table of procedure numbers. *)
5811 pr "enum guestfs_procedure {\n";
5813 fun (shortname, _, proc_nr, _, _, _, _) ->
5814 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5816 pr " GUESTFS_PROC_NR_PROCS\n";
5820 (* Having to choose a maximum message size is annoying for several
5821 * reasons (it limits what we can do in the API), but it (a) makes
5822 * the protocol a lot simpler, and (b) provides a bound on the size
5823 * of the daemon which operates in limited memory space.
5825 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5828 (* Message header, etc. *)
5830 /* The communication protocol is now documented in the guestfs(3)
5834 const GUESTFS_PROGRAM = 0x2000F5F5;
5835 const GUESTFS_PROTOCOL_VERSION = 1;
5837 /* These constants must be larger than any possible message length. */
5838 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5839 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5841 enum guestfs_message_direction {
5842 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5843 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5846 enum guestfs_message_status {
5847 GUESTFS_STATUS_OK = 0,
5848 GUESTFS_STATUS_ERROR = 1
5851 const GUESTFS_ERROR_LEN = 256;
5853 struct guestfs_message_error {
5854 string error_message<GUESTFS_ERROR_LEN>;
5857 struct guestfs_message_header {
5858 unsigned prog; /* GUESTFS_PROGRAM */
5859 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5860 guestfs_procedure proc; /* GUESTFS_PROC_x */
5861 guestfs_message_direction direction;
5862 unsigned serial; /* message serial number */
5863 guestfs_message_status status;
5866 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5868 struct guestfs_chunk {
5869 int cancel; /* if non-zero, transfer is cancelled */
5870 /* data size is 0 bytes if the transfer has finished successfully */
5871 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5875 (* Generate the guestfs-structs.h file. *)
5876 and generate_structs_h () =
5877 generate_header CStyle LGPLv2plus;
5879 (* This is a public exported header file containing various
5880 * structures. The structures are carefully written to have
5881 * exactly the same in-memory format as the XDR structures that
5882 * we use on the wire to the daemon. The reason for creating
5883 * copies of these structures here is just so we don't have to
5884 * export the whole of guestfs_protocol.h (which includes much
5885 * unrelated and XDR-dependent stuff that we don't want to be
5886 * public, or required by clients).
5888 * To reiterate, we will pass these structures to and from the
5889 * client with a simple assignment or memcpy, so the format
5890 * must be identical to what rpcgen / the RFC defines.
5893 (* Public structures. *)
5896 pr "struct guestfs_%s {\n" typ;
5899 | name, FChar -> pr " char %s;\n" name
5900 | name, FString -> pr " char *%s;\n" name
5902 pr " uint32_t %s_len;\n" name;
5903 pr " char *%s;\n" name
5904 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5905 | name, FUInt32 -> pr " uint32_t %s;\n" name
5906 | name, FInt32 -> pr " int32_t %s;\n" name
5907 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5908 | name, FInt64 -> pr " int64_t %s;\n" name
5909 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5913 pr "struct guestfs_%s_list {\n" typ;
5914 pr " uint32_t len;\n";
5915 pr " struct guestfs_%s *val;\n" typ;
5918 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5919 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5923 (* Generate the guestfs-actions.h file. *)
5924 and generate_actions_h () =
5925 generate_header CStyle LGPLv2plus;
5927 fun (shortname, style, _, _, _, _, _) ->
5928 let name = "guestfs_" ^ shortname in
5929 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5933 (* Generate the guestfs-internal-actions.h file. *)
5934 and generate_internal_actions_h () =
5935 generate_header CStyle LGPLv2plus;
5937 fun (shortname, style, _, _, _, _, _) ->
5938 let name = "guestfs__" ^ shortname in
5939 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5941 ) non_daemon_functions
5943 (* Generate the client-side dispatch stubs. *)
5944 and generate_client_actions () =
5945 generate_header CStyle LGPLv2plus;
5952 #include <inttypes.h>
5954 #include \"guestfs.h\"
5955 #include \"guestfs-internal.h\"
5956 #include \"guestfs-internal-actions.h\"
5957 #include \"guestfs_protocol.h\"
5959 /* Check the return message from a call for validity. */
5961 check_reply_header (guestfs_h *g,
5962 const struct guestfs_message_header *hdr,
5963 unsigned int proc_nr, unsigned int serial)
5965 if (hdr->prog != GUESTFS_PROGRAM) {
5966 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5969 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5970 error (g, \"wrong protocol version (%%d/%%d)\",
5971 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5974 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5975 error (g, \"unexpected message direction (%%d/%%d)\",
5976 hdr->direction, GUESTFS_DIRECTION_REPLY);
5979 if (hdr->proc != proc_nr) {
5980 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5983 if (hdr->serial != serial) {
5984 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5991 /* Check we are in the right state to run a high-level action. */
5993 check_state (guestfs_h *g, const char *caller)
5995 if (!guestfs__is_ready (g)) {
5996 if (guestfs__is_config (g) || guestfs__is_launching (g))
5997 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6000 error (g, \"%%s called from the wrong state, %%d != READY\",
6001 caller, guestfs__get_state (g));
6009 let error_code_of = function
6010 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6011 | RConstString _ | RConstOptString _
6012 | RString _ | RStringList _
6013 | RStruct _ | RStructList _
6014 | RHashtable _ | RBufferOut _ -> "NULL"
6017 (* Generate code to check String-like parameters are not passed in
6018 * as NULL (returning an error if they are).
6020 let check_null_strings shortname style =
6021 let pr_newline = ref false in
6024 (* parameters which should not be NULL *)
6034 pr " if (%s == NULL) {\n" n;
6035 pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6036 pr " \"%s\", \"%s\");\n" shortname n;
6037 pr " return %s;\n" (error_code_of (fst style));
6044 (* not applicable *)
6050 if !pr_newline then pr "\n";
6053 (* Generate code to generate guestfish call traces. *)
6054 let trace_call shortname style =
6055 pr " if (guestfs__get_trace (g)) {\n";
6058 List.exists (function
6059 | StringList _ | DeviceList _ -> true
6060 | _ -> false) (snd style) in
6066 pr " printf (\"%s\");\n" shortname;
6069 | String n (* strings *)
6076 (* guestfish doesn't support string escaping, so neither do we *)
6077 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
6078 | OptString n -> (* string option *)
6079 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6080 pr " else printf (\" null\");\n"
6082 | DeviceList n -> (* string list *)
6083 pr " putchar (' ');\n";
6084 pr " putchar ('\"');\n";
6085 pr " for (i = 0; %s[i]; ++i) {\n" n;
6086 pr " if (i > 0) putchar (' ');\n";
6087 pr " fputs (%s[i], stdout);\n" n;
6089 pr " putchar ('\"');\n";
6090 | Bool n -> (* boolean *)
6091 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
6092 | Int n -> (* int *)
6093 pr " printf (\" %%d\", %s);\n" n
6095 pr " printf (\" %%\" PRIi64, %s);\n" n
6097 pr " putchar ('\\n');\n";
6102 (* For non-daemon functions, generate a wrapper around each function. *)
6104 fun (shortname, style, _, _, _, _, _) ->
6105 let name = "guestfs_" ^ shortname in
6107 generate_prototype ~extern:false ~semicolon:false ~newline:true
6108 ~handle:"g" name style;
6110 check_null_strings shortname style;
6111 trace_call shortname style;
6112 pr " return guestfs__%s " shortname;
6113 generate_c_call_args ~handle:"g" style;
6117 ) non_daemon_functions;
6119 (* Client-side stubs for each function. *)
6121 fun (shortname, style, _, _, _, _, _) ->
6122 let name = "guestfs_" ^ shortname in
6123 let error_code = error_code_of (fst style) in
6125 (* Generate the action stub. *)
6126 generate_prototype ~extern:false ~semicolon:false ~newline:true
6127 ~handle:"g" name style;
6131 (match snd style with
6133 | _ -> pr " struct %s_args args;\n" name
6136 pr " guestfs_message_header hdr;\n";
6137 pr " guestfs_message_error err;\n";
6139 match fst style with
6141 | RConstString _ | RConstOptString _ ->
6142 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6144 | RBool _ | RString _ | RStringList _
6145 | RStruct _ | RStructList _
6146 | RHashtable _ | RBufferOut _ ->
6147 pr " struct %s_ret ret;\n" name;
6150 pr " int serial;\n";
6153 check_null_strings shortname style;
6154 trace_call shortname style;
6155 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
6156 shortname error_code;
6157 pr " guestfs___set_busy (g);\n";
6160 (* Send the main header and arguments. *)
6161 (match snd style with
6163 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6164 (String.uppercase shortname)
6168 | Pathname n | Device n | Dev_or_Path n | String n ->
6169 pr " args.%s = (char *) %s;\n" n n
6171 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
6172 | StringList n | DeviceList n ->
6173 pr " args.%s.%s_val = (char **) %s;\n" n n n;
6174 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6176 pr " args.%s = %s;\n" n n
6178 pr " args.%s = %s;\n" n n
6180 pr " args.%s = %s;\n" n n
6181 | FileIn _ | FileOut _ -> ()
6183 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6184 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6185 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6187 pr " guestfs___end_busy (g);\n";
6188 pr " return %s;\n" error_code;
6190 pr " args.%s.%s_val = (char *) %s;\n" n n n;
6191 pr " args.%s.%s_len = %s_size;\n" n n n
6193 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6194 (String.uppercase shortname);
6195 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6198 pr " if (serial == -1) {\n";
6199 pr " guestfs___end_busy (g);\n";
6200 pr " return %s;\n" error_code;
6204 (* Send any additional files (FileIn) requested. *)
6205 let need_read_reply_label = ref false in
6209 pr " r = guestfs___send_file (g, %s);\n" n;
6210 pr " if (r == -1) {\n";
6211 pr " guestfs___end_busy (g);\n";
6212 pr " return %s;\n" error_code;
6214 pr " if (r == -2) /* daemon cancelled */\n";
6215 pr " goto read_reply;\n";
6216 need_read_reply_label := true;
6221 (* Wait for the reply from the remote end. *)
6222 if !need_read_reply_label then pr " read_reply:\n";
6223 pr " memset (&hdr, 0, sizeof hdr);\n";
6224 pr " memset (&err, 0, sizeof err);\n";
6225 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
6227 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
6231 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6234 pr " if (r == -1) {\n";
6235 pr " guestfs___end_busy (g);\n";
6236 pr " return %s;\n" error_code;
6240 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6241 (String.uppercase shortname);
6242 pr " guestfs___end_busy (g);\n";
6243 pr " return %s;\n" error_code;
6247 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6248 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6249 pr " free (err.error_message);\n";
6250 pr " guestfs___end_busy (g);\n";
6251 pr " return %s;\n" error_code;
6255 (* Expecting to receive further files (FileOut)? *)
6259 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6260 pr " guestfs___end_busy (g);\n";
6261 pr " return %s;\n" error_code;
6267 pr " guestfs___end_busy (g);\n";
6269 (match fst style with
6270 | RErr -> pr " return 0;\n"
6271 | RInt n | RInt64 n | RBool n ->
6272 pr " return ret.%s;\n" n
6273 | RConstString _ | RConstOptString _ ->
6274 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6276 pr " return ret.%s; /* caller will free */\n" n
6277 | RStringList n | RHashtable n ->
6278 pr " /* caller will free this, but we need to add a NULL entry */\n";
6279 pr " ret.%s.%s_val =\n" n n;
6280 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6281 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6283 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6284 pr " return ret.%s.%s_val;\n" n n
6286 pr " /* caller will free this */\n";
6287 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6288 | RStructList (n, _) ->
6289 pr " /* caller will free this */\n";
6290 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6292 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6293 pr " * _val might be NULL here. To make the API saner for\n";
6294 pr " * callers, we turn this case into a unique pointer (using\n";
6295 pr " * malloc(1)).\n";
6297 pr " if (ret.%s.%s_len > 0) {\n" n n;
6298 pr " *size_r = ret.%s.%s_len;\n" n n;
6299 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6301 pr " free (ret.%s.%s_val);\n" n n;
6302 pr " char *p = safe_malloc (g, 1);\n";
6303 pr " *size_r = ret.%s.%s_len;\n" n n;
6311 (* Functions to free structures. *)
6312 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6313 pr " * structure format is identical to the XDR format. See note in\n";
6314 pr " * generator.ml.\n";
6321 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6323 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6329 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6331 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6338 (* Generate daemon/actions.h. *)
6339 and generate_daemon_actions_h () =
6340 generate_header CStyle GPLv2plus;
6342 pr "#include \"../src/guestfs_protocol.h\"\n";
6346 fun (name, style, _, _, _, _, _) ->
6348 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6352 (* Generate the linker script which controls the visibility of
6353 * symbols in the public ABI and ensures no other symbols get
6354 * exported accidentally.
6356 and generate_linker_script () =
6357 generate_header HashStyle GPLv2plus;
6362 "guestfs_get_error_handler";
6363 "guestfs_get_out_of_memory_handler";
6364 "guestfs_last_error";
6365 "guestfs_set_close_callback";
6366 "guestfs_set_error_handler";
6367 "guestfs_set_launch_done_callback";
6368 "guestfs_set_log_message_callback";
6369 "guestfs_set_out_of_memory_handler";
6370 "guestfs_set_subprocess_quit_callback";
6372 (* Unofficial parts of the API: the bindings code use these
6373 * functions, so it is useful to export them.
6375 "guestfs_safe_calloc";
6376 "guestfs_safe_malloc";
6377 "guestfs_safe_strdup";
6378 "guestfs_safe_memdup";
6381 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6385 List.map (fun (typ, _) ->
6386 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6389 let globals = List.sort compare (globals @ functions @ structs) in
6393 List.iter (pr " %s;\n") globals;
6400 (* Generate the server-side stubs. *)
6401 and generate_daemon_actions () =
6402 generate_header CStyle GPLv2plus;
6404 pr "#include <config.h>\n";
6406 pr "#include <stdio.h>\n";
6407 pr "#include <stdlib.h>\n";
6408 pr "#include <string.h>\n";
6409 pr "#include <inttypes.h>\n";
6410 pr "#include <rpc/types.h>\n";
6411 pr "#include <rpc/xdr.h>\n";
6413 pr "#include \"daemon.h\"\n";
6414 pr "#include \"c-ctype.h\"\n";
6415 pr "#include \"../src/guestfs_protocol.h\"\n";
6416 pr "#include \"actions.h\"\n";
6420 fun (name, style, _, _, _, _, _) ->
6421 (* Generate server-side stubs. *)
6422 pr "static void %s_stub (XDR *xdr_in)\n" name;
6425 match fst style with
6426 | RErr | RInt _ -> pr " int r;\n"; "-1"
6427 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6428 | RBool _ -> pr " int r;\n"; "-1"
6429 | RConstString _ | RConstOptString _ ->
6430 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6431 | RString _ -> pr " char *r;\n"; "NULL"
6432 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6433 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6434 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6436 pr " size_t size = 1;\n";
6440 (match snd style with
6443 pr " struct guestfs_%s_args args;\n" name;
6446 | Device n | Dev_or_Path n
6449 | OptString n -> pr " char *%s;\n" n
6450 | StringList n | DeviceList n -> pr " char **%s;\n" n
6451 | Bool n -> pr " int %s;\n" n
6452 | Int n -> pr " int %s;\n" n
6453 | Int64 n -> pr " int64_t %s;\n" n
6454 | FileIn _ | FileOut _ -> ()
6456 pr " const char *%s;\n" n;
6457 pr " size_t %s_size;\n" n
6463 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6465 (match snd style with
6468 pr " memset (&args, 0, sizeof args);\n";
6470 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6472 pr " if (cancel_receive () != -2)\n";
6473 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6477 pr " char *%s = args.%s;\n" n n
6479 let pr_list_handling_code n =
6480 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6481 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6482 pr " if (%s == NULL) {\n" n;
6484 pr " if (cancel_receive () != -2)\n";
6485 pr " reply_with_perror (\"realloc\");\n";
6488 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6489 pr " args.%s.%s_val = %s;\n" n n n;
6495 pr " ABS_PATH (%s, %s, goto done);\n"
6496 n (if is_filein then "cancel_receive ()" else "0");
6499 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6500 n (if is_filein then "cancel_receive ()" else "0");
6503 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6504 n (if is_filein then "cancel_receive ()" else "0");
6505 | String n -> pr_args n
6506 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6508 pr_list_handling_code n;
6510 pr_list_handling_code n;
6511 pr " /* Ensure that each is a device,\n";
6512 pr " * and perform device name translation.\n";
6516 pr " for (i = 0; %s[i] != NULL; ++i)\n" n;
6517 pr " RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6518 (if is_filein then "cancel_receive ()" else "0");
6520 | Bool n -> pr " %s = args.%s;\n" n n
6521 | Int n -> pr " %s = args.%s;\n" n n
6522 | Int64 n -> pr " %s = args.%s;\n" n n
6523 | FileIn _ | FileOut _ -> ()
6525 pr " %s = args.%s.%s_val;\n" n n n;
6526 pr " %s_size = args.%s.%s_len;\n" n n n
6531 (* this is used at least for do_equal *)
6532 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6533 (* Emit NEED_ROOT just once, even when there are two or
6534 more Pathname args *)
6535 pr " NEED_ROOT (%s, goto done);\n"
6536 (if is_filein then "cancel_receive ()" else "0");
6539 (* Don't want to call the impl with any FileIn or FileOut
6540 * parameters, since these go "outside" the RPC protocol.
6543 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6545 pr " r = do_%s " name;
6546 generate_c_call_args (fst style, args');
6549 (match fst style with
6550 | RErr | RInt _ | RInt64 _ | RBool _
6551 | RConstString _ | RConstOptString _
6552 | RString _ | RStringList _ | RHashtable _
6553 | RStruct (_, _) | RStructList (_, _) ->
6554 pr " if (r == %s)\n" error_code;
6555 pr " /* do_%s has already called reply_with_error */\n" name;
6559 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6560 pr " * an ordinary zero-length buffer), so be careful ...\n";
6562 pr " if (size == 1 && r == %s)\n" error_code;
6563 pr " /* do_%s has already called reply_with_error */\n" name;
6568 (* If there are any FileOut parameters, then the impl must
6569 * send its own reply.
6572 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6574 pr " /* do_%s has already sent a reply */\n" name
6576 match fst style with
6577 | RErr -> pr " reply (NULL, NULL);\n"
6578 | RInt n | RInt64 n | RBool n ->
6579 pr " struct guestfs_%s_ret ret;\n" name;
6580 pr " ret.%s = r;\n" n;
6581 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6583 | RConstString _ | RConstOptString _ ->
6584 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6586 pr " struct guestfs_%s_ret ret;\n" name;
6587 pr " ret.%s = r;\n" n;
6588 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6591 | RStringList n | RHashtable n ->
6592 pr " struct guestfs_%s_ret ret;\n" name;
6593 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6594 pr " ret.%s.%s_val = r;\n" n n;
6595 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6597 pr " free_strings (r);\n"
6599 pr " struct guestfs_%s_ret ret;\n" name;
6600 pr " ret.%s = *r;\n" n;
6601 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6603 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6605 | RStructList (n, _) ->
6606 pr " struct guestfs_%s_ret ret;\n" name;
6607 pr " ret.%s = *r;\n" n;
6608 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6610 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6613 pr " struct guestfs_%s_ret ret;\n" name;
6614 pr " ret.%s.%s_val = r;\n" n n;
6615 pr " ret.%s.%s_len = size;\n" n n;
6616 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6621 (* Free the args. *)
6623 (match snd style with
6626 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6633 (* Dispatch function. *)
6634 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6636 pr " switch (proc_nr) {\n";
6639 fun (name, style, _, _, _, _, _) ->
6640 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6641 pr " %s_stub (xdr_in);\n" name;
6646 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";
6651 (* LVM columns and tokenization functions. *)
6652 (* XXX This generates crap code. We should rethink how we
6658 pr "static const char *lvm_%s_cols = \"%s\";\n"
6659 typ (String.concat "," (List.map fst cols));
6662 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6664 pr " char *tok, *p, *next;\n";
6665 pr " size_t i, j;\n";
6668 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6671 pr " if (!str) {\n";
6672 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6675 pr " if (!*str || c_isspace (*str)) {\n";
6676 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6681 fun (name, coltype) ->
6682 pr " if (!tok) {\n";
6683 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6686 pr " p = strchrnul (tok, ',');\n";
6687 pr " if (*p) next = p+1; else next = NULL;\n";
6688 pr " *p = '\\0';\n";
6691 pr " r->%s = strdup (tok);\n" name;
6692 pr " if (r->%s == NULL) {\n" name;
6693 pr " perror (\"strdup\");\n";
6697 pr " for (i = j = 0; i < 32; ++j) {\n";
6698 pr " if (tok[j] == '\\0') {\n";
6699 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6701 pr " } else if (tok[j] != '-')\n";
6702 pr " r->%s[i++] = tok[j];\n" name;
6705 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6706 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6710 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6711 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6715 pr " if (tok[0] == '\\0')\n";
6716 pr " r->%s = -1;\n" name;
6717 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6718 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6721 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6722 assert false (* can never be an LVM column *)
6724 pr " tok = next;\n";
6727 pr " if (tok != NULL) {\n";
6728 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6735 pr "guestfs_int_lvm_%s_list *\n" typ;
6736 pr "parse_command_line_%ss (void)\n" typ;
6738 pr " char *out, *err;\n";
6739 pr " char *p, *pend;\n";
6741 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6742 pr " void *newp;\n";
6744 pr " ret = malloc (sizeof *ret);\n";
6745 pr " if (!ret) {\n";
6746 pr " reply_with_perror (\"malloc\");\n";
6747 pr " return NULL;\n";
6750 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6751 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6753 pr " r = command (&out, &err,\n";
6754 pr " \"lvm\", \"%ss\",\n" typ;
6755 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6756 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6757 pr " if (r == -1) {\n";
6758 pr " reply_with_error (\"%%s\", err);\n";
6759 pr " free (out);\n";
6760 pr " free (err);\n";
6761 pr " free (ret);\n";
6762 pr " return NULL;\n";
6765 pr " free (err);\n";
6767 pr " /* Tokenize each line of the output. */\n";
6770 pr " while (p) {\n";
6771 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6772 pr " if (pend) {\n";
6773 pr " *pend = '\\0';\n";
6777 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6780 pr " if (!*p) { /* Empty line? Skip it. */\n";
6785 pr " /* Allocate some space to store this next entry. */\n";
6786 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6787 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6788 pr " if (newp == NULL) {\n";
6789 pr " reply_with_perror (\"realloc\");\n";
6790 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6791 pr " free (ret);\n";
6792 pr " free (out);\n";
6793 pr " return NULL;\n";
6795 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6797 pr " /* Tokenize the next entry. */\n";
6798 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6799 pr " if (r == -1) {\n";
6800 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6801 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6802 pr " free (ret);\n";
6803 pr " free (out);\n";
6804 pr " return NULL;\n";
6811 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6813 pr " free (out);\n";
6814 pr " return ret;\n";
6817 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6819 (* Generate a list of function names, for debugging in the daemon.. *)
6820 and generate_daemon_names () =
6821 generate_header CStyle GPLv2plus;
6823 pr "#include <config.h>\n";
6825 pr "#include \"daemon.h\"\n";
6828 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6829 pr "const char *function_names[] = {\n";
6831 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6835 (* Generate the optional groups for the daemon to implement
6836 * guestfs_available.
6838 and generate_daemon_optgroups_c () =
6839 generate_header CStyle GPLv2plus;
6841 pr "#include <config.h>\n";
6843 pr "#include \"daemon.h\"\n";
6844 pr "#include \"optgroups.h\"\n";
6847 pr "struct optgroup optgroups[] = {\n";
6850 pr " { \"%s\", optgroup_%s_available },\n" group group
6852 pr " { NULL, NULL }\n";
6855 and generate_daemon_optgroups_h () =
6856 generate_header CStyle GPLv2plus;
6860 pr "extern int optgroup_%s_available (void);\n" group
6863 (* Generate the tests. *)
6864 and generate_tests () =
6865 generate_header CStyle GPLv2plus;
6872 #include <sys/types.h>
6875 #include \"guestfs.h\"
6876 #include \"guestfs-internal.h\"
6878 static guestfs_h *g;
6879 static int suppress_error = 0;
6881 static void print_error (guestfs_h *g, void *data, const char *msg)
6883 if (!suppress_error)
6884 fprintf (stderr, \"%%s\\n\", msg);
6887 /* FIXME: nearly identical code appears in fish.c */
6888 static void print_strings (char *const *argv)
6892 for (argc = 0; argv[argc] != NULL; ++argc)
6893 printf (\"\\t%%s\\n\", argv[argc]);
6897 static void print_table (char const *const *argv)
6901 for (i = 0; argv[i] != NULL; i += 2)
6902 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6907 is_available (const char *group)
6909 const char *groups[] = { group, NULL };
6913 r = guestfs_available (g, (char **) groups);
6920 incr (guestfs_h *g, void *iv)
6922 int *i = (int *) iv;
6928 (* Generate a list of commands which are not tested anywhere. *)
6929 pr "static void no_test_warnings (void)\n";
6932 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6934 fun (_, _, _, _, tests, _, _) ->
6935 let tests = filter_map (
6937 | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6938 | (_, Disabled, _) -> None
6940 let seq = List.concat (List.map seq_of_test tests) in
6941 let cmds_tested = List.map List.hd seq in
6942 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6946 fun (name, _, _, _, _, _, _) ->
6947 if not (Hashtbl.mem hash name) then
6948 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6954 (* Generate the actual tests. Note that we generate the tests
6955 * in reverse order, deliberately, so that (in general) the
6956 * newest tests run first. This makes it quicker and easier to
6961 fun (name, _, _, flags, tests, _, _) ->
6962 mapi (generate_one_test name flags) tests
6963 ) (List.rev all_functions) in
6964 let test_names = List.concat test_names in
6965 let nr_tests = List.length test_names in
6968 int main (int argc, char *argv[])
6971 unsigned long int n_failed = 0;
6972 const char *filename;
6974 int nr_tests, test_num = 0;
6976 setbuf (stdout, NULL);
6978 no_test_warnings ();
6980 g = guestfs_create ();
6982 printf (\"guestfs_create FAILED\\n\");
6983 exit (EXIT_FAILURE);
6986 guestfs_set_error_handler (g, print_error, NULL);
6988 guestfs_set_path (g, \"../appliance\");
6990 filename = \"test1.img\";
6991 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6994 exit (EXIT_FAILURE);
6996 if (lseek (fd, %d, SEEK_SET) == -1) {
7000 exit (EXIT_FAILURE);
7002 if (write (fd, &c, 1) == -1) {
7006 exit (EXIT_FAILURE);
7008 if (close (fd) == -1) {
7011 exit (EXIT_FAILURE);
7013 if (guestfs_add_drive (g, filename) == -1) {
7014 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7015 exit (EXIT_FAILURE);
7018 filename = \"test2.img\";
7019 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7022 exit (EXIT_FAILURE);
7024 if (lseek (fd, %d, SEEK_SET) == -1) {
7028 exit (EXIT_FAILURE);
7030 if (write (fd, &c, 1) == -1) {
7034 exit (EXIT_FAILURE);
7036 if (close (fd) == -1) {
7039 exit (EXIT_FAILURE);
7041 if (guestfs_add_drive (g, filename) == -1) {
7042 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7043 exit (EXIT_FAILURE);
7046 filename = \"test3.img\";
7047 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7050 exit (EXIT_FAILURE);
7052 if (lseek (fd, %d, SEEK_SET) == -1) {
7056 exit (EXIT_FAILURE);
7058 if (write (fd, &c, 1) == -1) {
7062 exit (EXIT_FAILURE);
7064 if (close (fd) == -1) {
7067 exit (EXIT_FAILURE);
7069 if (guestfs_add_drive (g, filename) == -1) {
7070 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7071 exit (EXIT_FAILURE);
7074 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7075 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7076 exit (EXIT_FAILURE);
7079 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7082 if (guestfs_launch (g) == -1) {
7083 printf (\"guestfs_launch FAILED\\n\");
7084 exit (EXIT_FAILURE);
7087 /* Cancel previous alarm. */
7092 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7096 pr " test_num++;\n";
7097 pr " if (guestfs_get_verbose (g))\n";
7098 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
7099 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7100 pr " if (%s () == -1) {\n" test_name;
7101 pr " printf (\"%s FAILED\\n\");\n" test_name;
7102 pr " n_failed++;\n";
7107 pr " /* Check close callback is called. */
7108 int close_sentinel = 1;
7109 guestfs_set_close_callback (g, incr, &close_sentinel);
7113 if (close_sentinel != 2) {
7114 fprintf (stderr, \"close callback was not called\\n\");
7115 exit (EXIT_FAILURE);
7118 unlink (\"test1.img\");
7119 unlink (\"test2.img\");
7120 unlink (\"test3.img\");
7124 pr " if (n_failed > 0) {\n";
7125 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7126 pr " exit (EXIT_FAILURE);\n";
7130 pr " exit (EXIT_SUCCESS);\n";
7133 and generate_one_test name flags i (init, prereq, test) =
7134 let test_name = sprintf "test_%s_%d" name i in
7137 static int %s_skip (void)
7141 str = getenv (\"TEST_ONLY\");
7143 return strstr (str, \"%s\") == NULL;
7144 str = getenv (\"SKIP_%s\");
7145 if (str && STREQ (str, \"1\")) return 1;
7146 str = getenv (\"SKIP_TEST_%s\");
7147 if (str && STREQ (str, \"1\")) return 1;
7151 " test_name name (String.uppercase test_name) (String.uppercase name);
7154 | Disabled | Always | IfAvailable _ -> ()
7155 | If code | Unless code ->
7156 pr "static int %s_prereq (void)\n" test_name;
7164 static int %s (void)
7167 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
7171 " test_name test_name test_name;
7173 (* Optional functions should only be tested if the relevant
7174 * support is available in the daemon.
7179 pr " if (!is_available (\"%s\")) {\n" group;
7180 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7188 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7190 pr " if (! %s_prereq ()) {\n" test_name;
7191 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7195 generate_one_test_body name i test_name init test;
7197 pr " if (%s_prereq ()) {\n" test_name;
7198 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7202 generate_one_test_body name i test_name init test;
7203 | IfAvailable group ->
7204 pr " if (!is_available (\"%s\")) {\n" group;
7205 pr " printf (\" %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7209 generate_one_test_body name i test_name init test;
7211 generate_one_test_body name i test_name init test
7219 and generate_one_test_body name i test_name init test =
7221 | InitNone (* XXX at some point, InitNone and InitEmpty became
7222 * folded together as the same thing. Really we should
7223 * make InitNone do nothing at all, but the tests may
7224 * need to be checked to make sure this is OK.
7227 pr " /* InitNone|InitEmpty for %s */\n" test_name;
7228 List.iter (generate_test_command_call test_name)
7229 [["blockdev_setrw"; "/dev/sda"];
7233 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7234 List.iter (generate_test_command_call test_name)
7235 [["blockdev_setrw"; "/dev/sda"];
7238 ["part_disk"; "/dev/sda"; "mbr"]]
7240 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7241 List.iter (generate_test_command_call test_name)
7242 [["blockdev_setrw"; "/dev/sda"];
7245 ["part_disk"; "/dev/sda"; "mbr"];
7246 ["mkfs"; "ext2"; "/dev/sda1"];
7247 ["mount_options"; ""; "/dev/sda1"; "/"]]
7248 | InitBasicFSonLVM ->
7249 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7251 List.iter (generate_test_command_call test_name)
7252 [["blockdev_setrw"; "/dev/sda"];
7255 ["part_disk"; "/dev/sda"; "mbr"];
7256 ["pvcreate"; "/dev/sda1"];
7257 ["vgcreate"; "VG"; "/dev/sda1"];
7258 ["lvcreate"; "LV"; "VG"; "8"];
7259 ["mkfs"; "ext2"; "/dev/VG/LV"];
7260 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7262 pr " /* InitISOFS for %s */\n" test_name;
7263 List.iter (generate_test_command_call test_name)
7264 [["blockdev_setrw"; "/dev/sda"];
7267 ["mount_ro"; "/dev/sdd"; "/"]]
7270 let get_seq_last = function
7272 failwithf "%s: you cannot use [] (empty list) when expecting a command"
7275 let seq = List.rev seq in
7276 List.rev (List.tl seq), List.hd seq
7281 pr " /* TestRun for %s (%d) */\n" name i;
7282 List.iter (generate_test_command_call test_name) seq
7283 | TestOutput (seq, expected) ->
7284 pr " /* TestOutput for %s (%d) */\n" name i;
7285 pr " const char *expected = \"%s\";\n" (c_quote expected);
7286 let seq, last = get_seq_last seq in
7288 pr " if (STRNEQ (r, expected)) {\n";
7289 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7293 List.iter (generate_test_command_call test_name) seq;
7294 generate_test_command_call ~test test_name last
7295 | TestOutputList (seq, expected) ->
7296 pr " /* TestOutputList for %s (%d) */\n" name i;
7297 let seq, last = get_seq_last seq in
7301 pr " if (!r[%d]) {\n" i;
7302 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7303 pr " print_strings (r);\n";
7307 pr " const char *expected = \"%s\";\n" (c_quote str);
7308 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7309 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7314 pr " if (r[%d] != NULL) {\n" (List.length expected);
7315 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7317 pr " print_strings (r);\n";
7321 List.iter (generate_test_command_call test_name) seq;
7322 generate_test_command_call ~test test_name last
7323 | TestOutputListOfDevices (seq, expected) ->
7324 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7325 let seq, last = get_seq_last seq in
7329 pr " if (!r[%d]) {\n" i;
7330 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7331 pr " print_strings (r);\n";
7335 pr " const char *expected = \"%s\";\n" (c_quote str);
7336 pr " r[%d][5] = 's';\n" i;
7337 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7338 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7343 pr " if (r[%d] != NULL) {\n" (List.length expected);
7344 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7346 pr " print_strings (r);\n";
7350 List.iter (generate_test_command_call test_name) seq;
7351 generate_test_command_call ~test test_name last
7352 | TestOutputInt (seq, expected) ->
7353 pr " /* TestOutputInt for %s (%d) */\n" name i;
7354 let seq, last = get_seq_last seq in
7356 pr " if (r != %d) {\n" expected;
7357 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7363 List.iter (generate_test_command_call test_name) seq;
7364 generate_test_command_call ~test test_name last
7365 | TestOutputIntOp (seq, op, expected) ->
7366 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7367 let seq, last = get_seq_last seq in
7369 pr " if (! (r %s %d)) {\n" op expected;
7370 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7371 test_name op expected;
7376 List.iter (generate_test_command_call test_name) seq;
7377 generate_test_command_call ~test test_name last
7378 | TestOutputTrue seq ->
7379 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7380 let seq, last = get_seq_last seq in
7383 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7388 List.iter (generate_test_command_call test_name) seq;
7389 generate_test_command_call ~test test_name last
7390 | TestOutputFalse seq ->
7391 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7392 let seq, last = get_seq_last seq in
7395 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7400 List.iter (generate_test_command_call test_name) seq;
7401 generate_test_command_call ~test test_name last
7402 | TestOutputLength (seq, expected) ->
7403 pr " /* TestOutputLength for %s (%d) */\n" name i;
7404 let seq, last = get_seq_last seq in
7407 pr " for (j = 0; j < %d; ++j)\n" expected;
7408 pr " if (r[j] == NULL) {\n";
7409 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7411 pr " print_strings (r);\n";
7414 pr " if (r[j] != NULL) {\n";
7415 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7417 pr " print_strings (r);\n";
7421 List.iter (generate_test_command_call test_name) seq;
7422 generate_test_command_call ~test test_name last
7423 | TestOutputBuffer (seq, expected) ->
7424 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7425 pr " const char *expected = \"%s\";\n" (c_quote expected);
7426 let seq, last = get_seq_last seq in
7427 let len = String.length expected in
7429 pr " if (size != %d) {\n" len;
7430 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7433 pr " if (STRNEQLEN (r, expected, size)) {\n";
7434 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7438 List.iter (generate_test_command_call test_name) seq;
7439 generate_test_command_call ~test test_name last
7440 | TestOutputStruct (seq, checks) ->
7441 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7442 let seq, last = get_seq_last seq in
7446 | CompareWithInt (field, expected) ->
7447 pr " if (r->%s != %d) {\n" field expected;
7448 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7449 test_name field expected;
7450 pr " (int) r->%s);\n" field;
7453 | CompareWithIntOp (field, op, expected) ->
7454 pr " if (!(r->%s %s %d)) {\n" field op expected;
7455 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7456 test_name field op expected;
7457 pr " (int) r->%s);\n" field;
7460 | CompareWithString (field, expected) ->
7461 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7462 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7463 test_name field expected;
7464 pr " r->%s);\n" field;
7467 | CompareFieldsIntEq (field1, field2) ->
7468 pr " if (r->%s != r->%s) {\n" field1 field2;
7469 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7470 test_name field1 field2;
7471 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7474 | CompareFieldsStrEq (field1, field2) ->
7475 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7476 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7477 test_name field1 field2;
7478 pr " r->%s, r->%s);\n" field1 field2;
7483 List.iter (generate_test_command_call test_name) seq;
7484 generate_test_command_call ~test test_name last
7485 | TestLastFail seq ->
7486 pr " /* TestLastFail for %s (%d) */\n" name i;
7487 let seq, last = get_seq_last seq in
7488 List.iter (generate_test_command_call test_name) seq;
7489 generate_test_command_call test_name ~expect_error:true last
7491 (* Generate the code to run a command, leaving the result in 'r'.
7492 * If you expect to get an error then you should set expect_error:true.
7494 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7496 | [] -> assert false
7498 (* Look up the command to find out what args/ret it has. *)
7501 let _, style, _, _, _, _, _ =
7502 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7505 failwithf "%s: in test, command %s was not found" test_name name in
7507 if List.length (snd style) <> List.length args then
7508 failwithf "%s: in test, wrong number of args given to %s"
7515 | OptString n, "NULL" -> ()
7518 | Dev_or_Path n, arg
7520 | OptString n, arg ->
7521 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7522 | BufferIn n, arg ->
7523 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7524 pr " size_t %s_size = %d;\n" n (String.length arg)
7528 | FileIn _, _ | FileOut _, _ -> ()
7529 | StringList n, "" | DeviceList n, "" ->
7530 pr " const char *const %s[1] = { NULL };\n" n
7531 | StringList n, arg | DeviceList n, arg ->
7532 let strs = string_split " " arg in
7535 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7537 pr " const char *const %s[] = {\n" n;
7539 fun i _ -> pr " %s_%d,\n" n i
7543 ) (List.combine (snd style) args);
7546 match fst style with
7547 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7548 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7549 | RConstString _ | RConstOptString _ ->
7550 pr " const char *r;\n"; "NULL"
7551 | RString _ -> pr " char *r;\n"; "NULL"
7552 | RStringList _ | RHashtable _ ->
7556 | RStruct (_, typ) ->
7557 pr " struct guestfs_%s *r;\n" typ; "NULL"
7558 | RStructList (_, typ) ->
7559 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7562 pr " size_t size;\n";
7565 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7566 pr " r = guestfs_%s (g" name;
7568 (* Generate the parameters. *)
7571 | OptString _, "NULL" -> pr ", NULL"
7573 | Device n, _ | Dev_or_Path n, _
7578 pr ", %s, %s_size" n n
7579 | FileIn _, arg | FileOut _, arg ->
7580 pr ", \"%s\"" (c_quote arg)
7581 | StringList n, _ | DeviceList n, _ ->
7582 pr ", (char **) %s" n
7585 try int_of_string arg
7586 with Failure "int_of_string" ->
7587 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7591 try Int64.of_string arg
7592 with Failure "int_of_string" ->
7593 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7596 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7597 ) (List.combine (snd style) args);
7599 (match fst style with
7600 | RBufferOut _ -> pr ", &size"
7606 if not expect_error then
7607 pr " if (r == %s)\n" error_code
7609 pr " if (r != %s)\n" error_code;
7612 (* Insert the test code. *)
7618 (match fst style with
7619 | RErr | RInt _ | RInt64 _ | RBool _
7620 | RConstString _ | RConstOptString _ -> ()
7621 | RString _ | RBufferOut _ -> pr " free (r);\n"
7622 | RStringList _ | RHashtable _ ->
7623 pr " for (i = 0; r[i] != NULL; ++i)\n";
7624 pr " free (r[i]);\n";
7626 | RStruct (_, typ) ->
7627 pr " guestfs_free_%s (r);\n" typ
7628 | RStructList (_, typ) ->
7629 pr " guestfs_free_%s_list (r);\n" typ
7635 let str = replace_str str "\r" "\\r" in
7636 let str = replace_str str "\n" "\\n" in
7637 let str = replace_str str "\t" "\\t" in
7638 let str = replace_str str "\000" "\\0" in
7641 (* Generate a lot of different functions for guestfish. *)
7642 and generate_fish_cmds () =
7643 generate_header CStyle GPLv2plus;
7647 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7649 let all_functions_sorted =
7651 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7652 ) all_functions_sorted in
7654 pr "#include <config.h>\n";
7656 pr "#include <stdio.h>\n";
7657 pr "#include <stdlib.h>\n";
7658 pr "#include <string.h>\n";
7659 pr "#include <inttypes.h>\n";
7661 pr "#include <guestfs.h>\n";
7662 pr "#include \"c-ctype.h\"\n";
7663 pr "#include \"full-write.h\"\n";
7664 pr "#include \"xstrtol.h\"\n";
7665 pr "#include \"fish.h\"\n";
7667 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
7668 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7671 (* list_commands function, which implements guestfish -h *)
7672 pr "void list_commands (void)\n";
7674 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7675 pr " list_builtin_commands ();\n";
7677 fun (name, _, _, flags, _, shortdesc, _) ->
7678 let name = replace_char name '_' '-' in
7679 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7681 ) all_functions_sorted;
7682 pr " printf (\" %%s\\n\",";
7683 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7687 (* display_command function, which implements guestfish -h cmd *)
7688 pr "int display_command (const char *cmd)\n";
7691 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7692 let name2 = replace_char name '_' '-' in
7694 try find_map (function FishAlias n -> Some n | _ -> None) flags
7695 with Not_found -> name in
7696 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7698 match snd style with
7702 name2 (String.concat " " (List.map name_of_argt args)) in
7705 if List.mem ProtocolLimitWarning flags then
7706 ("\n\n" ^ protocol_limit_warning)
7709 (* For DangerWillRobinson commands, we should probably have
7710 * guestfish prompt before allowing you to use them (especially
7711 * in interactive mode). XXX
7715 if List.mem DangerWillRobinson flags then
7716 ("\n\n" ^ danger_will_robinson)
7721 match deprecation_notice flags with
7723 | Some txt -> "\n\n" ^ txt in
7725 let describe_alias =
7726 if name <> alias then
7727 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7731 pr "STRCASEEQ (cmd, \"%s\")" name;
7732 if name <> name2 then
7733 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7734 if name <> alias then
7735 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7737 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7739 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7740 "=head1 DESCRIPTION\n\n" ^
7741 longdesc ^ warnings ^ describe_alias);
7746 pr " return display_builtin_command (cmd);\n";
7750 let emit_print_list_function typ =
7751 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7754 pr " unsigned int i;\n";
7756 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7757 pr " printf (\"[%%d] = {\\n\", i);\n";
7758 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7759 pr " printf (\"}\\n\");\n";
7765 (* print_* functions *)
7769 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7771 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7774 pr " unsigned int i;\n";
7780 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7782 pr " printf (\"%%s%s: \", indent);\n" name;
7783 pr " for (i = 0; i < 32; ++i)\n";
7784 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7785 pr " printf (\"\\n\");\n"
7787 pr " printf (\"%%s%s: \", indent);\n" name;
7788 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7789 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7790 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7792 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7793 pr " printf (\"\\n\");\n"
7794 | name, (FUInt64|FBytes) ->
7795 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7798 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7801 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7804 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7807 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7809 | name, FOptPercent ->
7810 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7811 typ name name typ name;
7812 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7818 (* Emit a print_TYPE_list function definition only if that function is used. *)
7821 | typ, (RStructListOnly | RStructAndList) ->
7822 (* generate the function for typ *)
7823 emit_print_list_function typ
7824 | typ, _ -> () (* empty *)
7825 ) (rstructs_used_by all_functions);
7827 (* Emit a print_TYPE function definition only if that function is used. *)
7830 | typ, (RStructOnly | RStructAndList) ->
7831 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7833 pr " print_%s_indent (%s, \"\");\n" typ typ;
7836 | typ, _ -> () (* empty *)
7837 ) (rstructs_used_by all_functions);
7839 (* run_<action> actions *)
7841 fun (name, style, _, flags, _, _, _) ->
7842 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7844 (match fst style with
7847 | RBool _ -> pr " int r;\n"
7848 | RInt64 _ -> pr " int64_t r;\n"
7849 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7850 | RString _ -> pr " char *r;\n"
7851 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7852 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7853 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7856 pr " size_t size;\n";
7862 | OptString n -> pr " const char *%s;\n" n
7866 | FileOut n -> pr " char *%s;\n" n
7868 pr " const char *%s;\n" n;
7869 pr " size_t %s_size;\n" n
7870 | StringList n | DeviceList n -> pr " char **%s;\n" n
7871 | Bool n -> pr " int %s;\n" n
7872 | Int n -> pr " int %s;\n" n
7873 | Int64 n -> pr " int64_t %s;\n" n
7876 (* Check and convert parameters. *)
7877 let argc_expected = List.length (snd style) in
7878 pr " if (argc != %d) {\n" argc_expected;
7879 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7881 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7885 let parse_integer fn fntyp rtyp range name i =
7887 pr " strtol_error xerr;\n";
7888 pr " %s r;\n" fntyp;
7890 pr " xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7891 pr " if (xerr != LONGINT_OK) {\n";
7892 pr " fprintf (stderr,\n";
7893 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7894 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7899 | Some (min, max, comment) ->
7900 pr " /* %s */\n" comment;
7901 pr " if (r < %s || r > %s) {\n" min max;
7902 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7906 pr " /* The check above should ensure this assignment does not overflow. */\n";
7908 pr " %s = r;\n" name;
7917 pr " %s = argv[%d];\n" name i
7919 | Dev_or_Path name ->
7920 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7921 pr " if (%s == NULL) return -1;\n" name
7923 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7926 pr " %s = argv[%d];\n" name i;
7927 pr " %s_size = strlen (argv[%d]);\n" name i
7929 pr " %s = file_in (argv[%d]);\n" name i;
7930 pr " if (%s == NULL) return -1;\n" name
7932 pr " %s = file_out (argv[%d]);\n" name i;
7933 pr " if (%s == NULL) return -1;\n" name
7934 | StringList name | DeviceList name ->
7935 pr " %s = parse_string_list (argv[%d]);\n" name i;
7936 pr " if (%s == NULL) return -1;\n" name;
7938 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7941 let min = "(-(2LL<<30))"
7942 and max = "((2LL<<30)-1)"
7944 "The Int type in the generator is a signed 31 bit int." in
7945 Some (min, max, comment) in
7946 parse_integer "xstrtoll" "long long" "int" range name i
7948 parse_integer "xstrtoll" "long long" "int64_t" None name i
7951 (* Call C API function. *)
7952 pr " r = guestfs_%s " name;
7953 generate_c_call_args ~handle:"g" style;
7958 | Device _ | String _
7959 | OptString _ | Bool _
7962 | Pathname name | Dev_or_Path name | FileOut name ->
7963 pr " free (%s);\n" name
7965 pr " free_file_in (%s);\n" name
7966 | StringList name | DeviceList name ->
7967 pr " free_strings (%s);\n" name
7970 (* Any output flags? *)
7972 let flags = filter_map (
7973 function FishOutput flag -> Some flag | _ -> None
7979 failwithf "%s: more than one FishOutput flag is not allowed" name in
7981 (* Check return value for errors and display command results. *)
7982 (match fst style with
7983 | RErr -> pr " return r;\n"
7985 pr " if (r == -1) return -1;\n";
7986 (match fish_output with
7988 pr " printf (\"%%d\\n\", r);\n";
7989 | Some FishOutputOctal ->
7990 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7991 | Some FishOutputHexadecimal ->
7992 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7995 pr " if (r == -1) return -1;\n";
7996 (match fish_output with
7998 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7999 | Some FishOutputOctal ->
8000 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8001 | Some FishOutputHexadecimal ->
8002 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8005 pr " if (r == -1) return -1;\n";
8006 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8009 pr " if (r == NULL) return -1;\n";
8010 pr " printf (\"%%s\\n\", r);\n";
8012 | RConstOptString _ ->
8013 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
8016 pr " if (r == NULL) return -1;\n";
8017 pr " printf (\"%%s\\n\", r);\n";
8021 pr " if (r == NULL) return -1;\n";
8022 pr " print_strings (r);\n";
8023 pr " free_strings (r);\n";
8025 | RStruct (_, typ) ->
8026 pr " if (r == NULL) return -1;\n";
8027 pr " print_%s (r);\n" typ;
8028 pr " guestfs_free_%s (r);\n" typ;
8030 | RStructList (_, typ) ->
8031 pr " if (r == NULL) return -1;\n";
8032 pr " print_%s_list (r);\n" typ;
8033 pr " guestfs_free_%s_list (r);\n" typ;
8036 pr " if (r == NULL) return -1;\n";
8037 pr " print_table (r);\n";
8038 pr " free_strings (r);\n";
8041 pr " if (r == NULL) return -1;\n";
8042 pr " if (full_write (1, r, size) != size) {\n";
8043 pr " perror (\"write\");\n";
8054 (* run_action function *)
8055 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8058 fun (name, _, _, flags, _, _, _) ->
8059 let name2 = replace_char name '_' '-' in
8061 try find_map (function FishAlias n -> Some n | _ -> None) flags
8062 with Not_found -> name in
8064 pr "STRCASEEQ (cmd, \"%s\")" name;
8065 if name <> name2 then
8066 pr " || STRCASEEQ (cmd, \"%s\")" name2;
8067 if name <> alias then
8068 pr " || STRCASEEQ (cmd, \"%s\")" alias;
8070 pr " return run_%s (cmd, argc, argv);\n" name;
8074 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8075 pr " if (command_num == 1)\n";
8076 pr " extended_help_message ();\n";
8083 (* Readline completion for guestfish. *)
8084 and generate_fish_completion () =
8085 generate_header CStyle GPLv2plus;
8089 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8099 #ifdef HAVE_LIBREADLINE
8100 #include <readline/readline.h>
8105 #ifdef HAVE_LIBREADLINE
8107 static const char *const commands[] = {
8108 BUILTIN_COMMANDS_FOR_COMPLETION,
8111 (* Get the commands, including the aliases. They don't need to be
8112 * sorted - the generator() function just does a dumb linear search.
8116 fun (name, _, _, flags, _, _, _) ->
8117 let name2 = replace_char name '_' '-' in
8119 try find_map (function FishAlias n -> Some n | _ -> None) flags
8120 with Not_found -> name in
8122 if name <> alias then [name2; alias] else [name2]
8124 let commands = List.flatten commands in
8126 List.iter (pr " \"%s\",\n") commands;
8132 generator (const char *text, int state)
8134 static size_t index, len;
8139 len = strlen (text);
8142 rl_attempted_completion_over = 1;
8144 while ((name = commands[index]) != NULL) {
8146 if (STRCASEEQLEN (name, text, len))
8147 return strdup (name);
8153 #endif /* HAVE_LIBREADLINE */
8155 #ifdef HAVE_RL_COMPLETION_MATCHES
8156 #define RL_COMPLETION_MATCHES rl_completion_matches
8158 #ifdef HAVE_COMPLETION_MATCHES
8159 #define RL_COMPLETION_MATCHES completion_matches
8161 #endif /* else just fail if we don't have either symbol */
8164 do_completion (const char *text, int start, int end)
8166 char **matches = NULL;
8168 #ifdef HAVE_LIBREADLINE
8169 rl_completion_append_character = ' ';
8172 matches = RL_COMPLETION_MATCHES (text, generator);
8173 else if (complete_dest_paths)
8174 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8181 (* Generate the POD documentation for guestfish. *)
8182 and generate_fish_actions_pod () =
8183 let all_functions_sorted =
8185 fun (_, _, _, flags, _, _, _) ->
8186 not (List.mem NotInFish flags || List.mem NotInDocs flags)
8187 ) all_functions_sorted in
8189 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8192 fun (name, style, _, flags, _, _, longdesc) ->
8194 Str.global_substitute rex (
8197 try Str.matched_group 1 s
8199 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8200 "C<" ^ replace_char sub '_' '-' ^ ">"
8202 let name = replace_char name '_' '-' in
8204 try find_map (function FishAlias n -> Some n | _ -> None) flags
8205 with Not_found -> name in
8207 pr "=head2 %s" name;
8208 if name <> alias then
8215 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8216 | OptString n -> pr " %s" n
8217 | StringList n | DeviceList n -> pr " '%s ...'" n
8218 | Bool _ -> pr " true|false"
8219 | Int n -> pr " %s" n
8220 | Int64 n -> pr " %s" n
8221 | FileIn n | FileOut n -> pr " (%s|-)" n
8222 | BufferIn n -> pr " %s" n
8226 pr "%s\n\n" longdesc;
8228 if List.exists (function FileIn _ | FileOut _ -> true
8229 | _ -> false) (snd style) then
8230 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8232 if List.mem ProtocolLimitWarning flags then
8233 pr "%s\n\n" protocol_limit_warning;
8235 if List.mem DangerWillRobinson flags then
8236 pr "%s\n\n" danger_will_robinson;
8238 match deprecation_notice flags with
8240 | Some txt -> pr "%s\n\n" txt
8241 ) all_functions_sorted
8243 and generate_fish_prep_options_h () =
8244 generate_header CStyle GPLv2plus;
8246 pr "#ifndef PREPOPTS_H\n";
8251 const char *name; /* eg. \"fs\" */
8253 size_t nr_params; /* optional parameters */
8254 struct prep_param *params;
8256 const char *shortdesc; /* short description */
8257 const char *longdesc; /* long description */
8259 /* functions to implement it */
8260 void (*prelaunch) (const char *filename, prep_data *);
8261 void (*postlaunch) (const char *filename, prep_data *, const char *device);
8265 const char *pname; /* parameter name */
8266 const char *pdefault; /* parameter default */
8267 const char *pdesc; /* parameter description */
8270 extern const struct prep preps[];
8273 " (List.length prepopts);
8276 fun (name, shortdesc, args, longdesc) ->
8278 extern void prep_prelaunch_%s (const char *filename, prep_data *data);
8279 extern void prep_postlaunch_%s (const char *filename, prep_data *data, const char *device);
8285 pr "#endif /* PREPOPTS_H */\n"
8287 and generate_fish_prep_options_c () =
8288 generate_header CStyle GPLv2plus;
8292 #include \"prepopts.h\"
8297 fun (name, shortdesc, args, longdesc) ->
8298 pr "static struct prep_param %s_args[] = {\n" name;
8300 fun (n, default, desc) ->
8301 pr " { \"%s\", \"%s\", \"%s\" },\n" n default desc
8307 pr "const struct prep preps[] = {\n";
8309 fun (name, shortdesc, args, longdesc) ->
8310 pr " { \"%s\", %d, %s_args,
8313 prep_prelaunch_%s, prep_postlaunch_%s },
8315 name (List.length args) name
8316 (c_quote shortdesc) (c_quote longdesc)
8321 (* Generate a C function prototype. *)
8322 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8323 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8325 ?handle name style =
8326 if extern then pr "extern ";
8327 if static then pr "static ";
8328 (match fst style with
8330 | RInt _ -> pr "int "
8331 | RInt64 _ -> pr "int64_t "
8332 | RBool _ -> pr "int "
8333 | RConstString _ | RConstOptString _ -> pr "const char *"
8334 | RString _ | RBufferOut _ -> pr "char *"
8335 | RStringList _ | RHashtable _ -> pr "char **"
8336 | RStruct (_, typ) ->
8337 if not in_daemon then pr "struct guestfs_%s *" typ
8338 else pr "guestfs_int_%s *" typ
8339 | RStructList (_, typ) ->
8340 if not in_daemon then pr "struct guestfs_%s_list *" typ
8341 else pr "guestfs_int_%s_list *" typ
8343 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8344 pr "%s%s (" prefix name;
8345 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8348 let comma = ref false in
8351 | Some handle -> pr "guestfs_h *%s" handle; comma := true
8355 if single_line then pr ", " else pr ",\n\t\t"
8362 | Device n | Dev_or_Path n
8366 pr "const char *%s" n
8367 | StringList n | DeviceList n ->
8369 pr "char *const *%s" n
8370 | Bool n -> next (); pr "int %s" n
8371 | Int n -> next (); pr "int %s" n
8372 | Int64 n -> next (); pr "int64_t %s" n
8375 if not in_daemon then (next (); pr "const char *%s" n)
8378 pr "const char *%s" n;
8380 pr "size_t %s_size" n
8382 if is_RBufferOut then (next (); pr "size_t *size_r");
8385 if semicolon then pr ";";
8386 if newline then pr "\n"
8388 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8389 and generate_c_call_args ?handle ?(decl = false) style =
8391 let comma = ref false in
8393 if !comma then pr ", ";
8398 | Some handle -> pr "%s" handle; comma := true
8404 pr "%s, %s_size" n n
8407 pr "%s" (name_of_argt arg)
8409 (* For RBufferOut calls, add implicit &size parameter. *)
8411 match fst style with
8419 (* Generate the OCaml bindings interface. *)
8420 and generate_ocaml_mli () =
8421 generate_header OCamlStyle LGPLv2plus;
8424 (** For API documentation you should refer to the C API
8425 in the guestfs(3) manual page. The OCaml API uses almost
8426 exactly the same calls. *)
8429 (** A [guestfs_h] handle. *)
8431 exception Error of string
8432 (** This exception is raised when there is an error. *)
8434 exception Handle_closed of string
8435 (** This exception is raised if you use a {!Guestfs.t} handle
8436 after calling {!close} on it. The string is the name of
8439 val create : unit -> t
8440 (** Create a {!Guestfs.t} handle. *)
8442 val close : t -> unit
8443 (** Close the {!Guestfs.t} handle and free up all resources used
8446 Handles are closed by the garbage collector when they become
8447 unreferenced, but callers can call this in order to provide
8448 predictable cleanup. *)
8451 generate_ocaml_structure_decls ();
8455 fun (name, style, _, _, _, shortdesc, _) ->
8456 generate_ocaml_prototype name style;
8457 pr "(** %s *)\n" shortdesc;
8459 ) all_functions_sorted
8461 (* Generate the OCaml bindings implementation. *)
8462 and generate_ocaml_ml () =
8463 generate_header OCamlStyle LGPLv2plus;
8468 exception Error of string
8469 exception Handle_closed of string
8471 external create : unit -> t = \"ocaml_guestfs_create\"
8472 external close : t -> unit = \"ocaml_guestfs_close\"
8474 (* Give the exceptions names, so they can be raised from the C code. *)
8476 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8477 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8481 generate_ocaml_structure_decls ();
8485 fun (name, style, _, _, _, shortdesc, _) ->
8486 generate_ocaml_prototype ~is_external:true name style;
8487 ) all_functions_sorted
8489 (* Generate the OCaml bindings C implementation. *)
8490 and generate_ocaml_c () =
8491 generate_header CStyle LGPLv2plus;
8498 #include <caml/config.h>
8499 #include <caml/alloc.h>
8500 #include <caml/callback.h>
8501 #include <caml/fail.h>
8502 #include <caml/memory.h>
8503 #include <caml/mlvalues.h>
8504 #include <caml/signals.h>
8506 #include \"guestfs.h\"
8508 #include \"guestfs_c.h\"
8510 /* Copy a hashtable of string pairs into an assoc-list. We return
8511 * the list in reverse order, but hashtables aren't supposed to be
8514 static CAMLprim value
8515 copy_table (char * const * argv)
8518 CAMLlocal5 (rv, pairv, kv, vv, cons);
8522 for (i = 0; argv[i] != NULL; i += 2) {
8523 kv = caml_copy_string (argv[i]);
8524 vv = caml_copy_string (argv[i+1]);
8525 pairv = caml_alloc (2, 0);
8526 Store_field (pairv, 0, kv);
8527 Store_field (pairv, 1, vv);
8528 cons = caml_alloc (2, 0);
8529 Store_field (cons, 1, rv);
8531 Store_field (cons, 0, pairv);
8539 (* Struct copy functions. *)
8541 let emit_ocaml_copy_list_function typ =
8542 pr "static CAMLprim value\n";
8543 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8545 pr " CAMLparam0 ();\n";
8546 pr " CAMLlocal2 (rv, v);\n";
8547 pr " unsigned int i;\n";
8549 pr " if (%ss->len == 0)\n" typ;
8550 pr " CAMLreturn (Atom (0));\n";
8552 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8553 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8554 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8555 pr " caml_modify (&Field (rv, i), v);\n";
8557 pr " CAMLreturn (rv);\n";
8565 let has_optpercent_col =
8566 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8568 pr "static CAMLprim value\n";
8569 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8571 pr " CAMLparam0 ();\n";
8572 if has_optpercent_col then
8573 pr " CAMLlocal3 (rv, v, v2);\n"
8575 pr " CAMLlocal2 (rv, v);\n";
8577 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8582 pr " v = caml_copy_string (%s->%s);\n" typ name
8584 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8585 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8588 pr " v = caml_alloc_string (32);\n";
8589 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8590 | name, (FBytes|FInt64|FUInt64) ->
8591 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8592 | name, (FInt32|FUInt32) ->
8593 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8594 | name, FOptPercent ->
8595 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8596 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8597 pr " v = caml_alloc (1, 0);\n";
8598 pr " Store_field (v, 0, v2);\n";
8599 pr " } else /* None */\n";
8600 pr " v = Val_int (0);\n";
8602 pr " v = Val_int (%s->%s);\n" typ name
8604 pr " Store_field (rv, %d, v);\n" i
8606 pr " CAMLreturn (rv);\n";
8611 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8614 | typ, (RStructListOnly | RStructAndList) ->
8615 (* generate the function for typ *)
8616 emit_ocaml_copy_list_function typ
8617 | typ, _ -> () (* empty *)
8618 ) (rstructs_used_by all_functions);
8622 fun (name, style, _, _, _, _, _) ->
8623 pr "/* Automatically generated wrapper for function\n";
8625 generate_ocaml_prototype name style;
8630 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8632 let needs_extra_vs =
8633 match fst style with RConstOptString _ -> true | _ -> false in
8635 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8636 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8637 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8640 pr "CAMLprim value\n";
8641 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8642 List.iter (pr ", value %s") (List.tl params);
8647 | [p1; p2; p3; p4; p5] ->
8648 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8649 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8650 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8651 pr " CAMLxparam%d (%s);\n"
8652 (List.length rest) (String.concat ", " rest)
8654 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8656 if not needs_extra_vs then
8657 pr " CAMLlocal1 (rv);\n"
8659 pr " CAMLlocal3 (rv, v, v2);\n";
8662 pr " guestfs_h *g = Guestfs_val (gv);\n";
8663 pr " if (g == NULL)\n";
8664 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8670 | Device n | Dev_or_Path n
8674 (* Copy strings in case the GC moves them: RHBZ#604691 *)
8675 pr " char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8677 pr " char *%s =\n" n;
8678 pr " %sv != Val_int (0) ?" n;
8679 pr " guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8681 pr " size_t %s_size = caml_string_length (%sv);\n" n n;
8682 pr " char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8683 | StringList n | DeviceList n ->
8684 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8686 pr " int %s = Bool_val (%sv);\n" n n
8688 pr " int %s = Int_val (%sv);\n" n n
8690 pr " int64_t %s = Int64_val (%sv);\n" n n
8693 match fst style with
8694 | RErr -> pr " int r;\n"; "-1"
8695 | RInt _ -> pr " int r;\n"; "-1"
8696 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8697 | RBool _ -> pr " int r;\n"; "-1"
8698 | RConstString _ | RConstOptString _ ->
8699 pr " const char *r;\n"; "NULL"
8700 | RString _ -> pr " char *r;\n"; "NULL"
8705 | RStruct (_, typ) ->
8706 pr " struct guestfs_%s *r;\n" typ; "NULL"
8707 | RStructList (_, typ) ->
8708 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8715 pr " size_t size;\n";
8719 pr " caml_enter_blocking_section ();\n";
8720 pr " r = guestfs_%s " name;
8721 generate_c_call_args ~handle:"g" style;
8723 pr " caml_leave_blocking_section ();\n";
8725 (* Free strings if we copied them above. *)
8728 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8729 | FileIn n | FileOut n | BufferIn n ->
8730 pr " free (%s);\n" n
8731 | StringList n | DeviceList n ->
8732 pr " ocaml_guestfs_free_strings (%s);\n" n;
8733 | Bool _ | Int _ | Int64 _ -> ()
8736 pr " if (r == %s)\n" error_code;
8737 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8740 (match fst style with
8741 | RErr -> pr " rv = Val_unit;\n"
8742 | RInt _ -> pr " rv = Val_int (r);\n"
8744 pr " rv = caml_copy_int64 (r);\n"
8745 | RBool _ -> pr " rv = Val_bool (r);\n"
8747 pr " rv = caml_copy_string (r);\n"
8748 | RConstOptString _ ->
8749 pr " if (r) { /* Some string */\n";
8750 pr " v = caml_alloc (1, 0);\n";
8751 pr " v2 = caml_copy_string (r);\n";
8752 pr " Store_field (v, 0, v2);\n";
8753 pr " } else /* None */\n";
8754 pr " v = Val_int (0);\n";
8756 pr " rv = caml_copy_string (r);\n";
8759 pr " rv = caml_copy_string_array ((const char **) r);\n";
8760 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8762 | RStruct (_, typ) ->
8763 pr " rv = copy_%s (r);\n" typ;
8764 pr " guestfs_free_%s (r);\n" typ;
8765 | RStructList (_, typ) ->
8766 pr " rv = copy_%s_list (r);\n" typ;
8767 pr " guestfs_free_%s_list (r);\n" typ;
8769 pr " rv = copy_table (r);\n";
8770 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8773 pr " rv = caml_alloc_string (size);\n";
8774 pr " memcpy (String_val (rv), r, size);\n";
8777 pr " CAMLreturn (rv);\n";
8781 if List.length params > 5 then (
8782 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8783 pr "CAMLprim value ";
8784 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8785 pr "CAMLprim value\n";
8786 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8788 pr " return ocaml_guestfs_%s (argv[0]" name;
8789 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8794 ) all_functions_sorted
8796 and generate_ocaml_structure_decls () =
8799 pr "type %s = {\n" typ;
8802 | name, FString -> pr " %s : string;\n" name
8803 | name, FBuffer -> pr " %s : string;\n" name
8804 | name, FUUID -> pr " %s : string;\n" name
8805 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8806 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8807 | name, FChar -> pr " %s : char;\n" name
8808 | name, FOptPercent -> pr " %s : float option;\n" name
8814 and generate_ocaml_prototype ?(is_external = false) name style =
8815 if is_external then pr "external " else pr "val ";
8816 pr "%s : t -> " name;
8819 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8820 | BufferIn _ -> pr "string -> "
8821 | OptString _ -> pr "string option -> "
8822 | StringList _ | DeviceList _ -> pr "string array -> "
8823 | Bool _ -> pr "bool -> "
8824 | Int _ -> pr "int -> "
8825 | Int64 _ -> pr "int64 -> "
8827 (match fst style with
8828 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8829 | RInt _ -> pr "int"
8830 | RInt64 _ -> pr "int64"
8831 | RBool _ -> pr "bool"
8832 | RConstString _ -> pr "string"
8833 | RConstOptString _ -> pr "string option"
8834 | RString _ | RBufferOut _ -> pr "string"
8835 | RStringList _ -> pr "string array"
8836 | RStruct (_, typ) -> pr "%s" typ
8837 | RStructList (_, typ) -> pr "%s array" typ
8838 | RHashtable _ -> pr "(string * string) list"
8840 if is_external then (
8842 if List.length (snd style) + 1 > 5 then
8843 pr "\"ocaml_guestfs_%s_byte\" " name;
8844 pr "\"ocaml_guestfs_%s\"" name
8848 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8849 and generate_perl_xs () =
8850 generate_header CStyle LGPLv2plus;
8853 #include \"EXTERN.h\"
8857 #include <guestfs.h>
8860 #define PRId64 \"lld\"
8864 my_newSVll(long long val) {
8865 #ifdef USE_64_BIT_ALL
8866 return newSViv(val);
8870 len = snprintf(buf, 100, \"%%\" PRId64, val);
8871 return newSVpv(buf, len);
8876 #define PRIu64 \"llu\"
8880 my_newSVull(unsigned long long val) {
8881 #ifdef USE_64_BIT_ALL
8882 return newSVuv(val);
8886 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8887 return newSVpv(buf, len);
8891 /* http://www.perlmonks.org/?node_id=680842 */
8893 XS_unpack_charPtrPtr (SV *arg) {
8898 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8899 croak (\"array reference expected\");
8901 av = (AV *)SvRV (arg);
8902 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8904 croak (\"malloc failed\");
8906 for (i = 0; i <= av_len (av); i++) {
8907 SV **elem = av_fetch (av, i, 0);
8909 if (!elem || !*elem)
8910 croak (\"missing element in list\");
8912 ret[i] = SvPV_nolen (*elem);
8920 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8927 RETVAL = guestfs_create ();
8929 croak (\"could not create guestfs handle\");
8930 guestfs_set_error_handler (RETVAL, NULL, NULL);
8938 /* For the 'g' argument above we do the conversion explicitly and
8939 * don't rely on the typemap, because if the handle has been
8940 * explicitly closed we don't want the typemap conversion to
8943 HV *hv = (HV *) SvRV (sv);
8944 SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8946 guestfs_h *g = (guestfs_h *) SvIV (*svp);
8956 /* Avoid double-free in DESTROY method. */
8957 HV *hv = (HV *) SvRV (ST(0));
8958 (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8963 fun (name, style, _, _, _, _, _) ->
8964 (match fst style with
8965 | RErr -> pr "void\n"
8966 | RInt _ -> pr "SV *\n"
8967 | RInt64 _ -> pr "SV *\n"
8968 | RBool _ -> pr "SV *\n"
8969 | RConstString _ -> pr "SV *\n"
8970 | RConstOptString _ -> pr "SV *\n"
8971 | RString _ -> pr "SV *\n"
8972 | RBufferOut _ -> pr "SV *\n"
8974 | RStruct _ | RStructList _
8976 pr "void\n" (* all lists returned implictly on the stack *)
8978 (* Call and arguments. *)
8981 fun arg -> pr ", %s" (name_of_argt arg)
8984 pr " guestfs_h *g;\n";
8988 | Pathname n | Device n | Dev_or_Path n | String n
8989 | FileIn n | FileOut n ->
8992 pr " char *%s;\n" n;
8993 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8995 (* http://www.perlmonks.org/?node_id=554277
8996 * Note that the implicit handle argument means we have
8997 * to add 1 to the ST(x) operator.
8999 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9000 | StringList n | DeviceList n -> pr " char **%s;\n" n
9001 | Bool n -> pr " int %s;\n" n
9002 | Int n -> pr " int %s;\n" n
9003 | Int64 n -> pr " int64_t %s;\n" n
9006 let do_cleanups () =
9009 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9010 | Bool _ | Int _ | Int64 _
9011 | FileIn _ | FileOut _
9013 | StringList n | DeviceList n -> pr " free (%s);\n" n
9018 (match fst style with
9023 pr " r = guestfs_%s " name;
9024 generate_c_call_args ~handle:"g" style;
9027 pr " if (r == -1)\n";
9028 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9034 pr " %s = guestfs_%s " n name;
9035 generate_c_call_args ~handle:"g" style;
9038 pr " if (%s == -1)\n" n;
9039 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9040 pr " RETVAL = newSViv (%s);\n" n;
9045 pr " int64_t %s;\n" n;
9047 pr " %s = guestfs_%s " n name;
9048 generate_c_call_args ~handle:"g" style;
9051 pr " if (%s == -1)\n" n;
9052 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9053 pr " RETVAL = my_newSVll (%s);\n" n;
9058 pr " const char *%s;\n" n;
9060 pr " %s = guestfs_%s " n name;
9061 generate_c_call_args ~handle:"g" style;
9064 pr " if (%s == NULL)\n" n;
9065 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9066 pr " RETVAL = newSVpv (%s, 0);\n" n;
9069 | RConstOptString n ->
9071 pr " const char *%s;\n" n;
9073 pr " %s = guestfs_%s " n name;
9074 generate_c_call_args ~handle:"g" style;
9077 pr " if (%s == NULL)\n" n;
9078 pr " RETVAL = &PL_sv_undef;\n";
9080 pr " RETVAL = newSVpv (%s, 0);\n" n;
9085 pr " char *%s;\n" n;
9087 pr " %s = guestfs_%s " n name;
9088 generate_c_call_args ~handle:"g" style;
9091 pr " if (%s == NULL)\n" n;
9092 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9093 pr " RETVAL = newSVpv (%s, 0);\n" n;
9094 pr " free (%s);\n" n;
9097 | RStringList n | RHashtable n ->
9099 pr " char **%s;\n" n;
9100 pr " size_t i, n;\n";
9102 pr " %s = guestfs_%s " n name;
9103 generate_c_call_args ~handle:"g" style;
9106 pr " if (%s == NULL)\n" n;
9107 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9108 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9109 pr " EXTEND (SP, n);\n";
9110 pr " for (i = 0; i < n; ++i) {\n";
9111 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9112 pr " free (%s[i]);\n" n;
9114 pr " free (%s);\n" n;
9115 | RStruct (n, typ) ->
9116 let cols = cols_of_struct typ in
9117 generate_perl_struct_code typ cols name style n do_cleanups
9118 | RStructList (n, typ) ->
9119 let cols = cols_of_struct typ in
9120 generate_perl_struct_list_code typ cols name style n do_cleanups
9123 pr " char *%s;\n" n;
9124 pr " size_t size;\n";
9126 pr " %s = guestfs_%s " n name;
9127 generate_c_call_args ~handle:"g" style;
9130 pr " if (%s == NULL)\n" n;
9131 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9132 pr " RETVAL = newSVpvn (%s, size);\n" n;
9133 pr " free (%s);\n" n;
9141 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9143 pr " struct guestfs_%s_list *%s;\n" typ n;
9147 pr " %s = guestfs_%s " n name;
9148 generate_c_call_args ~handle:"g" style;
9151 pr " if (%s == NULL)\n" n;
9152 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9153 pr " EXTEND (SP, %s->len);\n" n;
9154 pr " for (i = 0; i < %s->len; ++i) {\n" n;
9155 pr " hv = newHV ();\n";
9159 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9160 name (String.length name) n name
9162 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9163 name (String.length name) n name
9165 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9166 name (String.length name) n name n name
9167 | name, (FBytes|FUInt64) ->
9168 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9169 name (String.length name) n name
9171 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9172 name (String.length name) n name
9173 | name, (FInt32|FUInt32) ->
9174 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9175 name (String.length name) n name
9177 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9178 name (String.length name) n name
9179 | name, FOptPercent ->
9180 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9181 name (String.length name) n name
9183 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9185 pr " guestfs_free_%s_list (%s);\n" typ n
9187 and generate_perl_struct_code typ cols name style n do_cleanups =
9189 pr " struct guestfs_%s *%s;\n" typ n;
9191 pr " %s = guestfs_%s " n name;
9192 generate_c_call_args ~handle:"g" style;
9195 pr " if (%s == NULL)\n" n;
9196 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9197 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
9199 fun ((name, _) as col) ->
9200 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9204 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9207 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9210 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9212 | name, (FBytes|FUInt64) ->
9213 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9216 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9218 | name, (FInt32|FUInt32) ->
9219 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9222 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9224 | name, FOptPercent ->
9225 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9228 pr " free (%s);\n" n
9230 (* Generate Sys/Guestfs.pm. *)
9231 and generate_perl_pm () =
9232 generate_header HashStyle LGPLv2plus;
9239 Sys::Guestfs - Perl bindings for libguestfs
9245 my $h = Sys::Guestfs->new ();
9246 $h->add_drive ('guest.img');
9248 $h->mount ('/dev/sda1', '/');
9249 $h->touch ('/hello');
9254 The C<Sys::Guestfs> module provides a Perl XS binding to the
9255 libguestfs API for examining and modifying virtual machine
9258 Amongst the things this is good for: making batch configuration
9259 changes to guests, getting disk used/free statistics (see also:
9260 virt-df), migrating between virtualization systems (see also:
9261 virt-p2v), performing partial backups, performing partial guest
9262 clones, cloning guests and changing registry/UUID/hostname info, and
9265 Libguestfs uses Linux kernel and qemu code, and can access any type of
9266 guest filesystem that Linux and qemu can, including but not limited
9267 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9268 schemes, qcow, qcow2, vmdk.
9270 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9271 LVs, what filesystem is in each LV, etc.). It can also run commands
9272 in the context of the guest. Also you can access filesystems over
9275 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9276 functions for using libguestfs from Perl, including integration
9281 All errors turn into calls to C<croak> (see L<Carp(3)>).
9289 package Sys::Guestfs;
9294 # This version number changes whenever a new function
9295 # is added to the libguestfs API. It is not directly
9296 # related to the libguestfs version number.
9297 use vars qw($VERSION);
9301 XSLoader::load ('Sys::Guestfs');
9303 =item $h = Sys::Guestfs->new ();
9305 Create a new guestfs handle.
9311 my $class = ref ($proto) || $proto;
9313 my $g = Sys::Guestfs::_create ();
9314 my $self = { _g => $g };
9315 bless $self, $class;
9321 Explicitly close the guestfs handle.
9323 B<Note:> You should not usually call this function. The handle will
9324 be closed implicitly when its reference count goes to zero (eg.
9325 when it goes out of scope or the program ends). This call is
9326 only required in some exceptional cases, such as where the program
9327 may contain cached references to the handle 'somewhere' and you
9328 really have to have the close happen right away. After calling
9329 C<close> the program must not call any method (including C<close>)
9330 on the handle (but the implicit call to C<DESTROY> that happens
9331 when the final reference is cleaned up is OK).
9337 (* Actions. We only need to print documentation for these as
9338 * they are pulled in from the XS code automatically.
9341 fun (name, style, _, flags, _, _, longdesc) ->
9342 if not (List.mem NotInDocs flags) then (
9343 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9345 generate_perl_prototype name style;
9347 pr "%s\n\n" longdesc;
9348 if List.mem ProtocolLimitWarning flags then
9349 pr "%s\n\n" protocol_limit_warning;
9350 if List.mem DangerWillRobinson flags then
9351 pr "%s\n\n" danger_will_robinson;
9352 match deprecation_notice flags with
9354 | Some txt -> pr "%s\n\n" txt
9356 ) all_functions_sorted;
9368 From time to time we add new libguestfs APIs. Also some libguestfs
9369 APIs won't be available in all builds of libguestfs (the Fedora
9370 build is full-featured, but other builds may disable features).
9371 How do you test whether the APIs that your Perl program needs are
9372 available in the version of C<Sys::Guestfs> that you are using?
9374 To test if a particular function is available in the C<Sys::Guestfs>
9375 class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
9376 (see L<perlobj(1)>). For example:
9379 if (defined (Sys::Guestfs->can (\"set_verbose\"))) {
9380 print \"\\$h->set_verbose is available\\n\";
9383 To test if particular features are supported by the current
9384 build, use the L</available> method like the example below. Note
9385 that the appliance must be launched first.
9387 $h->available ( [\"augeas\"] );
9389 Since the L</available> method croaks if the feature is not supported,
9390 you might also want to wrap this in an eval and return a boolean.
9391 In fact this has already been done for you: use
9392 L<Sys::Guestfs::Lib(3)/feature_available>.
9394 For further discussion on this topic, refer to
9395 L<guestfs(3)/AVAILABILITY>.
9397 =head1 STORING DATA IN THE HANDLE
9399 The handle returned from L</new> is a hash reference. The hash
9400 normally contains a single element:
9403 _g => [private data used by libguestfs]
9406 Callers can add other elements to this hash to store data for their own
9407 purposes. The data lasts for the lifetime of the handle.
9409 Any fields whose names begin with an underscore are reserved
9410 for private use by libguestfs. We may add more in future.
9412 It is recommended that callers prefix the name of their field(s)
9413 with some unique string, to avoid conflicts with other users.
9417 Copyright (C) %s Red Hat Inc.
9421 Please see the file COPYING.LIB for the full license.
9427 L<http://libguestfs.org>,
9428 L<Sys::Guestfs::Lib(3)>.
9433 and generate_perl_prototype name style =
9434 (match fst style with
9442 | RBufferOut n -> pr "$%s = " n
9444 | RHashtable n -> pr "%%%s = " n
9446 | RStructList (n,_) -> pr "@%s = " n
9449 let comma = ref false in
9452 if !comma then pr ", ";
9455 | Pathname n | Device n | Dev_or_Path n | String n
9456 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9459 | StringList n | DeviceList n ->
9464 (* Generate Python C module. *)
9465 and generate_python_c () =
9466 generate_header CStyle LGPLv2plus;
9469 #define PY_SSIZE_T_CLEAN 1
9472 #if PY_VERSION_HEX < 0x02050000
9473 typedef int Py_ssize_t;
9474 #define PY_SSIZE_T_MAX INT_MAX
9475 #define PY_SSIZE_T_MIN INT_MIN
9482 #include \"guestfs.h\"
9490 get_handle (PyObject *obj)
9493 assert (obj != Py_None);
9494 return ((Pyguestfs_Object *) obj)->g;
9498 put_handle (guestfs_h *g)
9502 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9505 /* This list should be freed (but not the strings) after use. */
9507 get_string_list (PyObject *obj)
9514 if (!PyList_Check (obj)) {
9515 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9519 Py_ssize_t slen = PyList_Size (obj);
9521 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9524 len = (size_t) slen;
9525 r = malloc (sizeof (char *) * (len+1));
9527 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9531 for (i = 0; i < len; ++i)
9532 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9539 put_string_list (char * const * const argv)
9544 for (argc = 0; argv[argc] != NULL; ++argc)
9547 list = PyList_New (argc);
9548 for (i = 0; i < argc; ++i)
9549 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9555 put_table (char * const * const argv)
9557 PyObject *list, *item;
9560 for (argc = 0; argv[argc] != NULL; ++argc)
9563 list = PyList_New (argc >> 1);
9564 for (i = 0; i < argc; i += 2) {
9565 item = PyTuple_New (2);
9566 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9567 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9568 PyList_SetItem (list, i >> 1, item);
9575 free_strings (char **argv)
9579 for (argc = 0; argv[argc] != NULL; ++argc)
9585 py_guestfs_create (PyObject *self, PyObject *args)
9589 g = guestfs_create ();
9591 PyErr_SetString (PyExc_RuntimeError,
9592 \"guestfs.create: failed to allocate handle\");
9595 guestfs_set_error_handler (g, NULL, NULL);
9596 return put_handle (g);
9600 py_guestfs_close (PyObject *self, PyObject *args)
9605 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9607 g = get_handle (py_g);
9611 Py_INCREF (Py_None);
9617 let emit_put_list_function typ =
9618 pr "static PyObject *\n";
9619 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9621 pr " PyObject *list;\n";
9624 pr " list = PyList_New (%ss->len);\n" typ;
9625 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9626 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9627 pr " return list;\n";
9632 (* Structures, turned into Python dictionaries. *)
9635 pr "static PyObject *\n";
9636 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9638 pr " PyObject *dict;\n";
9640 pr " dict = PyDict_New ();\n";
9644 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9645 pr " PyString_FromString (%s->%s));\n"
9648 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9649 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9652 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9653 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9655 | name, (FBytes|FUInt64) ->
9656 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9657 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9660 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9661 pr " PyLong_FromLongLong (%s->%s));\n"
9664 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9665 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9668 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9669 pr " PyLong_FromLong (%s->%s));\n"
9671 | name, FOptPercent ->
9672 pr " if (%s->%s >= 0)\n" typ name;
9673 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9674 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9677 pr " Py_INCREF (Py_None);\n";
9678 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9681 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9682 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9684 pr " return dict;\n";
9690 (* Emit a put_TYPE_list function definition only if that function is used. *)
9693 | typ, (RStructListOnly | RStructAndList) ->
9694 (* generate the function for typ *)
9695 emit_put_list_function typ
9696 | typ, _ -> () (* empty *)
9697 ) (rstructs_used_by all_functions);
9699 (* Python wrapper functions. *)
9701 fun (name, style, _, _, _, _, _) ->
9702 pr "static PyObject *\n";
9703 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9706 pr " PyObject *py_g;\n";
9707 pr " guestfs_h *g;\n";
9708 pr " PyObject *py_r;\n";
9711 match fst style with
9712 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9713 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9714 | RConstString _ | RConstOptString _ ->
9715 pr " const char *r;\n"; "NULL"
9716 | RString _ -> pr " char *r;\n"; "NULL"
9717 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9718 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9719 | RStructList (_, typ) ->
9720 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9723 pr " size_t size;\n";
9728 | Pathname n | Device n | Dev_or_Path n | String n
9729 | FileIn n | FileOut n ->
9730 pr " const char *%s;\n" n
9731 | OptString n -> pr " const char *%s;\n" n
9733 pr " const char *%s;\n" n;
9734 pr " Py_ssize_t %s_size;\n" n
9735 | StringList n | DeviceList n ->
9736 pr " PyObject *py_%s;\n" n;
9737 pr " char **%s;\n" n
9738 | Bool n -> pr " int %s;\n" n
9739 | Int n -> pr " int %s;\n" n
9740 | Int64 n -> pr " long long %s;\n" n
9745 (* Convert the parameters. *)
9746 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9749 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9750 | OptString _ -> pr "z"
9751 | StringList _ | DeviceList _ -> pr "O"
9752 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9754 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9755 * emulate C's int/long/long long in Python?
9757 | BufferIn _ -> pr "s#"
9759 pr ":guestfs_%s\",\n" name;
9763 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9764 | OptString n -> pr ", &%s" n
9765 | StringList n | DeviceList n -> pr ", &py_%s" n
9766 | Bool n -> pr ", &%s" n
9767 | Int n -> pr ", &%s" n
9768 | Int64 n -> pr ", &%s" n
9769 | BufferIn n -> pr ", &%s, &%s_size" n n
9773 pr " return NULL;\n";
9775 pr " g = get_handle (py_g);\n";
9778 | Pathname _ | Device _ | Dev_or_Path _ | String _
9779 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9781 | StringList n | DeviceList n ->
9782 pr " %s = get_string_list (py_%s);\n" n n;
9783 pr " if (!%s) return NULL;\n" n
9788 pr " r = guestfs_%s " name;
9789 generate_c_call_args ~handle:"g" style;
9794 | Pathname _ | Device _ | Dev_or_Path _ | String _
9795 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9797 | StringList n | DeviceList n ->
9798 pr " free (%s);\n" n
9801 pr " if (r == %s) {\n" error_code;
9802 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9803 pr " return NULL;\n";
9807 (match fst style with
9809 pr " Py_INCREF (Py_None);\n";
9810 pr " py_r = Py_None;\n"
9812 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9813 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9814 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9815 | RConstOptString _ ->
9817 pr " py_r = PyString_FromString (r);\n";
9819 pr " Py_INCREF (Py_None);\n";
9820 pr " py_r = Py_None;\n";
9823 pr " py_r = PyString_FromString (r);\n";
9826 pr " py_r = put_string_list (r);\n";
9827 pr " free_strings (r);\n"
9828 | RStruct (_, typ) ->
9829 pr " py_r = put_%s (r);\n" typ;
9830 pr " guestfs_free_%s (r);\n" typ
9831 | RStructList (_, typ) ->
9832 pr " py_r = put_%s_list (r);\n" typ;
9833 pr " guestfs_free_%s_list (r);\n" typ
9835 pr " py_r = put_table (r);\n";
9836 pr " free_strings (r);\n"
9838 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9842 pr " return py_r;\n";
9847 (* Table of functions. *)
9848 pr "static PyMethodDef methods[] = {\n";
9849 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9850 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9852 fun (name, _, _, _, _, _, _) ->
9853 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9856 pr " { NULL, NULL, 0, NULL }\n";
9860 (* Init function. *)
9863 initlibguestfsmod (void)
9865 static int initialized = 0;
9867 if (initialized) return;
9868 Py_InitModule ((char *) \"libguestfsmod\", methods);
9873 (* Generate Python module. *)
9874 and generate_python_py () =
9875 generate_header HashStyle LGPLv2plus;
9878 u\"\"\"Python bindings for libguestfs
9881 g = guestfs.GuestFS ()
9882 g.add_drive (\"guest.img\")
9884 parts = g.list_partitions ()
9886 The guestfs module provides a Python binding to the libguestfs API
9887 for examining and modifying virtual machine disk images.
9889 Amongst the things this is good for: making batch configuration
9890 changes to guests, getting disk used/free statistics (see also:
9891 virt-df), migrating between virtualization systems (see also:
9892 virt-p2v), performing partial backups, performing partial guest
9893 clones, cloning guests and changing registry/UUID/hostname info, and
9896 Libguestfs uses Linux kernel and qemu code, and can access any type of
9897 guest filesystem that Linux and qemu can, including but not limited
9898 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9899 schemes, qcow, qcow2, vmdk.
9901 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9902 LVs, what filesystem is in each LV, etc.). It can also run commands
9903 in the context of the guest. Also you can access filesystems over
9906 Errors which happen while using the API are turned into Python
9907 RuntimeError exceptions.
9909 To create a guestfs handle you usually have to perform the following
9912 # Create the handle, call add_drive at least once, and possibly
9913 # several times if the guest has multiple block devices:
9914 g = guestfs.GuestFS ()
9915 g.add_drive (\"guest.img\")
9917 # Launch the qemu subprocess and wait for it to become ready:
9920 # Now you can issue commands, for example:
9925 import libguestfsmod
9928 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9930 def __init__ (self):
9931 \"\"\"Create a new libguestfs handle.\"\"\"
9932 self._o = libguestfsmod.create ()
9935 libguestfsmod.close (self._o)
9940 fun (name, style, _, flags, _, _, longdesc) ->
9942 generate_py_call_args ~handle:"self" (snd style);
9945 if not (List.mem NotInDocs flags) then (
9946 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9948 match fst style with
9949 | RErr | RInt _ | RInt64 _ | RBool _
9950 | RConstOptString _ | RConstString _
9951 | RString _ | RBufferOut _ -> doc
9953 doc ^ "\n\nThis function returns a list of strings."
9954 | RStruct (_, typ) ->
9955 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9956 | RStructList (_, typ) ->
9957 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9959 doc ^ "\n\nThis function returns a dictionary." in
9961 if List.mem ProtocolLimitWarning flags then
9962 doc ^ "\n\n" ^ protocol_limit_warning
9965 if List.mem DangerWillRobinson flags then
9966 doc ^ "\n\n" ^ danger_will_robinson
9969 match deprecation_notice flags with
9971 | Some txt -> doc ^ "\n\n" ^ txt in
9972 let doc = pod2text ~width:60 name doc in
9973 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9974 let doc = String.concat "\n " doc in
9975 pr " u\"\"\"%s\"\"\"\n" doc;
9977 pr " return libguestfsmod.%s " name;
9978 generate_py_call_args ~handle:"self._o" (snd style);
9983 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9984 and generate_py_call_args ~handle args =
9986 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9989 (* Useful if you need the longdesc POD text as plain text. Returns a
9992 * Because this is very slow (the slowest part of autogeneration),
9993 * we memoize the results.
9995 and pod2text ~width name longdesc =
9996 let key = width, name, longdesc in
9997 try Hashtbl.find pod2text_memo key
9999 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10000 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10002 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10003 let chan = open_process_in cmd in
10004 let lines = ref [] in
10006 let line = input_line chan in
10007 if i = 1 then (* discard the first line of output *)
10010 let line = triml line in
10011 lines := line :: !lines;
10014 let lines = try loop 1 with End_of_file -> List.rev !lines in
10016 (match close_process_in chan with
10019 failwithf "pod2text: process exited with non-zero status (%d)" i
10020 | WSIGNALED i | WSTOPPED i ->
10021 failwithf "pod2text: process signalled or stopped by signal %d" i
10023 Hashtbl.add pod2text_memo key lines;
10024 pod2text_memo_updated ();
10027 (* Generate ruby bindings. *)
10028 and generate_ruby_c () =
10029 generate_header CStyle LGPLv2plus;
10033 #include <stdlib.h>
10037 #include \"guestfs.h\"
10039 #include \"extconf.h\"
10041 /* For Ruby < 1.9 */
10043 #define RARRAY_LEN(r) (RARRAY((r))->len)
10046 static VALUE m_guestfs; /* guestfs module */
10047 static VALUE c_guestfs; /* guestfs_h handle */
10048 static VALUE e_Error; /* used for all errors */
10050 static void ruby_guestfs_free (void *p)
10053 guestfs_close ((guestfs_h *) p);
10056 static VALUE ruby_guestfs_create (VALUE m)
10060 g = guestfs_create ();
10062 rb_raise (e_Error, \"failed to create guestfs handle\");
10064 /* Don't print error messages to stderr by default. */
10065 guestfs_set_error_handler (g, NULL, NULL);
10067 /* Wrap it, and make sure the close function is called when the
10068 * handle goes away.
10070 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10073 static VALUE ruby_guestfs_close (VALUE gv)
10076 Data_Get_Struct (gv, guestfs_h, g);
10078 ruby_guestfs_free (g);
10079 DATA_PTR (gv) = NULL;
10087 fun (name, style, _, _, _, _, _) ->
10088 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10089 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10092 pr " guestfs_h *g;\n";
10093 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
10095 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10101 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
10102 pr " Check_Type (%sv, T_STRING);\n" n;
10103 pr " const char *%s = StringValueCStr (%sv);\n" n n;
10104 pr " if (!%s)\n" n;
10105 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10106 pr " \"%s\", \"%s\");\n" n name
10108 pr " Check_Type (%sv, T_STRING);\n" n;
10109 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
10110 pr " if (!%s)\n" n;
10111 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10112 pr " \"%s\", \"%s\");\n" n name;
10113 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
10115 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10116 | StringList n | DeviceList n ->
10117 pr " char **%s;\n" n;
10118 pr " Check_Type (%sv, T_ARRAY);\n" n;
10120 pr " size_t i, len;\n";
10121 pr " len = RARRAY_LEN (%sv);\n" n;
10122 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10124 pr " for (i = 0; i < len; ++i) {\n";
10125 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
10126 pr " %s[i] = StringValueCStr (v);\n" n;
10128 pr " %s[len] = NULL;\n" n;
10131 pr " int %s = RTEST (%sv);\n" n n
10133 pr " int %s = NUM2INT (%sv);\n" n n
10135 pr " long long %s = NUM2LL (%sv);\n" n n
10140 match fst style with
10141 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
10142 | RInt64 _ -> pr " int64_t r;\n"; "-1"
10143 | RConstString _ | RConstOptString _ ->
10144 pr " const char *r;\n"; "NULL"
10145 | RString _ -> pr " char *r;\n"; "NULL"
10146 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
10147 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
10148 | RStructList (_, typ) ->
10149 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
10152 pr " size_t size;\n";
10156 pr " r = guestfs_%s " name;
10157 generate_c_call_args ~handle:"g" style;
10162 | Pathname _ | Device _ | Dev_or_Path _ | String _
10163 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10165 | StringList n | DeviceList n ->
10166 pr " free (%s);\n" n
10169 pr " if (r == %s)\n" error_code;
10170 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10173 (match fst style with
10175 pr " return Qnil;\n"
10176 | RInt _ | RBool _ ->
10177 pr " return INT2NUM (r);\n"
10179 pr " return ULL2NUM (r);\n"
10180 | RConstString _ ->
10181 pr " return rb_str_new2 (r);\n";
10182 | RConstOptString _ ->
10184 pr " return rb_str_new2 (r);\n";
10186 pr " return Qnil;\n";
10188 pr " VALUE rv = rb_str_new2 (r);\n";
10190 pr " return rv;\n";
10192 pr " size_t i, len = 0;\n";
10193 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
10194 pr " VALUE rv = rb_ary_new2 (len);\n";
10195 pr " for (i = 0; r[i] != NULL; ++i) {\n";
10196 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10197 pr " free (r[i]);\n";
10201 | RStruct (_, typ) ->
10202 let cols = cols_of_struct typ in
10203 generate_ruby_struct_code typ cols
10204 | RStructList (_, typ) ->
10205 let cols = cols_of_struct typ in
10206 generate_ruby_struct_list_code typ cols
10208 pr " VALUE rv = rb_hash_new ();\n";
10210 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
10211 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10212 pr " free (r[i]);\n";
10213 pr " free (r[i+1]);\n";
10218 pr " VALUE rv = rb_str_new (r, size);\n";
10220 pr " return rv;\n";
10228 /* Initialize the module. */
10229 void Init__guestfs ()
10231 m_guestfs = rb_define_module (\"Guestfs\");
10232 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10233 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10235 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10236 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10239 (* Define the rest of the methods. *)
10241 fun (name, style, _, _, _, _, _) ->
10242 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
10243 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10248 (* Ruby code to return a struct. *)
10249 and generate_ruby_struct_code typ cols =
10250 pr " VALUE rv = rb_hash_new ();\n";
10254 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10256 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10258 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10259 | name, (FBytes|FUInt64) ->
10260 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10262 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10264 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10266 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10267 | name, FOptPercent ->
10268 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10269 | name, FChar -> (* XXX wrong? *)
10270 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10272 pr " guestfs_free_%s (r);\n" typ;
10275 (* Ruby code to return a struct list. *)
10276 and generate_ruby_struct_list_code typ cols =
10277 pr " VALUE rv = rb_ary_new2 (r->len);\n";
10279 pr " for (i = 0; i < r->len; ++i) {\n";
10280 pr " VALUE hv = rb_hash_new ();\n";
10284 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10286 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
10288 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10289 | name, (FBytes|FUInt64) ->
10290 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10292 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10294 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10296 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10297 | name, FOptPercent ->
10298 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10299 | name, FChar -> (* XXX wrong? *)
10300 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10302 pr " rb_ary_push (rv, hv);\n";
10304 pr " guestfs_free_%s_list (r);\n" typ;
10307 (* Generate Java bindings GuestFS.java file. *)
10308 and generate_java_java () =
10309 generate_header CStyle LGPLv2plus;
10312 package com.redhat.et.libguestfs;
10314 import java.util.HashMap;
10315 import com.redhat.et.libguestfs.LibGuestFSException;
10316 import com.redhat.et.libguestfs.PV;
10317 import com.redhat.et.libguestfs.VG;
10318 import com.redhat.et.libguestfs.LV;
10319 import com.redhat.et.libguestfs.Stat;
10320 import com.redhat.et.libguestfs.StatVFS;
10321 import com.redhat.et.libguestfs.IntBool;
10322 import com.redhat.et.libguestfs.Dirent;
10325 * The GuestFS object is a libguestfs handle.
10329 public class GuestFS {
10330 // Load the native code.
10332 System.loadLibrary (\"guestfs_jni\");
10336 * The native guestfs_h pointer.
10341 * Create a libguestfs handle.
10343 * @throws LibGuestFSException
10345 public GuestFS () throws LibGuestFSException
10349 private native long _create () throws LibGuestFSException;
10352 * Close a libguestfs handle.
10354 * You can also leave handles to be collected by the garbage
10355 * collector, but this method ensures that the resources used
10356 * by the handle are freed up immediately. If you call any
10357 * other methods after closing the handle, you will get an
10360 * @throws LibGuestFSException
10362 public void close () throws LibGuestFSException
10368 private native void _close (long g) throws LibGuestFSException;
10370 public void finalize () throws LibGuestFSException
10378 fun (name, style, _, flags, _, shortdesc, longdesc) ->
10379 if not (List.mem NotInDocs flags); then (
10380 let doc = replace_str longdesc "C<guestfs_" "C<g." in
10382 if List.mem ProtocolLimitWarning flags then
10383 doc ^ "\n\n" ^ protocol_limit_warning
10386 if List.mem DangerWillRobinson flags then
10387 doc ^ "\n\n" ^ danger_will_robinson
10390 match deprecation_notice flags with
10392 | Some txt -> doc ^ "\n\n" ^ txt in
10393 let doc = pod2text ~width:60 name doc in
10394 let doc = List.map ( (* RHBZ#501883 *)
10397 | nonempty -> nonempty
10399 let doc = String.concat "\n * " doc in
10402 pr " * %s\n" shortdesc;
10405 pr " * @throws LibGuestFSException\n";
10409 generate_java_prototype ~public:true ~semicolon:false name style;
10412 pr " if (g == 0)\n";
10413 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
10416 if fst style <> RErr then pr "return ";
10418 generate_java_call_args ~handle:"g" (snd style);
10422 generate_java_prototype ~privat:true ~native:true name style;
10429 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10430 and generate_java_call_args ~handle args =
10432 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10435 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10436 ?(semicolon=true) name style =
10437 if privat then pr "private ";
10438 if public then pr "public ";
10439 if native then pr "native ";
10442 (match fst style with
10443 | RErr -> pr "void ";
10444 | RInt _ -> pr "int ";
10445 | RInt64 _ -> pr "long ";
10446 | RBool _ -> pr "boolean ";
10447 | RConstString _ | RConstOptString _ | RString _
10448 | RBufferOut _ -> pr "String ";
10449 | RStringList _ -> pr "String[] ";
10450 | RStruct (_, typ) ->
10451 let name = java_name_of_struct typ in
10453 | RStructList (_, typ) ->
10454 let name = java_name_of_struct typ in
10456 | RHashtable _ -> pr "HashMap<String,String> ";
10459 if native then pr "_%s " name else pr "%s " name;
10461 let needs_comma = ref false in
10464 needs_comma := true
10470 if !needs_comma then pr ", ";
10471 needs_comma := true;
10475 | Device n | Dev_or_Path n
10483 | StringList n | DeviceList n ->
10494 pr " throws LibGuestFSException";
10495 if semicolon then pr ";"
10497 and generate_java_struct jtyp cols () =
10498 generate_header CStyle LGPLv2plus;
10501 package com.redhat.et.libguestfs;
10504 * Libguestfs %s structure.
10516 | name, FBuffer -> pr " public String %s;\n" name
10517 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10518 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10519 | name, FChar -> pr " public char %s;\n" name
10520 | name, FOptPercent ->
10521 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10522 pr " public float %s;\n" name
10527 and generate_java_c () =
10528 generate_header CStyle LGPLv2plus;
10532 #include <stdlib.h>
10533 #include <string.h>
10535 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10536 #include \"guestfs.h\"
10538 /* Note that this function returns. The exception is not thrown
10539 * until after the wrapper function returns.
10542 throw_exception (JNIEnv *env, const char *msg)
10545 cl = (*env)->FindClass (env,
10546 \"com/redhat/et/libguestfs/LibGuestFSException\");
10547 (*env)->ThrowNew (env, cl, msg);
10550 JNIEXPORT jlong JNICALL
10551 Java_com_redhat_et_libguestfs_GuestFS__1create
10552 (JNIEnv *env, jobject obj)
10556 g = guestfs_create ();
10558 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10561 guestfs_set_error_handler (g, NULL, NULL);
10562 return (jlong) (long) g;
10565 JNIEXPORT void JNICALL
10566 Java_com_redhat_et_libguestfs_GuestFS__1close
10567 (JNIEnv *env, jobject obj, jlong jg)
10569 guestfs_h *g = (guestfs_h *) (long) jg;
10576 fun (name, style, _, _, _, _, _) ->
10578 (match fst style with
10579 | RErr -> pr "void ";
10580 | RInt _ -> pr "jint ";
10581 | RInt64 _ -> pr "jlong ";
10582 | RBool _ -> pr "jboolean ";
10583 | RConstString _ | RConstOptString _ | RString _
10584 | RBufferOut _ -> pr "jstring ";
10585 | RStruct _ | RHashtable _ ->
10587 | RStringList _ | RStructList _ ->
10588 pr "jobjectArray ";
10591 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10592 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10594 pr " (JNIEnv *env, jobject obj, jlong jg";
10598 | Device n | Dev_or_Path n
10603 pr ", jstring j%s" n
10605 pr ", jbyteArray j%s" n
10606 | StringList n | DeviceList n ->
10607 pr ", jobjectArray j%s" n
10609 pr ", jboolean j%s" n
10617 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10618 let error_code, no_ret =
10619 match fst style with
10620 | RErr -> pr " int r;\n"; "-1", ""
10622 | RInt _ -> pr " int r;\n"; "-1", "0"
10623 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10624 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10625 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10627 pr " jstring jr;\n";
10628 pr " char *r;\n"; "NULL", "NULL"
10630 pr " jobjectArray jr;\n";
10631 pr " int r_len;\n";
10632 pr " jclass cl;\n";
10633 pr " jstring jstr;\n";
10634 pr " char **r;\n"; "NULL", "NULL"
10635 | RStruct (_, typ) ->
10636 pr " jobject jr;\n";
10637 pr " jclass cl;\n";
10638 pr " jfieldID fl;\n";
10639 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10640 | RStructList (_, typ) ->
10641 pr " jobjectArray jr;\n";
10642 pr " jclass cl;\n";
10643 pr " jfieldID fl;\n";
10644 pr " jobject jfl;\n";
10645 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10646 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10648 pr " jstring jr;\n";
10650 pr " size_t size;\n";
10655 | Device n | Dev_or_Path n
10660 pr " const char *%s;\n" n
10662 pr " jbyte *%s;\n" n;
10663 pr " size_t %s_size;\n" n
10664 | StringList n | DeviceList n ->
10665 pr " int %s_len;\n" n;
10666 pr " const char **%s;\n" n
10671 pr " int64_t %s;\n" n
10675 (match fst style with
10676 | RStringList _ | RStructList _ -> true
10677 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10678 | RConstOptString _
10679 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10680 List.exists (function
10681 | StringList _ -> true
10682 | DeviceList _ -> true
10683 | _ -> false) (snd style) in
10689 (* Get the parameters. *)
10693 | Device n | Dev_or_Path n
10697 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10699 (* This is completely undocumented, but Java null becomes
10700 * a NULL parameter.
10702 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10704 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10705 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10706 | StringList n | DeviceList n ->
10707 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10708 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10709 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10710 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10712 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10714 pr " %s[%s_len] = NULL;\n" n n;
10718 pr " %s = j%s;\n" n n
10721 (* Make the call. *)
10722 pr " r = guestfs_%s " name;
10723 generate_c_call_args ~handle:"g" style;
10726 (* Release the parameters. *)
10730 | Device n | Dev_or_Path n
10734 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10736 pr " if (j%s)\n" n;
10737 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10739 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10740 | StringList n | DeviceList n ->
10741 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10742 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10744 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10746 pr " free (%s);\n" n
10752 (* Check for errors. *)
10753 pr " if (r == %s) {\n" error_code;
10754 pr " throw_exception (env, guestfs_last_error (g));\n";
10755 pr " return %s;\n" no_ret;
10758 (* Return value. *)
10759 (match fst style with
10761 | RInt _ -> pr " return (jint) r;\n"
10762 | RBool _ -> pr " return (jboolean) r;\n"
10763 | RInt64 _ -> pr " return (jlong) r;\n"
10764 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10765 | RConstOptString _ ->
10766 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10768 pr " jr = (*env)->NewStringUTF (env, r);\n";
10772 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10773 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10774 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10775 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10776 pr " for (i = 0; i < r_len; ++i) {\n";
10777 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10778 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10779 pr " free (r[i]);\n";
10783 | RStruct (_, typ) ->
10784 let jtyp = java_name_of_struct typ in
10785 let cols = cols_of_struct typ in
10786 generate_java_struct_return typ jtyp cols
10787 | RStructList (_, typ) ->
10788 let jtyp = java_name_of_struct typ in
10789 let cols = cols_of_struct typ in
10790 generate_java_struct_list_return typ jtyp cols
10793 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10794 pr " return NULL;\n"
10796 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10805 and generate_java_struct_return typ jtyp cols =
10806 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10807 pr " jr = (*env)->AllocObject (env, cl);\n";
10811 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10812 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10815 pr " char s[33];\n";
10816 pr " memcpy (s, r->%s, 32);\n" name;
10817 pr " s[32] = 0;\n";
10818 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10819 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10823 pr " int len = r->%s_len;\n" name;
10824 pr " char s[len+1];\n";
10825 pr " memcpy (s, r->%s, len);\n" name;
10826 pr " s[len] = 0;\n";
10827 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10828 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10830 | name, (FBytes|FUInt64|FInt64) ->
10831 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10832 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10833 | name, (FUInt32|FInt32) ->
10834 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10835 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10836 | name, FOptPercent ->
10837 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10838 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10840 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10841 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10846 and generate_java_struct_list_return typ jtyp cols =
10847 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10848 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10849 pr " for (i = 0; i < r->len; ++i) {\n";
10850 pr " jfl = (*env)->AllocObject (env, cl);\n";
10854 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10855 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10858 pr " char s[33];\n";
10859 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10860 pr " s[32] = 0;\n";
10861 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10862 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10866 pr " int len = r->val[i].%s_len;\n" name;
10867 pr " char s[len+1];\n";
10868 pr " memcpy (s, r->val[i].%s, len);\n" name;
10869 pr " s[len] = 0;\n";
10870 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10871 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10873 | name, (FBytes|FUInt64|FInt64) ->
10874 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10875 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10876 | name, (FUInt32|FInt32) ->
10877 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10878 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10879 | name, FOptPercent ->
10880 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10881 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10883 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10884 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10886 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10888 pr " guestfs_free_%s_list (r);\n" typ;
10891 and generate_java_makefile_inc () =
10892 generate_header HashStyle GPLv2plus;
10894 pr "java_built_sources = \\\n";
10897 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10899 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10901 and generate_haskell_hs () =
10902 generate_header HaskellStyle LGPLv2plus;
10904 (* XXX We only know how to generate partial FFI for Haskell
10905 * at the moment. Please help out!
10907 let can_generate style =
10911 | RInt64 _, _ -> true
10913 | RConstString _, _
10914 | RConstOptString _, _
10920 | RBufferOut _, _ -> false in
10923 {-# INCLUDE <guestfs.h> #-}
10924 {-# LANGUAGE ForeignFunctionInterface #-}
10929 (* List out the names of the actions we want to export. *)
10931 fun (name, style, _, _, _, _, _) ->
10932 if can_generate style then pr ",\n %s" name
10938 -- Unfortunately some symbols duplicate ones already present
10939 -- in Prelude. We don't know which, so we hard-code a list
10941 import Prelude hiding (truncate)
10945 import Foreign.C.Types
10947 import Control.Exception
10948 import Data.Typeable
10950 data GuestfsS = GuestfsS -- represents the opaque C struct
10951 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10952 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10954 -- XXX define properly later XXX
10958 data IntBool = IntBool
10960 data StatVFS = StatVFS
10961 data Hashtable = Hashtable
10963 foreign import ccall unsafe \"guestfs_create\" c_create
10965 foreign import ccall unsafe \"&guestfs_close\" c_close
10966 :: FunPtr (GuestfsP -> IO ())
10967 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10968 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10970 create :: IO GuestfsH
10973 c_set_error_handler p nullPtr nullPtr
10974 h <- newForeignPtr c_close p
10977 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10978 :: GuestfsP -> IO CString
10980 -- last_error :: GuestfsH -> IO (Maybe String)
10981 -- last_error h = do
10982 -- str <- withForeignPtr h (\\p -> c_last_error p)
10983 -- maybePeek peekCString str
10985 last_error :: GuestfsH -> IO (String)
10987 str <- withForeignPtr h (\\p -> c_last_error p)
10988 if (str == nullPtr)
10989 then return \"no error\"
10990 else peekCString str
10994 (* Generate wrappers for each foreign function. *)
10996 fun (name, style, _, _, _, _, _) ->
10997 if can_generate style then (
10998 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
11000 generate_haskell_prototype ~handle:"GuestfsP" style;
11004 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11006 pr "%s %s = do\n" name
11007 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11009 (* Convert pointer arguments using with* functions. *)
11014 | Pathname n | Device n | Dev_or_Path n | String n ->
11015 pr "withCString %s $ \\%s -> " n n
11017 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11018 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11019 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11020 | Bool _ | Int _ | Int64 _ -> ()
11022 (* Convert integer arguments. *)
11026 | Bool n -> sprintf "(fromBool %s)" n
11027 | Int n -> sprintf "(fromIntegral %s)" n
11028 | Int64 n -> sprintf "(fromIntegral %s)" n
11029 | FileIn n | FileOut n
11030 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
11031 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11033 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11034 (String.concat " " ("p" :: args));
11035 (match fst style with
11036 | RErr | RInt _ | RInt64 _ | RBool _ ->
11037 pr " if (r == -1)\n";
11039 pr " err <- last_error h\n";
11041 | RConstString _ | RConstOptString _ | RString _
11042 | RStringList _ | RStruct _
11043 | RStructList _ | RHashtable _ | RBufferOut _ ->
11044 pr " if (r == nullPtr)\n";
11046 pr " err <- last_error h\n";
11049 (match fst style with
11051 pr " else return ()\n"
11053 pr " else return (fromIntegral r)\n"
11055 pr " else return (fromIntegral r)\n"
11057 pr " else return (toBool r)\n"
11059 | RConstOptString _
11066 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11072 and generate_haskell_prototype ~handle ?(hs = false) style =
11073 pr "%s -> " handle;
11074 let string = if hs then "String" else "CString" in
11075 let int = if hs then "Int" else "CInt" in
11076 let bool = if hs then "Bool" else "CInt" in
11077 let int64 = if hs then "Integer" else "Int64" in
11081 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
11083 if hs then pr "String"
11084 else pr "CString -> CInt"
11085 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11086 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11087 | Bool _ -> pr "%s" bool
11088 | Int _ -> pr "%s" int
11089 | Int64 _ -> pr "%s" int
11090 | FileIn _ -> pr "%s" string
11091 | FileOut _ -> pr "%s" string
11096 (match fst style with
11097 | RErr -> if not hs then pr "CInt"
11098 | RInt _ -> pr "%s" int
11099 | RInt64 _ -> pr "%s" int64
11100 | RBool _ -> pr "%s" bool
11101 | RConstString _ -> pr "%s" string
11102 | RConstOptString _ -> pr "Maybe %s" string
11103 | RString _ -> pr "%s" string
11104 | RStringList _ -> pr "[%s]" string
11105 | RStruct (_, typ) ->
11106 let name = java_name_of_struct typ in
11108 | RStructList (_, typ) ->
11109 let name = java_name_of_struct typ in
11111 | RHashtable _ -> pr "Hashtable"
11112 | RBufferOut _ -> pr "%s" string
11116 and generate_csharp () =
11117 generate_header CPlusPlusStyle LGPLv2plus;
11119 (* XXX Make this configurable by the C# assembly users. *)
11120 let library = "libguestfs.so.0" in
11123 // These C# bindings are highly experimental at present.
11125 // Firstly they only work on Linux (ie. Mono). In order to get them
11126 // to work on Windows (ie. .Net) you would need to port the library
11127 // itself to Windows first.
11129 // The second issue is that some calls are known to be incorrect and
11130 // can cause Mono to segfault. Particularly: calls which pass or
11131 // return string[], or return any structure value. This is because
11132 // we haven't worked out the correct way to do this from C#.
11134 // The third issue is that when compiling you get a lot of warnings.
11135 // We are not sure whether the warnings are important or not.
11137 // Fourthly we do not routinely build or test these bindings as part
11138 // of the make && make check cycle, which means that regressions might
11141 // Suggestions and patches are welcome.
11145 // gmcs Libguestfs.cs
11146 // mono Libguestfs.exe
11148 // (You'll probably want to add a Test class / static main function
11149 // otherwise this won't do anything useful).
11153 using System.Runtime.InteropServices;
11154 using System.Runtime.Serialization;
11155 using System.Collections;
11159 class Error : System.ApplicationException
11161 public Error (string message) : base (message) {}
11162 protected Error (SerializationInfo info, StreamingContext context) {}
11169 [DllImport (\"%s\")]
11170 static extern IntPtr guestfs_create ();
11174 _handle = guestfs_create ();
11175 if (_handle == IntPtr.Zero)
11176 throw new Error (\"could not create guestfs handle\");
11179 [DllImport (\"%s\")]
11180 static extern void guestfs_close (IntPtr h);
11184 guestfs_close (_handle);
11187 [DllImport (\"%s\")]
11188 static extern string guestfs_last_error (IntPtr h);
11190 " library library library;
11192 (* Generate C# structure bindings. We prefix struct names with
11193 * underscore because C# cannot have conflicting struct names and
11194 * method names (eg. "class stat" and "stat").
11198 pr " [StructLayout (LayoutKind.Sequential)]\n";
11199 pr " public class _%s {\n" typ;
11202 | name, FChar -> pr " char %s;\n" name
11203 | name, FString -> pr " string %s;\n" name
11205 pr " uint %s_len;\n" name;
11206 pr " string %s;\n" name
11208 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11209 pr " string %s;\n" name
11210 | name, FUInt32 -> pr " uint %s;\n" name
11211 | name, FInt32 -> pr " int %s;\n" name
11212 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
11213 | name, FInt64 -> pr " long %s;\n" name
11214 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
11220 (* Generate C# function bindings. *)
11222 fun (name, style, _, _, _, shortdesc, _) ->
11223 let rec csharp_return_type () =
11224 match fst style with
11226 | RBool n -> "bool"
11228 | RInt64 n -> "long"
11230 | RConstOptString n
11232 | RBufferOut n -> "string"
11233 | RStruct (_,n) -> "_" ^ n
11234 | RHashtable n -> "Hashtable"
11235 | RStringList n -> "string[]"
11236 | RStructList (_,n) -> sprintf "_%s[]" n
11238 and c_return_type () =
11239 match fst style with
11243 | RInt64 _ -> "long"
11245 | RConstOptString _
11247 | RBufferOut _ -> "string"
11248 | RStruct (_,n) -> "_" ^ n
11250 | RStringList _ -> "string[]"
11251 | RStructList (_,n) -> sprintf "_%s[]" n
11253 and c_error_comparison () =
11254 match fst style with
11258 | RInt64 _ -> "== -1"
11260 | RConstOptString _
11266 | RStructList (_,_) -> "== null"
11268 and generate_extern_prototype () =
11269 pr " static extern %s guestfs_%s (IntPtr h"
11270 (c_return_type ()) name;
11273 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11274 | FileIn n | FileOut n
11276 pr ", [In] string %s" n
11277 | StringList n | DeviceList n ->
11278 pr ", [In] string[] %s" n
11288 and generate_public_prototype () =
11289 pr " public %s %s (" (csharp_return_type ()) name;
11290 let comma = ref false in
11292 if !comma then pr ", ";
11297 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11298 | FileIn n | FileOut n
11300 next (); pr "string %s" n
11301 | StringList n | DeviceList n ->
11302 next (); pr "string[] %s" n
11304 next (); pr "bool %s" n
11306 next (); pr "int %s" n
11308 next (); pr "long %s" n
11312 and generate_call () =
11313 pr "guestfs_%s (_handle" name;
11314 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11318 pr " [DllImport (\"%s\")]\n" library;
11319 generate_extern_prototype ();
11321 pr " /// <summary>\n";
11322 pr " /// %s\n" shortdesc;
11323 pr " /// </summary>\n";
11324 generate_public_prototype ();
11326 pr " %s r;\n" (c_return_type ());
11329 pr " if (r %s)\n" (c_error_comparison ());
11330 pr " throw new Error (guestfs_last_error (_handle));\n";
11331 (match fst style with
11334 pr " return r != 0 ? true : false;\n"
11336 pr " Hashtable rr = new Hashtable ();\n";
11337 pr " for (size_t i = 0; i < r.Length; i += 2)\n";
11338 pr " rr.Add (r[i], r[i+1]);\n";
11340 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11341 | RString _ | RBufferOut _ | RStruct _ | RStringList _
11347 ) all_functions_sorted;
11353 and generate_bindtests () =
11354 generate_header CStyle LGPLv2plus;
11358 #include <stdlib.h>
11359 #include <inttypes.h>
11360 #include <string.h>
11362 #include \"guestfs.h\"
11363 #include \"guestfs-internal.h\"
11364 #include \"guestfs-internal-actions.h\"
11365 #include \"guestfs_protocol.h\"
11367 #define error guestfs_error
11368 #define safe_calloc guestfs_safe_calloc
11369 #define safe_malloc guestfs_safe_malloc
11372 print_strings (char *const *argv)
11377 for (argc = 0; argv[argc] != NULL; ++argc) {
11378 if (argc > 0) printf (\", \");
11379 printf (\"\\\"%%s\\\"\", argv[argc]);
11384 /* The test0 function prints its parameters to stdout. */
11388 match test_functions with
11389 | [] -> assert false
11390 | test0 :: tests -> test0, tests in
11393 let (name, style, _, _, _, _, _) = test0 in
11394 generate_prototype ~extern:false ~semicolon:false ~newline:true
11395 ~handle:"g" ~prefix:"guestfs__" name style;
11400 | Device n | Dev_or_Path n
11403 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
11407 pr " for (i = 0; i < %s_size; ++i)\n" n;
11408 pr " printf (\"<%%02x>\", %s[i]);\n" n;
11409 pr " printf (\"\\n\");\n";
11411 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11412 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
11413 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11414 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
11415 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11417 pr " /* Java changes stdout line buffering so we need this: */\n";
11418 pr " fflush (stdout);\n";
11424 fun (name, style, _, _, _, _, _) ->
11425 if String.sub name (String.length name - 3) 3 <> "err" then (
11426 pr "/* Test normal return. */\n";
11427 generate_prototype ~extern:false ~semicolon:false ~newline:true
11428 ~handle:"g" ~prefix:"guestfs__" name style;
11430 (match fst style with
11435 pr " sscanf (val, \"%%d\", &r);\n";
11438 pr " int64_t r;\n";
11439 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
11442 pr " return STREQ (val, \"true\");\n"
11444 | RConstOptString _ ->
11445 (* Can't return the input string here. Return a static
11446 * string so we ensure we get a segfault if the caller
11447 * tries to free it.
11449 pr " return \"static string\";\n"
11451 pr " return strdup (val);\n"
11453 pr " char **strs;\n";
11455 pr " sscanf (val, \"%%d\", &n);\n";
11456 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11457 pr " for (i = 0; i < n; ++i) {\n";
11458 pr " strs[i] = safe_malloc (g, 16);\n";
11459 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
11461 pr " strs[n] = NULL;\n";
11462 pr " return strs;\n"
11463 | RStruct (_, typ) ->
11464 pr " struct guestfs_%s *r;\n" typ;
11465 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11467 | RStructList (_, typ) ->
11468 pr " struct guestfs_%s_list *r;\n" typ;
11469 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11470 pr " sscanf (val, \"%%d\", &r->len);\n";
11471 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11474 pr " char **strs;\n";
11476 pr " sscanf (val, \"%%d\", &n);\n";
11477 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11478 pr " for (i = 0; i < n; ++i) {\n";
11479 pr " strs[i*2] = safe_malloc (g, 16);\n";
11480 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11481 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11482 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11484 pr " strs[n*2] = NULL;\n";
11485 pr " return strs;\n"
11487 pr " return strdup (val);\n"
11492 pr "/* Test error return. */\n";
11493 generate_prototype ~extern:false ~semicolon:false ~newline:true
11494 ~handle:"g" ~prefix:"guestfs__" name style;
11496 pr " error (g, \"error\");\n";
11497 (match fst style with
11498 | RErr | RInt _ | RInt64 _ | RBool _ ->
11500 | RConstString _ | RConstOptString _
11501 | RString _ | RStringList _ | RStruct _
11505 pr " return NULL;\n"
11512 and generate_ocaml_bindtests () =
11513 generate_header OCamlStyle GPLv2plus;
11517 let g = Guestfs.create () in
11521 String.concat " " (
11524 | CallString s -> "\"" ^ s ^ "\""
11525 | CallOptString None -> "None"
11526 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11527 | CallStringList xs ->
11528 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11529 | CallInt i when i >= 0 -> string_of_int i
11530 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11531 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11532 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11533 | CallBool b -> string_of_bool b
11534 | CallBuffer s -> sprintf "%S" s
11539 generate_lang_bindtests (
11540 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11543 pr "print_endline \"EOF\"\n"
11545 and generate_perl_bindtests () =
11546 pr "#!/usr/bin/perl -w\n";
11547 generate_header HashStyle GPLv2plus;
11554 my $g = Sys::Guestfs->new ();
11558 String.concat ", " (
11561 | CallString s -> "\"" ^ s ^ "\""
11562 | CallOptString None -> "undef"
11563 | CallOptString (Some s) -> sprintf "\"%s\"" s
11564 | CallStringList xs ->
11565 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11566 | CallInt i -> string_of_int i
11567 | CallInt64 i -> Int64.to_string i
11568 | CallBool b -> if b then "1" else "0"
11569 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11574 generate_lang_bindtests (
11575 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11578 pr "print \"EOF\\n\"\n"
11580 and generate_python_bindtests () =
11581 generate_header HashStyle GPLv2plus;
11586 g = guestfs.GuestFS ()
11590 String.concat ", " (
11593 | CallString s -> "\"" ^ s ^ "\""
11594 | CallOptString None -> "None"
11595 | CallOptString (Some s) -> sprintf "\"%s\"" s
11596 | CallStringList xs ->
11597 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11598 | CallInt i -> string_of_int i
11599 | CallInt64 i -> Int64.to_string i
11600 | CallBool b -> if b then "1" else "0"
11601 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11606 generate_lang_bindtests (
11607 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11610 pr "print \"EOF\"\n"
11612 and generate_ruby_bindtests () =
11613 generate_header HashStyle GPLv2plus;
11618 g = Guestfs::create()
11622 String.concat ", " (
11625 | CallString s -> "\"" ^ s ^ "\""
11626 | CallOptString None -> "nil"
11627 | CallOptString (Some s) -> sprintf "\"%s\"" s
11628 | CallStringList xs ->
11629 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11630 | CallInt i -> string_of_int i
11631 | CallInt64 i -> Int64.to_string i
11632 | CallBool b -> string_of_bool b
11633 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11638 generate_lang_bindtests (
11639 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11642 pr "print \"EOF\\n\"\n"
11644 and generate_java_bindtests () =
11645 generate_header CStyle GPLv2plus;
11648 import com.redhat.et.libguestfs.*;
11650 public class Bindtests {
11651 public static void main (String[] argv)
11654 GuestFS g = new GuestFS ();
11658 String.concat ", " (
11661 | CallString s -> "\"" ^ s ^ "\""
11662 | CallOptString None -> "null"
11663 | CallOptString (Some s) -> sprintf "\"%s\"" s
11664 | CallStringList xs ->
11666 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11667 | CallInt i -> string_of_int i
11668 | CallInt64 i -> Int64.to_string i
11669 | CallBool b -> string_of_bool b
11671 "new byte[] { " ^ String.concat "," (
11672 map_chars (fun c -> string_of_int (Char.code c)) s
11678 generate_lang_bindtests (
11679 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11683 System.out.println (\"EOF\");
11685 catch (Exception exn) {
11686 System.err.println (exn);
11693 and generate_haskell_bindtests () =
11694 generate_header HaskellStyle GPLv2plus;
11697 module Bindtests where
11698 import qualified Guestfs
11701 g <- Guestfs.create
11705 String.concat " " (
11708 | CallString s -> "\"" ^ s ^ "\""
11709 | CallOptString None -> "Nothing"
11710 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11711 | CallStringList xs ->
11712 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11713 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11714 | CallInt i -> string_of_int i
11715 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11716 | CallInt64 i -> Int64.to_string i
11717 | CallBool true -> "True"
11718 | CallBool false -> "False"
11719 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11724 generate_lang_bindtests (
11725 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11728 pr " putStrLn \"EOF\"\n"
11730 (* Language-independent bindings tests - we do it this way to
11731 * ensure there is parity in testing bindings across all languages.
11733 and generate_lang_bindtests call =
11734 call "test0" [CallString "abc"; CallOptString (Some "def");
11735 CallStringList []; CallBool false;
11736 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11737 CallBuffer "abc\000abc"];
11738 call "test0" [CallString "abc"; CallOptString None;
11739 CallStringList []; CallBool false;
11740 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11741 CallBuffer "abc\000abc"];
11742 call "test0" [CallString ""; CallOptString (Some "def");
11743 CallStringList []; CallBool false;
11744 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11745 CallBuffer "abc\000abc"];
11746 call "test0" [CallString ""; CallOptString (Some "");
11747 CallStringList []; CallBool false;
11748 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11749 CallBuffer "abc\000abc"];
11750 call "test0" [CallString "abc"; CallOptString (Some "def");
11751 CallStringList ["1"]; CallBool false;
11752 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11753 CallBuffer "abc\000abc"];
11754 call "test0" [CallString "abc"; CallOptString (Some "def");
11755 CallStringList ["1"; "2"]; CallBool false;
11756 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11757 CallBuffer "abc\000abc"];
11758 call "test0" [CallString "abc"; CallOptString (Some "def");
11759 CallStringList ["1"]; CallBool true;
11760 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11761 CallBuffer "abc\000abc"];
11762 call "test0" [CallString "abc"; CallOptString (Some "def");
11763 CallStringList ["1"]; CallBool false;
11764 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11765 CallBuffer "abc\000abc"];
11766 call "test0" [CallString "abc"; CallOptString (Some "def");
11767 CallStringList ["1"]; CallBool false;
11768 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11769 CallBuffer "abc\000abc"];
11770 call "test0" [CallString "abc"; CallOptString (Some "def");
11771 CallStringList ["1"]; CallBool false;
11772 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11773 CallBuffer "abc\000abc"];
11774 call "test0" [CallString "abc"; CallOptString (Some "def");
11775 CallStringList ["1"]; CallBool false;
11776 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11777 CallBuffer "abc\000abc"];
11778 call "test0" [CallString "abc"; CallOptString (Some "def");
11779 CallStringList ["1"]; CallBool false;
11780 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11781 CallBuffer "abc\000abc"];
11782 call "test0" [CallString "abc"; CallOptString (Some "def");
11783 CallStringList ["1"]; CallBool false;
11784 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11785 CallBuffer "abc\000abc"]
11787 (* XXX Add here tests of the return and error functions. *)
11789 (* Code to generator bindings for virt-inspector. Currently only
11790 * implemented for OCaml code (for virt-p2v 2.0).
11792 let rng_input = "inspector/virt-inspector.rng"
11794 (* Read the input file and parse it into internal structures. This is
11795 * by no means a complete RELAX NG parser, but is just enough to be
11796 * able to parse the specific input file.
11799 | Element of string * rng list (* <element name=name/> *)
11800 | Attribute of string * rng list (* <attribute name=name/> *)
11801 | Interleave of rng list (* <interleave/> *)
11802 | ZeroOrMore of rng (* <zeroOrMore/> *)
11803 | OneOrMore of rng (* <oneOrMore/> *)
11804 | Optional of rng (* <optional/> *)
11805 | Choice of string list (* <choice><value/>*</choice> *)
11806 | Value of string (* <value>str</value> *)
11807 | Text (* <text/> *)
11809 let rec string_of_rng = function
11810 | Element (name, xs) ->
11811 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11812 | Attribute (name, xs) ->
11813 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11814 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11815 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11816 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11817 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11818 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11819 | Value value -> "Value \"" ^ value ^ "\""
11822 and string_of_rng_list xs =
11823 String.concat ", " (List.map string_of_rng xs)
11825 let rec parse_rng ?defines context = function
11827 | Xml.Element ("element", ["name", name], children) :: rest ->
11828 Element (name, parse_rng ?defines context children)
11829 :: parse_rng ?defines context rest
11830 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11831 Attribute (name, parse_rng ?defines context children)
11832 :: parse_rng ?defines context rest
11833 | Xml.Element ("interleave", [], children) :: rest ->
11834 Interleave (parse_rng ?defines context children)
11835 :: parse_rng ?defines context rest
11836 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11837 let rng = parse_rng ?defines context [child] in
11839 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11841 failwithf "%s: <zeroOrMore> contains more than one child element"
11844 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11845 let rng = parse_rng ?defines context [child] in
11847 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11849 failwithf "%s: <oneOrMore> contains more than one child element"
11852 | Xml.Element ("optional", [], [child]) :: rest ->
11853 let rng = parse_rng ?defines context [child] in
11855 | [child] -> Optional child :: parse_rng ?defines context rest
11857 failwithf "%s: <optional> contains more than one child element"
11860 | Xml.Element ("choice", [], children) :: rest ->
11861 let values = List.map (
11862 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11864 failwithf "%s: can't handle anything except <value> in <choice>"
11868 :: parse_rng ?defines context rest
11869 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11870 Value value :: parse_rng ?defines context rest
11871 | Xml.Element ("text", [], []) :: rest ->
11872 Text :: parse_rng ?defines context rest
11873 | Xml.Element ("ref", ["name", name], []) :: rest ->
11874 (* Look up the reference. Because of limitations in this parser,
11875 * we can't handle arbitrarily nested <ref> yet. You can only
11876 * use <ref> from inside <start>.
11878 (match defines with
11880 failwithf "%s: contains <ref>, but no refs are defined yet" context
11882 let rng = StringMap.find name map in
11883 rng @ parse_rng ?defines context rest
11886 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11889 let xml = Xml.parse_file rng_input in
11891 | Xml.Element ("grammar", _,
11892 Xml.Element ("start", _, gram) :: defines) ->
11893 (* The <define/> elements are referenced in the <start> section,
11894 * so build a map of those first.
11896 let defines = List.fold_left (
11898 function Xml.Element ("define", ["name", name], defn) ->
11899 StringMap.add name defn map
11901 failwithf "%s: expected <define name=name/>" rng_input
11902 ) StringMap.empty defines in
11903 let defines = StringMap.mapi parse_rng defines in
11905 (* Parse the <start> clause, passing the defines. *)
11906 parse_rng ~defines "<start>" gram
11908 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11911 let name_of_field = function
11912 | Element (name, _) | Attribute (name, _)
11913 | ZeroOrMore (Element (name, _))
11914 | OneOrMore (Element (name, _))
11915 | Optional (Element (name, _)) -> name
11916 | Optional (Attribute (name, _)) -> name
11917 | Text -> (* an unnamed field in an element *)
11920 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11922 (* At the moment this function only generates OCaml types. However we
11923 * should parameterize it later so it can generate types/structs in a
11924 * variety of languages.
11926 let generate_types xs =
11927 (* A simple type is one that can be printed out directly, eg.
11928 * "string option". A complex type is one which has a name and has
11929 * to be defined via another toplevel definition, eg. a struct.
11931 * generate_type generates code for either simple or complex types.
11932 * In the simple case, it returns the string ("string option"). In
11933 * the complex case, it returns the name ("mountpoint"). In the
11934 * complex case it has to print out the definition before returning,
11935 * so it should only be called when we are at the beginning of a
11936 * new line (BOL context).
11938 let rec generate_type = function
11939 | Text -> (* string *)
11941 | Choice values -> (* [`val1|`val2|...] *)
11942 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11943 | ZeroOrMore rng -> (* <rng> list *)
11944 let t, is_simple = generate_type rng in
11945 t ^ " list (* 0 or more *)", is_simple
11946 | OneOrMore rng -> (* <rng> list *)
11947 let t, is_simple = generate_type rng in
11948 t ^ " list (* 1 or more *)", is_simple
11949 (* virt-inspector hack: bool *)
11950 | Optional (Attribute (name, [Value "1"])) ->
11952 | Optional rng -> (* <rng> list *)
11953 let t, is_simple = generate_type rng in
11954 t ^ " option", is_simple
11955 (* type name = { fields ... } *)
11956 | Element (name, fields) when is_attrs_interleave fields ->
11957 generate_type_struct name (get_attrs_interleave fields)
11958 | Element (name, [field]) (* type name = field *)
11959 | Attribute (name, [field]) ->
11960 let t, is_simple = generate_type field in
11961 if is_simple then (t, true)
11963 pr "type %s = %s\n" name t;
11966 | Element (name, fields) -> (* type name = { fields ... } *)
11967 generate_type_struct name fields
11969 failwithf "generate_type failed at: %s" (string_of_rng rng)
11971 and is_attrs_interleave = function
11972 | [Interleave _] -> true
11973 | Attribute _ :: fields -> is_attrs_interleave fields
11974 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11977 and get_attrs_interleave = function
11978 | [Interleave fields] -> fields
11979 | ((Attribute _) as field) :: fields
11980 | ((Optional (Attribute _)) as field) :: fields ->
11981 field :: get_attrs_interleave fields
11982 | _ -> assert false
11984 and generate_types xs =
11985 List.iter (fun x -> ignore (generate_type x)) xs
11987 and generate_type_struct name fields =
11988 (* Calculate the types of the fields first. We have to do this
11989 * before printing anything so we are still in BOL context.
11991 let types = List.map fst (List.map generate_type fields) in
11993 (* Special case of a struct containing just a string and another
11994 * field. Turn it into an assoc list.
11997 | ["string"; other] ->
11998 let fname1, fname2 =
12000 | [f1; f2] -> name_of_field f1, name_of_field f2
12001 | _ -> assert false in
12002 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12006 pr "type %s = {\n" name;
12008 fun (field, ftype) ->
12009 let fname = name_of_field field in
12010 pr " %s_%s : %s;\n" name fname ftype
12011 ) (List.combine fields types);
12013 (* Return the name of this type, and
12014 * false because it's not a simple type.
12021 let generate_parsers xs =
12022 (* As for generate_type above, generate_parser makes a parser for
12023 * some type, and returns the name of the parser it has generated.
12024 * Because it (may) need to print something, it should always be
12025 * called in BOL context.
12027 let rec generate_parser = function
12028 | Text -> (* string *)
12029 "string_child_or_empty"
12030 | Choice values -> (* [`val1|`val2|...] *)
12031 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12033 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12034 | ZeroOrMore rng -> (* <rng> list *)
12035 let pa = generate_parser rng in
12036 sprintf "(fun x -> List.map %s (Xml.children x))" pa
12037 | OneOrMore rng -> (* <rng> list *)
12038 let pa = generate_parser rng in
12039 sprintf "(fun x -> List.map %s (Xml.children x))" pa
12040 (* virt-inspector hack: bool *)
12041 | Optional (Attribute (name, [Value "1"])) ->
12042 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12043 | Optional rng -> (* <rng> list *)
12044 let pa = generate_parser rng in
12045 sprintf "(function None -> None | Some x -> Some (%s x))" pa
12046 (* type name = { fields ... } *)
12047 | Element (name, fields) when is_attrs_interleave fields ->
12048 generate_parser_struct name (get_attrs_interleave fields)
12049 | Element (name, [field]) -> (* type name = field *)
12050 let pa = generate_parser field in
12051 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12052 pr "let %s =\n" parser_name;
12054 pr "let parse_%s = %s\n" name parser_name;
12056 | Attribute (name, [field]) ->
12057 let pa = generate_parser field in
12058 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12059 pr "let %s =\n" parser_name;
12061 pr "let parse_%s = %s\n" name parser_name;
12063 | Element (name, fields) -> (* type name = { fields ... } *)
12064 generate_parser_struct name ([], fields)
12066 failwithf "generate_parser failed at: %s" (string_of_rng rng)
12068 and is_attrs_interleave = function
12069 | [Interleave _] -> true
12070 | Attribute _ :: fields -> is_attrs_interleave fields
12071 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12074 and get_attrs_interleave = function
12075 | [Interleave fields] -> [], fields
12076 | ((Attribute _) as field) :: fields
12077 | ((Optional (Attribute _)) as field) :: fields ->
12078 let attrs, interleaves = get_attrs_interleave fields in
12079 (field :: attrs), interleaves
12080 | _ -> assert false
12082 and generate_parsers xs =
12083 List.iter (fun x -> ignore (generate_parser x)) xs
12085 and generate_parser_struct name (attrs, interleaves) =
12086 (* Generate parsers for the fields first. We have to do this
12087 * before printing anything so we are still in BOL context.
12089 let fields = attrs @ interleaves in
12090 let pas = List.map generate_parser fields in
12092 (* Generate an intermediate tuple from all the fields first.
12093 * If the type is just a string + another field, then we will
12094 * return this directly, otherwise it is turned into a record.
12096 * RELAX NG note: This code treats <interleave> and plain lists of
12097 * fields the same. In other words, it doesn't bother enforcing
12098 * any ordering of fields in the XML.
12100 pr "let parse_%s x =\n" name;
12101 pr " let t = (\n ";
12102 let comma = ref false in
12105 if !comma then pr ",\n ";
12108 | Optional (Attribute (fname, [field])), pa ->
12110 | Optional (Element (fname, [field])), pa ->
12111 pr "%s (optional_child %S x)" pa fname
12112 | Attribute (fname, [Text]), _ ->
12113 pr "attribute %S x" fname
12114 | (ZeroOrMore _ | OneOrMore _), pa ->
12119 let fname = name_of_field field in
12120 pr "%s (child %S x)" pa fname
12121 ) (List.combine fields pas);
12125 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12129 pr " (Obj.magic t : %s)\n" name
12133 | (Optional (Attribute (fname, [field])), pa) ->
12134 pr " %s_%s =\n" name fname;
12136 | (Optional (Element (fname, [field])), pa) ->
12137 pr " %s_%s =\n" name fname;
12138 pr " (let x = optional_child %S x in\n" fname;
12141 let fname = name_of_field field in
12142 pr " %s_%s =\n" name fname;
12143 pr " (let x = child %S x in\n" fname;
12145 ) (List.combine fields pas);
12149 sprintf "parse_%s" name
12152 generate_parsers xs
12154 (* Generate ocaml/guestfs_inspector.mli. *)
12155 let generate_ocaml_inspector_mli () =
12156 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12159 (** This is an OCaml language binding to the external [virt-inspector]
12162 For more information, please read the man page [virt-inspector(1)].
12167 generate_types grammar;
12168 pr "(** The nested information returned from the {!inspect} function. *)\n";
12172 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12173 (** To inspect a libvirt domain called [name], pass a singleton
12174 list: [inspect [name]]. When using libvirt only, you may
12175 optionally pass a libvirt URI using [inspect ~connect:uri ...].
12177 To inspect a disk image or images, pass a list of the filenames
12178 of the disk images: [inspect filenames]
12180 This function inspects the given guest or disk images and
12181 returns a list of operating system(s) found and a large amount
12182 of information about them. In the vast majority of cases,
12183 a virtual machine only contains a single operating system.
12185 If the optional [~xml] parameter is given, then this function
12186 skips running the external virt-inspector program and just
12187 parses the given XML directly (which is expected to be XML
12188 produced from a previous run of virt-inspector). The list of
12189 names and connect URI are ignored in this case.
12191 This function can throw a wide variety of exceptions, for example
12192 if the external virt-inspector program cannot be found, or if
12193 it doesn't generate valid XML.
12197 (* Generate ocaml/guestfs_inspector.ml. *)
12198 let generate_ocaml_inspector_ml () =
12199 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12204 generate_types grammar;
12208 (* Misc functions which are used by the parser code below. *)
12209 let first_child = function
12210 | Xml.Element (_, _, c::_) -> c
12211 | Xml.Element (name, _, []) ->
12212 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12213 | Xml.PCData str ->
12214 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12216 let string_child_or_empty = function
12217 | Xml.Element (_, _, [Xml.PCData s]) -> s
12218 | Xml.Element (_, _, []) -> \"\"
12219 | Xml.Element (x, _, _) ->
12220 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12222 | Xml.PCData str ->
12223 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12225 let optional_child name xml =
12226 let children = Xml.children xml in
12228 Some (List.find (function
12229 | Xml.Element (n, _, _) when n = name -> true
12230 | _ -> false) children)
12234 let child name xml =
12235 match optional_child name xml with
12238 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12240 let attribute name xml =
12241 try Xml.attrib xml name
12242 with Xml.No_attribute _ ->
12243 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12247 generate_parsers grammar;
12251 (* Run external virt-inspector, then use parser to parse the XML. *)
12252 let inspect ?connect ?xml names =
12256 if names = [] then invalid_arg \"inspect: no names given\";
12257 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12258 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12260 let cmd = List.map Filename.quote cmd in
12261 let cmd = String.concat \" \" cmd in
12262 let chan = open_process_in cmd in
12263 let xml = Xml.parse_in chan in
12264 (match close_process_in chan with
12266 | WEXITED _ -> failwith \"external virt-inspector command failed\"
12267 | WSIGNALED i | WSTOPPED i ->
12268 failwith (\"external virt-inspector command died or stopped on sig \" ^
12273 Xml.parse_string doc in
12274 parse_operatingsystems xml
12277 and generate_max_proc_nr () =
12278 pr "%d\n" max_proc_nr
12280 let output_to filename k =
12281 let filename_new = filename ^ ".new" in
12282 chan := open_out filename_new;
12285 chan := Pervasives.stdout;
12287 (* Is the new file different from the current file? *)
12288 if Sys.file_exists filename && files_equal filename filename_new then
12289 unlink filename_new (* same, so skip it *)
12291 (* different, overwrite old one *)
12292 (try chmod filename 0o644 with Unix_error _ -> ());
12293 rename filename_new filename;
12294 chmod filename 0o444;
12295 printf "written %s\n%!" filename;
12298 let perror msg = function
12299 | Unix_error (err, _, _) ->
12300 eprintf "%s: %s\n" msg (error_message err)
12302 eprintf "%s: %s\n" msg (Printexc.to_string exn)
12304 (* Main program. *)
12307 try openfile "HACKING" [O_RDWR] 0
12309 | Unix_error (ENOENT, _, _) ->
12311 You are probably running this from the wrong directory.
12312 Run it from the top source directory using the command
12317 perror "open: HACKING" exn;
12320 (* Acquire a lock so parallel builds won't try to run the generator
12321 * twice at the same time. Subsequent builds will wait for the first
12322 * one to finish. Note the lock is released implicitly when the
12325 (try lockf lock_fd F_LOCK 1
12327 perror "lock: HACKING" exn;
12330 check_functions ();
12332 output_to "src/guestfs_protocol.x" generate_xdr;
12333 output_to "src/guestfs-structs.h" generate_structs_h;
12334 output_to "src/guestfs-actions.h" generate_actions_h;
12335 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12336 output_to "src/actions.c" generate_client_actions;
12337 output_to "src/bindtests.c" generate_bindtests;
12338 output_to "src/guestfs-structs.pod" generate_structs_pod;
12339 output_to "src/guestfs-actions.pod" generate_actions_pod;
12340 output_to "src/guestfs-availability.pod" generate_availability_pod;
12341 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12342 output_to "src/libguestfs.syms" generate_linker_script;
12343 output_to "daemon/actions.h" generate_daemon_actions_h;
12344 output_to "daemon/stubs.c" generate_daemon_actions;
12345 output_to "daemon/names.c" generate_daemon_names;
12346 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12347 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12348 output_to "capitests/tests.c" generate_tests;
12349 output_to "fish/cmds.c" generate_fish_cmds;
12350 output_to "fish/completion.c" generate_fish_completion;
12351 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12352 output_to "fish/prepopts.c" generate_fish_prep_options_c;
12353 output_to "fish/prepopts.h" generate_fish_prep_options_h;
12354 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12355 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12356 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12357 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12358 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12359 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12360 output_to "perl/Guestfs.xs" generate_perl_xs;
12361 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12362 output_to "perl/bindtests.pl" generate_perl_bindtests;
12363 output_to "python/guestfs-py.c" generate_python_c;
12364 output_to "python/guestfs.py" generate_python_py;
12365 output_to "python/bindtests.py" generate_python_bindtests;
12366 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12367 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12368 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12372 let cols = cols_of_struct typ in
12373 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12374 output_to filename (generate_java_struct jtyp cols);
12377 output_to "java/Makefile.inc" generate_java_makefile_inc;
12378 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12379 output_to "java/Bindtests.java" generate_java_bindtests;
12380 output_to "haskell/Guestfs.hs" generate_haskell_hs;
12381 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12382 output_to "csharp/Libguestfs.cs" generate_csharp;
12384 (* Always generate this file last, and unconditionally. It's used
12385 * by the Makefile to know when we must re-run the generator.
12387 let chan = open_out "src/stamp-generator" in
12388 fprintf chan "1\n";
12391 printf "generated %d lines of code\n" !lines