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.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | FishOutput of fish_output_t (* how to display output in guestfish *)
186 | NotInFish (* do not export via guestfish *)
187 | NotInDocs (* do not add this function to documentation *)
188 | DeprecatedBy of string (* function is deprecated, use .. instead *)
189 | Optional of string (* function is part of an optional group *)
192 | FishOutputOctal (* for int return, print in octal *)
193 | FishOutputHexadecimal (* for int return, print in hex *)
195 (* You can supply zero or as many tests as you want per API call.
197 * Note that the test environment has 3 block devices, of size 500MB,
198 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199 * a fourth ISO block device with some known files on it (/dev/sdd).
201 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202 * Number of cylinders was 63 for IDE emulated disks with precisely
203 * the same size. How exactly this is calculated is a mystery.
205 * The ISO block device (/dev/sdd) comes from images/test.iso.
207 * To be able to run the tests in a reasonable amount of time,
208 * the virtual machine and block devices are reused between tests.
209 * So don't try testing kill_subprocess :-x
211 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
213 * Don't assume anything about the previous contents of the block
214 * devices. Use 'Init*' to create some initial scenarios.
216 * You can add a prerequisite clause to any individual test. This
217 * is a run-time check, which, if it fails, causes the test to be
218 * skipped. Useful if testing a command which might not work on
219 * all variations of libguestfs builds. A test that has prerequisite
220 * of 'Always' is run unconditionally.
222 * In addition, packagers can skip individual tests by setting the
223 * environment variables: eg:
224 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
225 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
227 type tests = (test_init * test_prereq * test) list
229 (* Run the command sequence and just expect nothing to fail. *)
232 (* Run the command sequence and expect the output of the final
233 * command to be the string.
235 | TestOutput of seq * string
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of strings.
240 | TestOutputList of seq * string list
242 (* Run the command sequence and expect the output of the final
243 * command to be the list of block devices (could be either
244 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245 * character of each string).
247 | TestOutputListOfDevices of seq * string list
249 (* Run the command sequence and expect the output of the final
250 * command to be the integer.
252 | TestOutputInt of seq * int
254 (* Run the command sequence and expect the output of the final
255 * command to be <op> <int>, eg. ">=", "1".
257 | TestOutputIntOp of seq * string * int
259 (* Run the command sequence and expect the output of the final
260 * command to be a true value (!= 0 or != NULL).
262 | TestOutputTrue of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a false value (== 0 or == NULL, but not an error).
267 | TestOutputFalse of seq
269 (* Run the command sequence and expect the output of the final
270 * command to be a list of the given length (but don't care about
273 | TestOutputLength of seq * int
275 (* Run the command sequence and expect the output of the final
276 * command to be a buffer (RBufferOut), ie. string + size.
278 | TestOutputBuffer of seq * string
280 (* Run the command sequence and expect the output of the final
281 * command to be a structure.
283 | TestOutputStruct of seq * test_field_compare list
285 (* Run the command sequence and expect the final command (only)
288 | TestLastFail of seq
290 and test_field_compare =
291 | CompareWithInt of string * int
292 | CompareWithIntOp of string * string * int
293 | CompareWithString of string * string
294 | CompareFieldsIntEq of string * string
295 | CompareFieldsStrEq of string * string
297 (* Test prerequisites. *)
299 (* Test always runs. *)
302 (* Test is currently disabled - eg. it fails, or it tests some
303 * unimplemented feature.
307 (* 'string' is some C code (a function body) that should return
308 * true or false. The test will run if the code returns true.
312 (* As for 'If' but the test runs _unless_ the code returns true. *)
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";
390 let test_all_rets = [
391 (* except for RErr, which is tested thoroughly elsewhere *)
392 "test0rint", RInt "valout";
393 "test0rint64", RInt64 "valout";
394 "test0rbool", RBool "valout";
395 "test0rconststring", RConstString "valout";
396 "test0rconstoptstring", RConstOptString "valout";
397 "test0rstring", RString "valout";
398 "test0rstringlist", RStringList "valout";
399 "test0rstruct", RStruct ("valout", "lvm_pv");
400 "test0rstructlist", RStructList ("valout", "lvm_pv");
401 "test0rhashtable", RHashtable "valout";
404 let test_functions = [
405 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407 "internal test function - do not use",
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
413 It echos the contents of each parameter to stdout.
415 You probably don't want to call this function.");
419 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421 "internal test function - do not use",
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
427 It converts string C<val> to the return type.
429 You probably don't want to call this function.");
430 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432 "internal test function - do not use",
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
438 This function always returns an error.
440 You probably don't want to call this function.")]
444 (* non_daemon_functions are any functions which don't get processed
445 * in the daemon, eg. functions for setting and getting local
446 * configuration values.
449 let non_daemon_functions = test_functions @ [
450 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
452 "launch the qemu subprocess",
454 Internally libguestfs is implemented by running a virtual machine
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
460 ("wait_ready", (RErr, []), -1, [NotInFish],
462 "wait until the qemu subprocess launches (no op)",
464 This function is a no op.
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete. However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
475 ("kill_subprocess", (RErr, []), -1, [],
477 "kill the qemu subprocess",
479 This kills the qemu subprocess. You should never need to call this.");
481 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483 "add an image to examine or modify",
485 This function adds a virtual machine disk image C<filename> to the
486 guest. The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
490 You don't necessarily need to be root when using libguestfs. However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>. In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
507 Note that this call checks for the existence of C<filename>. This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
510 the general C<guestfs_config> call instead.");
512 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514 "add a CD-ROM disk image to examine",
516 This function adds a virtual CD-ROM disk image to the guest.
518 This is equivalent to the qemu parameter C<-cdrom filename>.
526 This call checks for the existence of C<filename>. This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
529 the general C<guestfs_config> call instead.
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
539 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541 "add a drive in snapshot mode (read-only)",
543 This adds a drive in snapshot mode, making it effectively
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed. We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>. In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
560 C<readonly=on> is only added where qemu supports this option.
562 Note that this call checks for the existence of C<filename>. This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
565 the general C<guestfs_config> call instead.");
567 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569 "add qemu parameters",
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>. Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
576 The first character of C<param> string must be a C<-> (dash).
578 C<value> can be NULL.");
580 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
582 "set the qemu binary",
584 Set the qemu binary that we will use.
586 The default is chosen when the library was compiled by the
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
594 Note that you should call this function as early as possible
595 after creating the handle. This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results. Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
602 ("get_qemu", (RConstString "qemu", []), -1, [],
603 [InitNone, Always, TestRun (
605 "get the qemu binary",
607 Return the current qemu binary.
609 This is always non-NULL. If it wasn't set already, then this will
610 return the default qemu binary name.");
612 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
614 "set the search path",
616 Set the path that libguestfs searches for kernel and initrd.img.
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
621 Setting C<path> to C<NULL> restores the default path.");
623 ("get_path", (RConstString "path", []), -1, [],
624 [InitNone, Always, TestRun (
626 "get the search path",
628 Return the current search path.
630 This is always non-NULL. If it wasn't set already, then this will
631 return the default path.");
633 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635 "add options to kernel command line",
637 This function is used to add additional options to the
638 guest kernel command line.
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
646 ("get_append", (RConstOptString "append", []), -1, [],
647 (* This cannot be tested with the current framework. The
648 * function can return NULL in normal operations, which the
649 * test framework interprets as an error.
652 "get the additional kernel options",
654 Return the additional kernel options which are added to the
655 guest kernel command line.
657 If C<NULL> then no options are added.");
659 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
663 If C<autosync> is true, this enables autosync. Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
671 ("get_autosync", (RBool "autosync", []), -1, [],
672 [InitNone, Always, TestRun (
673 [["get_autosync"]])],
676 Get the autosync flag.");
678 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687 ("get_verbose", (RBool "verbose", []), -1, [],
691 This returns the verbose messages flag.");
693 ("is_ready", (RBool "ready", []), -1, [],
694 [InitNone, Always, TestOutputTrue (
696 "is ready to accept commands",
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
701 For more information on states, see L<guestfs(3)>.");
703 ("is_config", (RBool "config", []), -1, [],
704 [InitNone, Always, TestOutputFalse (
706 "is in configuration state",
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
711 For more information on states, see L<guestfs(3)>.");
713 ("is_launching", (RBool "launching", []), -1, [],
714 [InitNone, Always, TestOutputFalse (
715 [["is_launching"]])],
716 "is launching subprocess",
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
721 For more information on states, see L<guestfs(3)>.");
723 ("is_busy", (RBool "busy", []), -1, [],
724 [InitNone, Always, TestOutputFalse (
726 "is busy processing a command",
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
731 For more information on states, see L<guestfs(3)>.");
733 ("get_state", (RInt "state", []), -1, [],
735 "get the current state",
737 This returns the current state as an opaque integer. This is
738 only useful for printing debug and internal error messages.
740 For more information on states, see L<guestfs(3)>.");
742 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743 [InitNone, Always, TestOutputInt (
744 [["set_memsize"; "500"];
745 ["get_memsize"]], 500)],
746 "set memory allocated to the qemu subprocess",
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess. This only has any effect if called before
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
759 ("get_memsize", (RInt "memsize", []), -1, [],
760 [InitNone, Always, TestOutputIntOp (
761 [["get_memsize"]], ">=", 256)],
762 "get memory allocated to the qemu subprocess",
764 This gets the memory size in megabytes allocated to the
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
774 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775 [InitNone, Always, TestOutputIntOp (
776 [["get_pid"]], ">=", 1)],
777 "get PID of qemu subprocess",
779 Return the process ID of the qemu subprocess. If there is no
780 qemu subprocess, then this will return an error.
782 This is an internal call used for debugging and testing.");
784 ("version", (RStruct ("version", "version"), []), -1, [],
785 [InitNone, Always, TestOutputStruct (
786 [["version"]], [CompareWithInt ("major", 1)])],
787 "get the library version number",
789 Return the libguestfs version number that the program is linked
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against. You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
797 This call was added in version C<1.0.58>. In previous
798 versions of libguestfs there was no way to get the version
799 number. From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then 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 I<Note:> Don't use this call to test for availability
812 of features. Distro backports makes this unreliable. Use
813 C<guestfs_available> instead.");
815 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816 [InitNone, Always, TestOutputTrue (
817 [["set_selinux"; "true"];
819 "set SELinux enabled or disabled at appliance boot",
821 This sets the selinux flag that is passed to the appliance
822 at boot time. The default is C<selinux=0> (disabled).
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
830 ("get_selinux", (RBool "selinux", []), -1, [],
832 "get SELinux enabled flag",
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
840 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841 [InitNone, Always, TestOutputFalse (
842 [["set_trace"; "false"];
844 "enable or disable command traces",
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish. In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
860 ("get_trace", (RBool "trace", []), -1, [],
862 "get command trace enabled flag",
864 Return the command trace flag.");
866 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867 [InitNone, Always, TestOutputFalse (
868 [["set_direct"; "false"];
870 "enable or disable direct appliance mode",
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
880 You probably don't want to use this unless you know what you
883 The default is disabled.");
885 ("get_direct", (RBool "direct", []), -1, [],
887 "get direct appliance mode flag",
889 Return the direct appliance mode flag.");
891 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892 [InitNone, Always, TestOutputTrue (
893 [["set_recovery_proc"; "true"];
894 ["get_recovery_proc"]])],
895 "enable or disable the recovery process",
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process. The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself). In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
911 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
913 "get recovery process enabled flag",
915 Return the recovery process enabled flag.");
917 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919 "add a drive specifying the QEMU block emulation to use",
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
924 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
926 "add a drive read-only specifying the QEMU block emulation to use",
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
933 (* daemon_functions are any functions which cause some action
934 * to take place in the daemon.
937 let daemon_functions = [
938 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939 [InitEmpty, Always, TestOutput (
940 [["part_disk"; "/dev/sda"; "mbr"];
941 ["mkfs"; "ext2"; "/dev/sda1"];
942 ["mount"; "/dev/sda1"; "/"];
943 ["write_file"; "/new"; "new file contents"; "0"];
944 ["cat"; "/new"]], "new file contents")],
945 "mount a guest disk at a position in the filesystem",
947 Mount a guest disk at a position in the filesystem. Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest. If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
953 The rules are the same as for L<mount(2)>: A filesystem must
954 first be mounted on C</> before others can be mounted. Other
955 filesystems can only be mounted on directories which already
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
964 ("sync", (RErr, []), 2, [],
965 [ InitEmpty, Always, TestRun [["sync"]]],
966 "sync disks, writes are flushed through to the disk image",
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
974 ("touch", (RErr, [Pathname "path"]), 3, [],
975 [InitBasicFS, Always, TestOutputTrue (
977 ["exists"; "/new"]])],
978 "update file timestamps or create a new file",
980 Touch acts like the L<touch(1)> command. It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
984 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985 [InitISOFS, Always, TestOutput (
986 [["cat"; "/known-2"]], "abcdef\n")],
987 "list the contents of a file",
989 Return the contents of the file named C<path>.
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string). For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
996 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997 [], (* XXX Tricky to test because it depends on the exact format
998 * of the 'ls -l' command, which changes between F10 and F11.
1000 "list the files in a directory (long format)",
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1005 This command is mostly useful for interactive sessions. It
1006 is I<not> intended that you try to parse the output string.");
1008 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009 [InitBasicFS, Always, TestOutputList (
1011 ["touch"; "/newer"];
1012 ["touch"; "/newest"];
1013 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014 "list the files in a directory",
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd). The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1020 This command is mostly useful for interactive sessions. Programs
1021 should probably use C<guestfs_readdir> instead.");
1023 ("list_devices", (RStringList "devices", []), 7, [],
1024 [InitEmpty, Always, TestOutputListOfDevices (
1025 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026 "list the block devices",
1028 List all the block devices.
1030 The full block device names are returned, eg. C</dev/sda>");
1032 ("list_partitions", (RStringList "partitions", []), 8, [],
1033 [InitBasicFS, Always, TestOutputListOfDevices (
1034 [["list_partitions"]], ["/dev/sda1"]);
1035 InitEmpty, Always, TestOutputListOfDevices (
1036 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038 "list the partitions",
1040 List all the partitions detected on all block devices.
1042 The full partition device names are returned, eg. C</dev/sda1>
1044 This does not return logical volumes. For that you will need to
1045 call C<guestfs_lvs>.");
1047 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049 [["pvs"]], ["/dev/sda1"]);
1050 InitEmpty, Always, TestOutputListOfDevices (
1051 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052 ["pvcreate"; "/dev/sda1"];
1053 ["pvcreate"; "/dev/sda2"];
1054 ["pvcreate"; "/dev/sda3"];
1055 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056 "list the LVM physical volumes (PVs)",
1058 List all the physical volumes detected. This is the equivalent
1059 of the L<pvs(8)> command.
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1064 See also C<guestfs_pvs_full>.");
1066 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067 [InitBasicFSonLVM, Always, TestOutputList (
1069 InitEmpty, Always, TestOutputList (
1070 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071 ["pvcreate"; "/dev/sda1"];
1072 ["pvcreate"; "/dev/sda2"];
1073 ["pvcreate"; "/dev/sda3"];
1074 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075 ["vgcreate"; "VG2"; "/dev/sda3"];
1076 ["vgs"]], ["VG1"; "VG2"])],
1077 "list the LVM volume groups (VGs)",
1079 List all the volumes groups detected. This is the equivalent
1080 of the L<vgs(8)> command.
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1085 See also C<guestfs_vgs_full>.");
1087 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088 [InitBasicFSonLVM, Always, TestOutputList (
1089 [["lvs"]], ["/dev/VG/LV"]);
1090 InitEmpty, Always, TestOutputList (
1091 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092 ["pvcreate"; "/dev/sda1"];
1093 ["pvcreate"; "/dev/sda2"];
1094 ["pvcreate"; "/dev/sda3"];
1095 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096 ["vgcreate"; "VG2"; "/dev/sda3"];
1097 ["lvcreate"; "LV1"; "VG1"; "50"];
1098 ["lvcreate"; "LV2"; "VG1"; "50"];
1099 ["lvcreate"; "LV3"; "VG2"; "50"];
1100 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101 "list the LVM logical volumes (LVs)",
1103 List all the logical volumes detected. This is the equivalent
1104 of the L<lvs(8)> command.
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1109 See also C<guestfs_lvs_full>.");
1111 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112 [], (* XXX how to test? *)
1113 "list the LVM physical volumes (PVs)",
1115 List all the physical volumes detected. This is the equivalent
1116 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1118 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119 [], (* XXX how to test? *)
1120 "list the LVM volume groups (VGs)",
1122 List all the volumes groups detected. This is the equivalent
1123 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1125 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM logical volumes (LVs)",
1129 List all the logical volumes detected. This is the equivalent
1130 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1132 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133 [InitISOFS, Always, TestOutputList (
1134 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135 InitISOFS, Always, TestOutputList (
1136 [["read_lines"; "/empty"]], [])],
1137 "read file as lines",
1139 Return the contents of the file named C<path>.
1141 The file contents are returned as a list of lines. Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line). For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1149 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150 [], (* XXX Augeas code needs tests. *)
1151 "create a new Augeas handle",
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1157 You must call this before using any other C<guestfs_aug_*>
1160 C<root> is the filesystem root. C<root> must not be NULL,
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1169 =item C<AUG_SAVE_BACKUP> = 1
1171 Keep the original file with a C<.augsave> extension.
1173 =item C<AUG_SAVE_NEWFILE> = 2
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1178 =item C<AUG_TYPE_CHECK> = 4
1180 Typecheck lenses (can be expensive).
1182 =item C<AUG_NO_STDINC> = 8
1184 Do not use standard load path for modules.
1186 =item C<AUG_SAVE_NOOP> = 16
1188 Make save a no-op, just record what would have been changed.
1190 =item C<AUG_NO_LOAD> = 32
1192 Do not load the tree in C<guestfs_aug_init>.
1196 To close the handle, you can call C<guestfs_aug_close>.
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1200 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201 [], (* XXX Augeas code needs tests. *)
1202 "close the current Augeas handle",
1204 Close the current Augeas handle and free up any resources
1205 used by it. After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1209 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210 [], (* XXX Augeas code needs tests. *)
1211 "define an Augeas variable",
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1220 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221 [], (* XXX Augeas code needs tests. *)
1222 "define an Augeas node",
1224 Defines a variable C<name> whose value is the result of
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1235 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236 [], (* XXX Augeas code needs tests. *)
1237 "look up the value of an Augeas path",
1239 Look up the value associated with C<path>. If C<path>
1240 matches exactly one node, the C<value> is returned.");
1242 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "set Augeas path to value",
1246 Set the value associated with C<path> to C<val>.
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL. Due to an oversight in the libguestfs API
1250 you cannot do that with this call. Instead you must use the
1251 C<guestfs_aug_clear> call.");
1253 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254 [], (* XXX Augeas code needs tests. *)
1255 "insert a sibling Augeas node",
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1265 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266 [], (* XXX Augeas code needs tests. *)
1267 "remove an Augeas path",
1269 Remove C<path> and all of its children.
1271 On success this returns the number of entries which were removed.");
1273 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274 [], (* XXX Augeas code needs tests. *)
1277 Move the node C<src> to C<dest>. C<src> must match exactly
1278 one node. C<dest> is overwritten if it exists.");
1280 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1282 "return Augeas nodes which match augpath",
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1288 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289 [], (* XXX Augeas code needs tests. *)
1290 "write all pending Augeas changes to disk",
1292 This writes all pending changes to disk.
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1297 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298 [], (* XXX Augeas code needs tests. *)
1299 "load files into the tree",
1301 Load files into the tree.
1303 See C<aug_load> in the Augeas documentation for the full gory
1306 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307 [], (* XXX Augeas code needs tests. *)
1308 "list Augeas nodes under augpath",
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1313 ("rm", (RErr, [Pathname "path"]), 29, [],
1314 [InitBasicFS, Always, TestRun
1317 InitBasicFS, Always, TestLastFail
1319 InitBasicFS, Always, TestLastFail
1324 Remove the single file C<path>.");
1326 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327 [InitBasicFS, Always, TestRun
1330 InitBasicFS, Always, TestLastFail
1331 [["rmdir"; "/new"]];
1332 InitBasicFS, Always, TestLastFail
1334 ["rmdir"; "/new"]]],
1335 "remove a directory",
1337 Remove the single directory C<path>.");
1339 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340 [InitBasicFS, Always, TestOutputFalse
1342 ["mkdir"; "/new/foo"];
1343 ["touch"; "/new/foo/bar"];
1345 ["exists"; "/new"]]],
1346 "remove a file or directory recursively",
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory. This is like the C<rm -rf> shell
1352 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353 [InitBasicFS, Always, TestOutputTrue
1355 ["is_dir"; "/new"]];
1356 InitBasicFS, Always, TestLastFail
1357 [["mkdir"; "/new/foo/bar"]]],
1358 "create a directory",
1360 Create a directory named C<path>.");
1362 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363 [InitBasicFS, Always, TestOutputTrue
1364 [["mkdir_p"; "/new/foo/bar"];
1365 ["is_dir"; "/new/foo/bar"]];
1366 InitBasicFS, Always, TestOutputTrue
1367 [["mkdir_p"; "/new/foo/bar"];
1368 ["is_dir"; "/new/foo"]];
1369 InitBasicFS, Always, TestOutputTrue
1370 [["mkdir_p"; "/new/foo/bar"];
1371 ["is_dir"; "/new"]];
1372 (* Regression tests for RHBZ#503133: *)
1373 InitBasicFS, Always, TestRun
1375 ["mkdir_p"; "/new"]];
1376 InitBasicFS, Always, TestLastFail
1378 ["mkdir_p"; "/new"]]],
1379 "create a directory and parents",
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary. This is like the C<mkdir -p> shell command.");
1384 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385 [], (* XXX Need stat command to test *)
1388 Change the mode (permissions) of C<path> to C<mode>. Only
1389 numeric modes are supported.
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.");
1395 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396 [], (* XXX Need stat command to test *)
1397 "change file owner and group",
1399 Change the file owner to C<owner> and group to C<group>.
1401 Only numeric uid and gid are supported. If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1405 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406 [InitISOFS, Always, TestOutputTrue (
1407 [["exists"; "/empty"]]);
1408 InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/directory"]])],
1410 "test if file or directory exists",
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1417 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418 [InitISOFS, Always, TestOutputTrue (
1419 [["is_file"; "/known-1"]]);
1420 InitISOFS, Always, TestOutputFalse (
1421 [["is_file"; "/directory"]])],
1422 "test if file exists",
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name. Note that it returns false for
1426 other objects like directories.
1428 See also C<guestfs_stat>.");
1430 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431 [InitISOFS, Always, TestOutputFalse (
1432 [["is_dir"; "/known-3"]]);
1433 InitISOFS, Always, TestOutputTrue (
1434 [["is_dir"; "/directory"]])],
1435 "test if file exists",
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name. Note that it returns false for
1439 other objects like files.
1441 See also C<guestfs_stat>.");
1443 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444 [InitEmpty, Always, TestOutputListOfDevices (
1445 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446 ["pvcreate"; "/dev/sda1"];
1447 ["pvcreate"; "/dev/sda2"];
1448 ["pvcreate"; "/dev/sda3"];
1449 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450 "create an LVM physical volume",
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1456 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457 [InitEmpty, Always, TestOutputList (
1458 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459 ["pvcreate"; "/dev/sda1"];
1460 ["pvcreate"; "/dev/sda2"];
1461 ["pvcreate"; "/dev/sda3"];
1462 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463 ["vgcreate"; "VG2"; "/dev/sda3"];
1464 ["vgs"]], ["VG1"; "VG2"])],
1465 "create an LVM volume group",
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1470 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471 [InitEmpty, Always, TestOutputList (
1472 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473 ["pvcreate"; "/dev/sda1"];
1474 ["pvcreate"; "/dev/sda2"];
1475 ["pvcreate"; "/dev/sda3"];
1476 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477 ["vgcreate"; "VG2"; "/dev/sda3"];
1478 ["lvcreate"; "LV1"; "VG1"; "50"];
1479 ["lvcreate"; "LV2"; "VG1"; "50"];
1480 ["lvcreate"; "LV3"; "VG2"; "50"];
1481 ["lvcreate"; "LV4"; "VG2"; "50"];
1482 ["lvcreate"; "LV5"; "VG2"; "50"];
1484 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486 "create an LVM logical volume",
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1491 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492 [InitEmpty, Always, TestOutput (
1493 [["part_disk"; "/dev/sda"; "mbr"];
1494 ["mkfs"; "ext2"; "/dev/sda1"];
1495 ["mount_options"; ""; "/dev/sda1"; "/"];
1496 ["write_file"; "/new"; "new file contents"; "0"];
1497 ["cat"; "/new"]], "new file contents")],
1498 "make a filesystem",
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume). The filesystem type is C<fstype>, for
1504 ("sfdisk", (RErr, [Device "device";
1505 Int "cyls"; Int "heads"; Int "sectors";
1506 StringList "lines"]), 43, [DangerWillRobinson],
1508 "create partitions on a block device",
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1513 C<device> should be a block device, for example C</dev/sda>.
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted. Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1523 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1524 information refer to the L<sfdisk(8)> manpage.
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1533 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534 [InitBasicFS, Always, TestOutput (
1535 [["write_file"; "/new"; "new file contents"; "0"];
1536 ["cat"; "/new"]], "new file contents");
1537 InitBasicFS, Always, TestOutput (
1538 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539 ["cat"; "/new"]], "\nnew file contents\n");
1540 InitBasicFS, Always, TestOutput (
1541 [["write_file"; "/new"; "\n\n"; "0"];
1542 ["cat"; "/new"]], "\n\n");
1543 InitBasicFS, Always, TestOutput (
1544 [["write_file"; "/new"; ""; "0"];
1545 ["cat"; "/new"]], "");
1546 InitBasicFS, Always, TestOutput (
1547 [["write_file"; "/new"; "\n\n\n"; "0"];
1548 ["cat"; "/new"]], "\n\n\n");
1549 InitBasicFS, Always, TestOutput (
1550 [["write_file"; "/new"; "\n"; "0"];
1551 ["cat"; "/new"]], "\n")],
1554 This call creates a file called C<path>. The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version. In the meantime
1565 use C<guestfs_upload>.");
1567 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568 [InitEmpty, Always, TestOutputListOfDevices (
1569 [["part_disk"; "/dev/sda"; "mbr"];
1570 ["mkfs"; "ext2"; "/dev/sda1"];
1571 ["mount_options"; ""; "/dev/sda1"; "/"];
1572 ["mounts"]], ["/dev/sda1"]);
1573 InitEmpty, Always, TestOutputList (
1574 [["part_disk"; "/dev/sda"; "mbr"];
1575 ["mkfs"; "ext2"; "/dev/sda1"];
1576 ["mount_options"; ""; "/dev/sda1"; "/"];
1579 "unmount a filesystem",
1581 This unmounts the given filesystem. The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1585 ("mounts", (RStringList "devices", []), 46, [],
1586 [InitBasicFS, Always, TestOutputListOfDevices (
1587 [["mounts"]], ["/dev/sda1"])],
1588 "show mounted filesystems",
1590 This returns the list of currently mounted filesystems. It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1593 Some internal mounts are not shown.
1595 See also: C<guestfs_mountpoints>");
1597 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598 [InitBasicFS, Always, TestOutputList (
1601 (* check that umount_all can unmount nested mounts correctly: *)
1602 InitEmpty, Always, TestOutputList (
1603 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604 ["mkfs"; "ext2"; "/dev/sda1"];
1605 ["mkfs"; "ext2"; "/dev/sda2"];
1606 ["mkfs"; "ext2"; "/dev/sda3"];
1607 ["mount_options"; ""; "/dev/sda1"; "/"];
1609 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610 ["mkdir"; "/mp1/mp2"];
1611 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612 ["mkdir"; "/mp1/mp2/mp3"];
1615 "unmount all filesystems",
1617 This unmounts all mounted filesystems.
1619 Some internal mounts are not unmounted by this call.");
1621 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1623 "remove all LVM LVs, VGs and PVs",
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1628 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629 [InitISOFS, Always, TestOutput (
1630 [["file"; "/empty"]], "empty");
1631 InitISOFS, Always, TestOutput (
1632 [["file"; "/known-1"]], "ASCII text");
1633 InitISOFS, Always, TestLastFail (
1634 [["file"; "/notexists"]])],
1635 "determine file type",
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file. This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1641 This call will also transparently look inside various types
1644 The exact command which runs is C<file -zbsL path>. Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1648 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649 [InitBasicFS, Always, TestOutput (
1650 [["upload"; "test-command"; "/test-command"];
1651 ["chmod"; "0o755"; "/test-command"];
1652 ["command"; "/test-command 1"]], "Result1");
1653 InitBasicFS, Always, TestOutput (
1654 [["upload"; "test-command"; "/test-command"];
1655 ["chmod"; "0o755"; "/test-command"];
1656 ["command"; "/test-command 2"]], "Result2\n");
1657 InitBasicFS, Always, TestOutput (
1658 [["upload"; "test-command"; "/test-command"];
1659 ["chmod"; "0o755"; "/test-command"];
1660 ["command"; "/test-command 3"]], "\nResult3");
1661 InitBasicFS, Always, TestOutput (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command"; "/test-command 4"]], "\nResult4\n");
1665 InitBasicFS, Always, TestOutput (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command"; "/test-command 5"]], "\nResult5\n\n");
1669 InitBasicFS, Always, TestOutput (
1670 [["upload"; "test-command"; "/test-command"];
1671 ["chmod"; "0o755"; "/test-command"];
1672 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673 InitBasicFS, Always, TestOutput (
1674 [["upload"; "test-command"; "/test-command"];
1675 ["chmod"; "0o755"; "/test-command"];
1676 ["command"; "/test-command 7"]], "");
1677 InitBasicFS, Always, TestOutput (
1678 [["upload"; "test-command"; "/test-command"];
1679 ["chmod"; "0o755"; "/test-command"];
1680 ["command"; "/test-command 8"]], "\n");
1681 InitBasicFS, Always, TestOutput (
1682 [["upload"; "test-command"; "/test-command"];
1683 ["chmod"; "0o755"; "/test-command"];
1684 ["command"; "/test-command 9"]], "\n\n");
1685 InitBasicFS, Always, TestOutput (
1686 [["upload"; "test-command"; "/test-command"];
1687 ["chmod"; "0o755"; "/test-command"];
1688 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689 InitBasicFS, Always, TestOutput (
1690 [["upload"; "test-command"; "/test-command"];
1691 ["chmod"; "0o755"; "/test-command"];
1692 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693 InitBasicFS, Always, TestLastFail (
1694 [["upload"; "test-command"; "/test-command"];
1695 ["chmod"; "0o755"; "/test-command"];
1696 ["command"; "/test-command"]])],
1697 "run a command from the guest filesystem",
1699 This call runs a command from the guest filesystem. The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters. The list must be
1707 non-empty (ie. must contain a program name). Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1711 The return value is anything printed to I<stdout> by
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message. The error message
1716 string is the content of I<stderr> from the command.
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>. If you require a program from
1720 another location, you should provide the full path in the
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places. It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1729 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730 [InitBasicFS, Always, TestOutputList (
1731 [["upload"; "test-command"; "/test-command"];
1732 ["chmod"; "0o755"; "/test-command"];
1733 ["command_lines"; "/test-command 1"]], ["Result1"]);
1734 InitBasicFS, Always, TestOutputList (
1735 [["upload"; "test-command"; "/test-command"];
1736 ["chmod"; "0o755"; "/test-command"];
1737 ["command_lines"; "/test-command 2"]], ["Result2"]);
1738 InitBasicFS, Always, TestOutputList (
1739 [["upload"; "test-command"; "/test-command"];
1740 ["chmod"; "0o755"; "/test-command"];
1741 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742 InitBasicFS, Always, TestOutputList (
1743 [["upload"; "test-command"; "/test-command"];
1744 ["chmod"; "0o755"; "/test-command"];
1745 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746 InitBasicFS, Always, TestOutputList (
1747 [["upload"; "test-command"; "/test-command"];
1748 ["chmod"; "0o755"; "/test-command"];
1749 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750 InitBasicFS, Always, TestOutputList (
1751 [["upload"; "test-command"; "/test-command"];
1752 ["chmod"; "0o755"; "/test-command"];
1753 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754 InitBasicFS, Always, TestOutputList (
1755 [["upload"; "test-command"; "/test-command"];
1756 ["chmod"; "0o755"; "/test-command"];
1757 ["command_lines"; "/test-command 7"]], []);
1758 InitBasicFS, Always, TestOutputList (
1759 [["upload"; "test-command"; "/test-command"];
1760 ["chmod"; "0o755"; "/test-command"];
1761 ["command_lines"; "/test-command 8"]], [""]);
1762 InitBasicFS, Always, TestOutputList (
1763 [["upload"; "test-command"; "/test-command"];
1764 ["chmod"; "0o755"; "/test-command"];
1765 ["command_lines"; "/test-command 9"]], ["";""]);
1766 InitBasicFS, Always, TestOutputList (
1767 [["upload"; "test-command"; "/test-command"];
1768 ["chmod"; "0o755"; "/test-command"];
1769 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770 InitBasicFS, Always, TestOutputList (
1771 [["upload"; "test-command"; "/test-command"];
1772 ["chmod"; "0o755"; "/test-command"];
1773 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774 "run a command, returning lines",
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1779 See also: C<guestfs_sh_lines>");
1781 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782 [InitISOFS, Always, TestOutputStruct (
1783 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784 "get file information",
1786 Returns file information for the given C<path>.
1788 This is the same as the C<stat(2)> system call.");
1790 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791 [InitISOFS, Always, TestOutputStruct (
1792 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793 "get file information for a symbolic link",
1795 Returns file information for the given C<path>.
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1801 This is the same as the C<lstat(2)> system call.");
1803 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804 [InitISOFS, Always, TestOutputStruct (
1805 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806 "get file system statistics",
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1812 This is the same as the C<statvfs(2)> system call.");
1814 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1816 "get ext2/ext3/ext4 superblock details",
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1821 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1822 manpage for more details. The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1826 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827 [InitEmpty, Always, TestOutputTrue (
1828 [["blockdev_setro"; "/dev/sda"];
1829 ["blockdev_getro"; "/dev/sda"]])],
1830 "set block device to read-only",
1832 Sets the block device named C<device> to read-only.
1834 This uses the L<blockdev(8)> command.");
1836 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837 [InitEmpty, Always, TestOutputFalse (
1838 [["blockdev_setrw"; "/dev/sda"];
1839 ["blockdev_getro"; "/dev/sda"]])],
1840 "set block device to read-write",
1842 Sets the block device named C<device> to read-write.
1844 This uses the L<blockdev(8)> command.");
1846 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847 [InitEmpty, Always, TestOutputTrue (
1848 [["blockdev_setro"; "/dev/sda"];
1849 ["blockdev_getro"; "/dev/sda"]])],
1850 "is block device set to read-only",
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1855 This uses the L<blockdev(8)> command.");
1857 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858 [InitEmpty, Always, TestOutputInt (
1859 [["blockdev_getss"; "/dev/sda"]], 512)],
1860 "get sectorsize of block device",
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 This uses the L<blockdev(8)> command.");
1870 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871 [InitEmpty, Always, TestOutputInt (
1872 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873 "get blocksize of block device",
1875 This returns the block size of a device.
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1884 "set blocksize of block device",
1886 This sets the block size of a device.
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1891 This uses the L<blockdev(8)> command.");
1893 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894 [InitEmpty, Always, TestOutputInt (
1895 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896 "get total size of device in 512-byte sectors",
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1905 This uses the L<blockdev(8)> command.");
1907 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908 [InitEmpty, Always, TestOutputInt (
1909 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910 "get total size of device in bytes",
1912 This returns the size of the device in bytes.
1914 See also C<guestfs_blockdev_getsz>.
1916 This uses the L<blockdev(8)> command.");
1918 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919 [InitEmpty, Always, TestRun
1920 [["blockdev_flushbufs"; "/dev/sda"]]],
1921 "flush device buffers",
1923 This tells the kernel to flush internal buffers associated
1926 This uses the L<blockdev(8)> command.");
1928 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929 [InitEmpty, Always, TestRun
1930 [["blockdev_rereadpt"; "/dev/sda"]]],
1931 "reread partition table",
1933 Reread the partition table on C<device>.
1935 This uses the L<blockdev(8)> command.");
1937 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938 [InitBasicFS, Always, TestOutput (
1939 (* Pick a file from cwd which isn't likely to change. *)
1940 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941 ["checksum"; "md5"; "/COPYING.LIB"]],
1942 Digest.to_hex (Digest.file "COPYING.LIB"))],
1943 "upload a file from the local machine",
1945 Upload local file C<filename> to C<remotefilename> on the
1948 C<filename> can also be a named pipe.
1950 See also C<guestfs_download>.");
1952 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953 [InitBasicFS, Always, TestOutput (
1954 (* Pick a file from cwd which isn't likely to change. *)
1955 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957 ["upload"; "testdownload.tmp"; "/upload"];
1958 ["checksum"; "md5"; "/upload"]],
1959 Digest.to_hex (Digest.file "COPYING.LIB"))],
1960 "download a file to the local machine",
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1965 C<filename> can also be a named pipe.
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1969 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970 [InitISOFS, Always, TestOutput (
1971 [["checksum"; "crc"; "/known-3"]], "2891671662");
1972 InitISOFS, Always, TestLastFail (
1973 [["checksum"; "crc"; "/notexists"]]);
1974 InitISOFS, Always, TestOutput (
1975 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986 "compute MD5, SHAx or CRC checksum of file",
1988 This call computes the MD5, SHAx or CRC checksum of the
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2003 Compute the MD5 hash (using the C<md5sum> program).
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2027 The checksum is returned as a printable string.");
2029 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030 [InitBasicFS, Always, TestOutput (
2031 [["tar_in"; "../images/helloworld.tar"; "/"];
2032 ["cat"; "/hello"]], "hello\n")],
2033 "unpack tarfile to directory",
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2041 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2043 "pack directory into tarfile",
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2051 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2052 [InitBasicFS, Always, TestOutput (
2053 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054 ["cat"; "/hello"]], "hello\n")],
2055 "unpack compressed tarball to directory",
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2062 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2064 "pack directory into compressed tarball",
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2071 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072 [InitBasicFS, Always, TestLastFail (
2074 ["mount_ro"; "/dev/sda1"; "/"];
2075 ["touch"; "/new"]]);
2076 InitBasicFS, Always, TestOutput (
2077 [["write_file"; "/new"; "data"; "0"];
2079 ["mount_ro"; "/dev/sda1"; "/"];
2080 ["cat"; "/new"]], "data")],
2081 "mount a guest disk, read-only",
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2086 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2088 "mount a guest disk with mount options",
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.");
2094 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2096 "mount a guest disk with mount options and vfstype",
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2102 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2104 "debugging and internals",
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2110 There is no comprehensive help for this command. You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2114 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115 [InitEmpty, Always, TestOutputList (
2116 [["part_disk"; "/dev/sda"; "mbr"];
2117 ["pvcreate"; "/dev/sda1"];
2118 ["vgcreate"; "VG"; "/dev/sda1"];
2119 ["lvcreate"; "LV1"; "VG"; "50"];
2120 ["lvcreate"; "LV2"; "VG"; "50"];
2121 ["lvremove"; "/dev/VG/LV1"];
2122 ["lvs"]], ["/dev/VG/LV2"]);
2123 InitEmpty, Always, TestOutputList (
2124 [["part_disk"; "/dev/sda"; "mbr"];
2125 ["pvcreate"; "/dev/sda1"];
2126 ["vgcreate"; "VG"; "/dev/sda1"];
2127 ["lvcreate"; "LV1"; "VG"; "50"];
2128 ["lvcreate"; "LV2"; "VG"; "50"];
2129 ["lvremove"; "/dev/VG"];
2131 InitEmpty, Always, TestOutputList (
2132 [["part_disk"; "/dev/sda"; "mbr"];
2133 ["pvcreate"; "/dev/sda1"];
2134 ["vgcreate"; "VG"; "/dev/sda1"];
2135 ["lvcreate"; "LV1"; "VG"; "50"];
2136 ["lvcreate"; "LV2"; "VG"; "50"];
2137 ["lvremove"; "/dev/VG"];
2139 "remove an LVM logical volume",
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2147 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148 [InitEmpty, Always, TestOutputList (
2149 [["part_disk"; "/dev/sda"; "mbr"];
2150 ["pvcreate"; "/dev/sda1"];
2151 ["vgcreate"; "VG"; "/dev/sda1"];
2152 ["lvcreate"; "LV1"; "VG"; "50"];
2153 ["lvcreate"; "LV2"; "VG"; "50"];
2156 InitEmpty, Always, TestOutputList (
2157 [["part_disk"; "/dev/sda"; "mbr"];
2158 ["pvcreate"; "/dev/sda1"];
2159 ["vgcreate"; "VG"; "/dev/sda1"];
2160 ["lvcreate"; "LV1"; "VG"; "50"];
2161 ["lvcreate"; "LV2"; "VG"; "50"];
2164 "remove an LVM volume group",
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2168 This also forcibly removes all logical volumes in the volume
2171 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172 [InitEmpty, Always, TestOutputListOfDevices (
2173 [["part_disk"; "/dev/sda"; "mbr"];
2174 ["pvcreate"; "/dev/sda1"];
2175 ["vgcreate"; "VG"; "/dev/sda1"];
2176 ["lvcreate"; "LV1"; "VG"; "50"];
2177 ["lvcreate"; "LV2"; "VG"; "50"];
2179 ["pvremove"; "/dev/sda1"];
2181 InitEmpty, Always, TestOutputListOfDevices (
2182 [["part_disk"; "/dev/sda"; "mbr"];
2183 ["pvcreate"; "/dev/sda1"];
2184 ["vgcreate"; "VG"; "/dev/sda1"];
2185 ["lvcreate"; "LV1"; "VG"; "50"];
2186 ["lvcreate"; "LV2"; "VG"; "50"];
2188 ["pvremove"; "/dev/sda1"];
2190 InitEmpty, Always, TestOutputListOfDevices (
2191 [["part_disk"; "/dev/sda"; "mbr"];
2192 ["pvcreate"; "/dev/sda1"];
2193 ["vgcreate"; "VG"; "/dev/sda1"];
2194 ["lvcreate"; "LV1"; "VG"; "50"];
2195 ["lvcreate"; "LV2"; "VG"; "50"];
2197 ["pvremove"; "/dev/sda1"];
2199 "remove an LVM physical volume",
2201 This wipes a physical volume C<device> so that LVM will no longer
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2208 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209 [InitBasicFS, Always, TestOutput (
2210 [["set_e2label"; "/dev/sda1"; "testlabel"];
2211 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212 "set the ext2/3/4 filesystem label",
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>. Filesystem labels are limited to
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2221 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2223 "get the ext2/3/4 filesystem label",
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2228 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229 (let uuid = uuidgen () in
2230 [InitBasicFS, Always, TestOutput (
2231 [["set_e2uuid"; "/dev/sda1"; uuid];
2232 ["get_e2uuid"; "/dev/sda1"]], uuid);
2233 InitBasicFS, Always, TestOutput (
2234 [["set_e2uuid"; "/dev/sda1"; "clear"];
2235 ["get_e2uuid"; "/dev/sda1"]], "");
2236 (* We can't predict what UUIDs will be, so just check the commands run. *)
2237 InitBasicFS, Always, TestRun (
2238 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239 InitBasicFS, Always, TestRun (
2240 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241 "set the ext2/3/4 filesystem UUID",
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>. The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2251 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2253 "get the ext2/3/4 filesystem UUID",
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259 [InitBasicFS, Always, TestOutputInt (
2260 [["umount"; "/dev/sda1"];
2261 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262 InitBasicFS, Always, TestOutputInt (
2263 [["umount"; "/dev/sda1"];
2264 ["zero"; "/dev/sda1"];
2265 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266 "run the filesystem checker",
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2271 The returned integer is the status. See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2280 Multiple status codes can be summed together.
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2289 Checking or repairing NTFS volumes is not supported
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2296 ("zero", (RErr, [Device "device"]), 85, [],
2297 [InitBasicFS, Always, TestOutput (
2298 [["umount"; "/dev/sda1"];
2299 ["zero"; "/dev/sda1"];
2300 ["file"; "/dev/sda1"]], "data")],
2301 "write zeroes to the device",
2303 This command writes zeroes over the first few blocks of C<device>.
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device). It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2311 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312 (* Test disabled because grub-install incompatible with virtio-blk driver.
2313 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2315 [InitBasicFS, Disabled, TestOutputTrue (
2316 [["grub_install"; "/"; "/dev/sda1"];
2317 ["is_dir"; "/boot"]])],
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2323 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324 [InitBasicFS, Always, TestOutput (
2325 [["write_file"; "/old"; "file content"; "0"];
2326 ["cp"; "/old"; "/new"];
2327 ["cat"; "/new"]], "file content");
2328 InitBasicFS, Always, TestOutputTrue (
2329 [["write_file"; "/old"; "file content"; "0"];
2330 ["cp"; "/old"; "/new"];
2331 ["is_file"; "/old"]]);
2332 InitBasicFS, Always, TestOutput (
2333 [["write_file"; "/old"; "file content"; "0"];
2335 ["cp"; "/old"; "/dir/new"];
2336 ["cat"; "/dir/new"]], "file content")],
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2342 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343 [InitBasicFS, Always, TestOutput (
2344 [["mkdir"; "/olddir"];
2345 ["mkdir"; "/newdir"];
2346 ["write_file"; "/olddir/file"; "file content"; "0"];
2347 ["cp_a"; "/olddir"; "/newdir"];
2348 ["cat"; "/newdir/olddir/file"]], "file content")],
2349 "copy a file or directory recursively",
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2354 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355 [InitBasicFS, Always, TestOutput (
2356 [["write_file"; "/old"; "file content"; "0"];
2357 ["mv"; "/old"; "/new"];
2358 ["cat"; "/new"]], "file content");
2359 InitBasicFS, Always, TestOutputFalse (
2360 [["write_file"; "/old"; "file content"; "0"];
2361 ["mv"; "/old"; "/new"];
2362 ["is_file"; "/old"]])],
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2368 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369 [InitEmpty, Always, TestRun (
2370 [["drop_caches"; "3"]])],
2371 "drop kernel page cache, dentries and inodes",
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches. The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2378 Setting C<whattodrop> to 3 should drop everything.
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2383 ("dmesg", (RString "kmsgs", []), 91, [],
2384 [InitEmpty, Always, TestRun (
2386 "return kernel messages",
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel. This is sometimes useful for extended
2390 debugging of problems.
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2397 ("ping_daemon", (RErr, []), 92, [],
2398 [InitEmpty, Always, TestRun (
2399 [["ping_daemon"]])],
2400 "ping the guest daemon",
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess. Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2407 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408 [InitBasicFS, Always, TestOutputTrue (
2409 [["write_file"; "/file1"; "contents of a file"; "0"];
2410 ["cp"; "/file1"; "/file2"];
2411 ["equal"; "/file1"; "/file2"]]);
2412 InitBasicFS, Always, TestOutputFalse (
2413 [["write_file"; "/file1"; "contents of a file"; "0"];
2414 ["write_file"; "/file2"; "contents of another file"; "0"];
2415 ["equal"; "/file1"; "/file2"]]);
2416 InitBasicFS, Always, TestLastFail (
2417 [["equal"; "/file1"; "/file2"]])],
2418 "test if two files have equal contents",
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2423 The external L<cmp(1)> program is used for the comparison.");
2425 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426 [InitISOFS, Always, TestOutputList (
2427 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428 InitISOFS, Always, TestOutputList (
2429 [["strings"; "/empty"]], [])],
2430 "print the printable strings in a file",
2432 This runs the L<strings(1)> command on a file and returns
2433 the list of printable strings found.");
2435 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2436 [InitISOFS, Always, TestOutputList (
2437 [["strings_e"; "b"; "/known-5"]], []);
2438 InitBasicFS, Disabled, TestOutputList (
2439 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2440 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2441 "print the printable strings in a file",
2443 This is like the C<guestfs_strings> command, but allows you to
2444 specify the encoding.
2446 See the L<strings(1)> manpage for the full list of encodings.
2448 Commonly useful encodings are C<l> (lower case L) which will
2449 show strings inside Windows/x86 files.
2451 The returned strings are transcoded to UTF-8.");
2453 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2454 [InitISOFS, Always, TestOutput (
2455 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2456 (* Test for RHBZ#501888c2 regression which caused large hexdump
2457 * commands to segfault.
2459 InitISOFS, Always, TestRun (
2460 [["hexdump"; "/100krandom"]])],
2461 "dump a file in hexadecimal",
2463 This runs C<hexdump -C> on the given C<path>. The result is
2464 the human-readable, canonical hex dump of the file.");
2466 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2467 [InitNone, Always, TestOutput (
2468 [["part_disk"; "/dev/sda"; "mbr"];
2469 ["mkfs"; "ext3"; "/dev/sda1"];
2470 ["mount_options"; ""; "/dev/sda1"; "/"];
2471 ["write_file"; "/new"; "test file"; "0"];
2472 ["umount"; "/dev/sda1"];
2473 ["zerofree"; "/dev/sda1"];
2474 ["mount_options"; ""; "/dev/sda1"; "/"];
2475 ["cat"; "/new"]], "test file")],
2476 "zero unused inodes and disk blocks on ext2/3 filesystem",
2478 This runs the I<zerofree> program on C<device>. This program
2479 claims to zero unused inodes and disk blocks on an ext2/3
2480 filesystem, thus making it possible to compress the filesystem
2483 You should B<not> run this program if the filesystem is
2486 It is possible that using this program can damage the filesystem
2487 or data on the filesystem.");
2489 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2491 "resize an LVM physical volume",
2493 This resizes (expands or shrinks) an existing LVM physical
2494 volume to match the new size of the underlying device.");
2496 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2497 Int "cyls"; Int "heads"; Int "sectors";
2498 String "line"]), 99, [DangerWillRobinson],
2500 "modify a single partition on a block device",
2502 This runs L<sfdisk(8)> option to modify just the single
2503 partition C<n> (note: C<n> counts from 1).
2505 For other parameters, see C<guestfs_sfdisk>. You should usually
2506 pass C<0> for the cyls/heads/sectors parameters.
2508 See also: C<guestfs_part_add>");
2510 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2512 "display the partition table",
2514 This displays the partition table on C<device>, in the
2515 human-readable output of the L<sfdisk(8)> command. It is
2516 not intended to be parsed.
2518 See also: C<guestfs_part_list>");
2520 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2522 "display the kernel geometry",
2524 This displays the kernel's idea of the geometry of C<device>.
2526 The result is in human-readable format, and not designed to
2529 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2531 "display the disk geometry from the partition table",
2533 This displays the disk geometry of C<device> read from the
2534 partition table. Especially in the case where the underlying
2535 block device has been resized, this can be different from the
2536 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2538 The result is in human-readable format, and not designed to
2541 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2543 "activate or deactivate all volume groups",
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in all volume groups.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2549 then those devices disappear.
2551 This command is the same as running C<vgchange -a y|n>");
2553 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2555 "activate or deactivate some volume groups",
2557 This command activates or (if C<activate> is false) deactivates
2558 all logical volumes in the listed volume groups C<volgroups>.
2559 If activated, then they are made known to the
2560 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2561 then those devices disappear.
2563 This command is the same as running C<vgchange -a y|n volgroups...>
2565 Note that if C<volgroups> is an empty list then B<all> volume groups
2566 are activated or deactivated.");
2568 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2569 [InitNone, Always, TestOutput (
2570 [["part_disk"; "/dev/sda"; "mbr"];
2571 ["pvcreate"; "/dev/sda1"];
2572 ["vgcreate"; "VG"; "/dev/sda1"];
2573 ["lvcreate"; "LV"; "VG"; "10"];
2574 ["mkfs"; "ext2"; "/dev/VG/LV"];
2575 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2576 ["write_file"; "/new"; "test content"; "0"];
2578 ["lvresize"; "/dev/VG/LV"; "20"];
2579 ["e2fsck_f"; "/dev/VG/LV"];
2580 ["resize2fs"; "/dev/VG/LV"];
2581 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2582 ["cat"; "/new"]], "test content")],
2583 "resize an LVM logical volume",
2585 This resizes (expands or shrinks) an existing LVM logical
2586 volume to C<mbytes>. When reducing, data in the reduced part
2589 ("resize2fs", (RErr, [Device "device"]), 106, [],
2590 [], (* lvresize tests this *)
2591 "resize an ext2/ext3 filesystem",
2593 This resizes an ext2 or ext3 filesystem to match the size of
2594 the underlying device.
2596 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2597 on the C<device> before calling this command. For unknown reasons
2598 C<resize2fs> sometimes gives an error about this and sometimes not.
2599 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2600 calling this function.");
2602 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2603 [InitBasicFS, Always, TestOutputList (
2604 [["find"; "/"]], ["lost+found"]);
2605 InitBasicFS, Always, TestOutputList (
2609 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2610 InitBasicFS, Always, TestOutputList (
2611 [["mkdir_p"; "/a/b/c"];
2612 ["touch"; "/a/b/c/d"];
2613 ["find"; "/a/b/"]], ["c"; "c/d"])],
2614 "find all files and directories",
2616 This command lists out all files and directories, recursively,
2617 starting at C<directory>. It is essentially equivalent to
2618 running the shell command C<find directory -print> but some
2619 post-processing happens on the output, described below.
2621 This returns a list of strings I<without any prefix>. Thus
2622 if the directory structure was:
2628 then the returned list from C<guestfs_find> C</tmp> would be
2636 If C<directory> is not a directory, then this command returns
2639 The returned list is sorted.
2641 See also C<guestfs_find0>.");
2643 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2644 [], (* lvresize tests this *)
2645 "check an ext2/ext3 filesystem",
2647 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2648 filesystem checker on C<device>, noninteractively (C<-p>),
2649 even if the filesystem appears to be clean (C<-f>).
2651 This command is only needed because of C<guestfs_resize2fs>
2652 (q.v.). Normally you should use C<guestfs_fsck>.");
2654 ("sleep", (RErr, [Int "secs"]), 109, [],
2655 [InitNone, Always, TestRun (
2657 "sleep for some seconds",
2659 Sleep for C<secs> seconds.");
2661 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2662 [InitNone, Always, TestOutputInt (
2663 [["part_disk"; "/dev/sda"; "mbr"];
2664 ["mkfs"; "ntfs"; "/dev/sda1"];
2665 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2666 InitNone, Always, TestOutputInt (
2667 [["part_disk"; "/dev/sda"; "mbr"];
2668 ["mkfs"; "ext2"; "/dev/sda1"];
2669 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2670 "probe NTFS volume",
2672 This command runs the L<ntfs-3g.probe(8)> command which probes
2673 an NTFS C<device> for mountability. (Not all NTFS volumes can
2674 be mounted read-write, and some cannot be mounted at all).
2676 C<rw> is a boolean flag. Set it to true if you want to test
2677 if the volume can be mounted read-write. Set it to false if
2678 you want to test if the volume can be mounted read-only.
2680 The return value is an integer which C<0> if the operation
2681 would succeed, or some non-zero value documented in the
2682 L<ntfs-3g.probe(8)> manual page.");
2684 ("sh", (RString "output", [String "command"]), 111, [],
2685 [], (* XXX needs tests *)
2686 "run a command via the shell",
2688 This call runs a command from the guest filesystem via the
2691 This is like C<guestfs_command>, but passes the command to:
2693 /bin/sh -c \"command\"
2695 Depending on the guest's shell, this usually results in
2696 wildcards being expanded, shell expressions being interpolated
2699 All the provisos about C<guestfs_command> apply to this call.");
2701 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2702 [], (* XXX needs tests *)
2703 "run a command via the shell returning lines",
2705 This is the same as C<guestfs_sh>, but splits the result
2706 into a list of lines.
2708 See also: C<guestfs_command_lines>");
2710 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2711 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2712 * code in stubs.c, since all valid glob patterns must start with "/".
2713 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2715 [InitBasicFS, Always, TestOutputList (
2716 [["mkdir_p"; "/a/b/c"];
2717 ["touch"; "/a/b/c/d"];
2718 ["touch"; "/a/b/c/e"];
2719 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2720 InitBasicFS, Always, TestOutputList (
2721 [["mkdir_p"; "/a/b/c"];
2722 ["touch"; "/a/b/c/d"];
2723 ["touch"; "/a/b/c/e"];
2724 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2725 InitBasicFS, Always, TestOutputList (
2726 [["mkdir_p"; "/a/b/c"];
2727 ["touch"; "/a/b/c/d"];
2728 ["touch"; "/a/b/c/e"];
2729 ["glob_expand"; "/a/*/x/*"]], [])],
2730 "expand a wildcard path",
2732 This command searches for all the pathnames matching
2733 C<pattern> according to the wildcard expansion rules
2736 If no paths match, then this returns an empty list
2737 (note: not an error).
2739 It is just a wrapper around the C L<glob(3)> function
2740 with flags C<GLOB_MARK|GLOB_BRACE>.
2741 See that manual page for more details.");
2743 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2744 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2745 [["scrub_device"; "/dev/sdc"]])],
2746 "scrub (securely wipe) a device",
2748 This command writes patterns over C<device> to make data retrieval
2751 It is an interface to the L<scrub(1)> program. See that
2752 manual page for more details.");
2754 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2755 [InitBasicFS, Always, TestRun (
2756 [["write_file"; "/file"; "content"; "0"];
2757 ["scrub_file"; "/file"]])],
2758 "scrub (securely wipe) a file",
2760 This command writes patterns over a file to make data retrieval
2763 The file is I<removed> after scrubbing.
2765 It is an interface to the L<scrub(1)> program. See that
2766 manual page for more details.");
2768 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2769 [], (* XXX needs testing *)
2770 "scrub (securely wipe) free space",
2772 This command creates the directory C<dir> and then fills it
2773 with files until the filesystem is full, and scrubs the files
2774 as for C<guestfs_scrub_file>, and deletes them.
2775 The intention is to scrub any free space on the partition
2778 It is an interface to the L<scrub(1)> program. See that
2779 manual page for more details.");
2781 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2782 [InitBasicFS, Always, TestRun (
2784 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2785 "create a temporary directory",
2787 This command creates a temporary directory. The
2788 C<template> parameter should be a full pathname for the
2789 temporary directory name with the final six characters being
2792 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2793 the second one being suitable for Windows filesystems.
2795 The name of the temporary directory that was created
2798 The temporary directory is created with mode 0700
2799 and is owned by root.
2801 The caller is responsible for deleting the temporary
2802 directory and its contents after use.
2804 See also: L<mkdtemp(3)>");
2806 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2807 [InitISOFS, Always, TestOutputInt (
2808 [["wc_l"; "/10klines"]], 10000)],
2809 "count lines in a file",
2811 This command counts the lines in a file, using the
2812 C<wc -l> external command.");
2814 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2815 [InitISOFS, Always, TestOutputInt (
2816 [["wc_w"; "/10klines"]], 10000)],
2817 "count words in a file",
2819 This command counts the words in a file, using the
2820 C<wc -w> external command.");
2822 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2823 [InitISOFS, Always, TestOutputInt (
2824 [["wc_c"; "/100kallspaces"]], 102400)],
2825 "count characters in a file",
2827 This command counts the characters in a file, using the
2828 C<wc -c> external command.");
2830 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2831 [InitISOFS, Always, TestOutputList (
2832 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2833 "return first 10 lines of a file",
2835 This command returns up to the first 10 lines of a file as
2836 a list of strings.");
2838 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2839 [InitISOFS, Always, TestOutputList (
2840 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2841 InitISOFS, Always, TestOutputList (
2842 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843 InitISOFS, Always, TestOutputList (
2844 [["head_n"; "0"; "/10klines"]], [])],
2845 "return first N lines of a file",
2847 If the parameter C<nrlines> is a positive number, this returns the first
2848 C<nrlines> lines of the file C<path>.
2850 If the parameter C<nrlines> is a negative number, this returns lines
2851 from the file C<path>, excluding the last C<nrlines> lines.
2853 If the parameter C<nrlines> is zero, this returns an empty list.");
2855 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2856 [InitISOFS, Always, TestOutputList (
2857 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2858 "return last 10 lines of a file",
2860 This command returns up to the last 10 lines of a file as
2861 a list of strings.");
2863 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2864 [InitISOFS, Always, TestOutputList (
2865 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2866 InitISOFS, Always, TestOutputList (
2867 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868 InitISOFS, Always, TestOutputList (
2869 [["tail_n"; "0"; "/10klines"]], [])],
2870 "return last N lines of a file",
2872 If the parameter C<nrlines> is a positive number, this returns the last
2873 C<nrlines> lines of the file C<path>.
2875 If the parameter C<nrlines> is a negative number, this returns lines
2876 from the file C<path>, starting with the C<-nrlines>th line.
2878 If the parameter C<nrlines> is zero, this returns an empty list.");
2880 ("df", (RString "output", []), 125, [],
2881 [], (* XXX Tricky to test because it depends on the exact format
2882 * of the 'df' command and other imponderables.
2884 "report file system disk space usage",
2886 This command runs the C<df> command to report disk space used.
2888 This command is mostly useful for interactive sessions. It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2892 ("df_h", (RString "output", []), 126, [],
2893 [], (* XXX Tricky to test because it depends on the exact format
2894 * of the 'df' command and other imponderables.
2896 "report file system disk space usage (human readable)",
2898 This command runs the C<df -h> command to report disk space used
2899 in human-readable format.
2901 This command is mostly useful for interactive sessions. It
2902 is I<not> intended that you try to parse the output string.
2903 Use C<statvfs> from programs.");
2905 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2906 [InitISOFS, Always, TestOutputInt (
2907 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2908 "estimate file space usage",
2910 This command runs the C<du -s> command to estimate file space
2913 C<path> can be a file or a directory. If C<path> is a directory
2914 then the estimate includes the contents of the directory and all
2915 subdirectories (recursively).
2917 The result is the estimated size in I<kilobytes>
2918 (ie. units of 1024 bytes).");
2920 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2921 [InitISOFS, Always, TestOutputList (
2922 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2923 "list files in an initrd",
2925 This command lists out files contained in an initrd.
2927 The files are listed without any initial C</> character. The
2928 files are listed in the order they appear (not necessarily
2929 alphabetical). Directory names are listed as separate items.
2931 Old Linux kernels (2.4 and earlier) used a compressed ext2
2932 filesystem as initrd. We I<only> support the newer initramfs
2933 format (compressed cpio files).");
2935 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2937 "mount a file using the loop device",
2939 This command lets you mount C<file> (a filesystem image
2940 in a file) on a mount point. It is entirely equivalent to
2941 the command C<mount -o loop file mountpoint>.");
2943 ("mkswap", (RErr, [Device "device"]), 130, [],
2944 [InitEmpty, Always, TestRun (
2945 [["part_disk"; "/dev/sda"; "mbr"];
2946 ["mkswap"; "/dev/sda1"]])],
2947 "create a swap partition",
2949 Create a swap partition on C<device>.");
2951 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2952 [InitEmpty, Always, TestRun (
2953 [["part_disk"; "/dev/sda"; "mbr"];
2954 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2955 "create a swap partition with a label",
2957 Create a swap partition on C<device> with label C<label>.
2959 Note that you cannot attach a swap label to a block device
2960 (eg. C</dev/sda>), just to a partition. This appears to be
2961 a limitation of the kernel or swap tools.");
2963 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2964 (let uuid = uuidgen () in
2965 [InitEmpty, Always, TestRun (
2966 [["part_disk"; "/dev/sda"; "mbr"];
2967 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2968 "create a swap partition with an explicit UUID",
2970 Create a swap partition on C<device> with UUID C<uuid>.");
2972 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2973 [InitBasicFS, Always, TestOutputStruct (
2974 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2975 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2976 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2977 InitBasicFS, Always, TestOutputStruct (
2978 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2979 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2980 "make block, character or FIFO devices",
2982 This call creates block or character special devices, or
2983 named pipes (FIFOs).
2985 The C<mode> parameter should be the mode, using the standard
2986 constants. C<devmajor> and C<devminor> are the
2987 device major and minor numbers, only used when creating block
2988 and character special devices.");
2990 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2991 [InitBasicFS, Always, TestOutputStruct (
2992 [["mkfifo"; "0o777"; "/node"];
2993 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2994 "make FIFO (named pipe)",
2996 This call creates a FIFO (named pipe) called C<path> with
2997 mode C<mode>. It is just a convenient wrapper around
2998 C<guestfs_mknod>.");
3000 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3001 [InitBasicFS, Always, TestOutputStruct (
3002 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3003 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3004 "make block device node",
3006 This call creates a block device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3010 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3011 [InitBasicFS, Always, TestOutputStruct (
3012 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3013 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3014 "make char device node",
3016 This call creates a char device node called C<path> with
3017 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3018 It is just a convenient wrapper around C<guestfs_mknod>.");
3020 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3021 [InitEmpty, Always, TestOutputInt (
3022 [["umask"; "0o22"]], 0o22)],
3023 "set file mode creation mask (umask)",
3025 This function sets the mask used for creating new files and
3026 device nodes to C<mask & 0777>.
3028 Typical umask values would be C<022> which creates new files
3029 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3030 C<002> which creates new files with permissions like
3031 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3033 The default umask is C<022>. This is important because it
3034 means that directories and device nodes will be created with
3035 C<0644> or C<0755> mode even if you specify C<0777>.
3037 See also C<guestfs_get_umask>,
3038 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3040 This call returns the previous umask.");
3042 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3044 "read directories entries",
3046 This returns the list of directory entries in directory C<dir>.
3048 All entries in the directory are returned, including C<.> and
3049 C<..>. The entries are I<not> sorted, but returned in the same
3050 order as the underlying filesystem.
3052 Also this call returns basic file type information about each
3053 file. The C<ftyp> field will contain one of the following characters:
3091 The L<readdir(3)> returned a C<d_type> field with an
3096 This function is primarily intended for use by programs. To
3097 get a simple list of names, use C<guestfs_ls>. To get a printable
3098 directory for human consumption, use C<guestfs_ll>.");
3100 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3102 "create partitions on a block device",
3104 This is a simplified interface to the C<guestfs_sfdisk>
3105 command, where partition sizes are specified in megabytes
3106 only (rounded to the nearest cylinder) and you don't need
3107 to specify the cyls, heads and sectors parameters which
3108 were rarely if ever used anyway.
3110 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3111 and C<guestfs_part_disk>");
3113 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3115 "determine file type inside a compressed file",
3117 This command runs C<file> after first decompressing C<path>
3120 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3122 Since 1.0.63, use C<guestfs_file> instead which can now
3123 process compressed files.");
3125 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3127 "list extended attributes of a file or directory",
3129 This call lists the extended attributes of the file or directory
3132 At the system call level, this is a combination of the
3133 L<listxattr(2)> and L<getxattr(2)> calls.
3135 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3137 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3139 "list extended attributes of a file or directory",
3141 This is the same as C<guestfs_getxattrs>, but if C<path>
3142 is a symbolic link, then it returns the extended attributes
3143 of the link itself.");
3145 ("setxattr", (RErr, [String "xattr";
3146 String "val"; Int "vallen"; (* will be BufferIn *)
3147 Pathname "path"]), 143, [Optional "linuxxattrs"],
3149 "set extended attribute of a file or directory",
3151 This call sets the extended attribute named C<xattr>
3152 of the file C<path> to the value C<val> (of length C<vallen>).
3153 The value is arbitrary 8 bit data.
3155 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3157 ("lsetxattr", (RErr, [String "xattr";
3158 String "val"; Int "vallen"; (* will be BufferIn *)
3159 Pathname "path"]), 144, [Optional "linuxxattrs"],
3161 "set extended attribute of a file or directory",
3163 This is the same as C<guestfs_setxattr>, but if C<path>
3164 is a symbolic link, then it sets an extended attribute
3165 of the link itself.");
3167 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3169 "remove extended attribute of a file or directory",
3171 This call removes the extended attribute named C<xattr>
3172 of the file C<path>.
3174 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3176 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3178 "remove extended attribute of a file or directory",
3180 This is the same as C<guestfs_removexattr>, but if C<path>
3181 is a symbolic link, then it removes an extended attribute
3182 of the link itself.");
3184 ("mountpoints", (RHashtable "mps", []), 147, [],
3188 This call is similar to C<guestfs_mounts>. That call returns
3189 a list of devices. This one returns a hash table (map) of
3190 device name to directory where the device is mounted.");
3192 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3193 (* This is a special case: while you would expect a parameter
3194 * of type "Pathname", that doesn't work, because it implies
3195 * NEED_ROOT in the generated calling code in stubs.c, and
3196 * this function cannot use NEED_ROOT.
3199 "create a mountpoint",
3201 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3202 specialized calls that can be used to create extra mountpoints
3203 before mounting the first filesystem.
3205 These calls are I<only> necessary in some very limited circumstances,
3206 mainly the case where you want to mount a mix of unrelated and/or
3207 read-only filesystems together.
3209 For example, live CDs often contain a \"Russian doll\" nest of
3210 filesystems, an ISO outer layer, with a squashfs image inside, with
3211 an ext2/3 image inside that. You can unpack this as follows
3214 add-ro Fedora-11-i686-Live.iso
3217 mkmountpoint /squash
3220 mount-loop /cd/LiveOS/squashfs.img /squash
3221 mount-loop /squash/LiveOS/ext3fs.img /ext3
3223 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3225 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3227 "remove a mountpoint",
3229 This calls removes a mountpoint that was previously created
3230 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3231 for full details.");
3233 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3234 [InitISOFS, Always, TestOutputBuffer (
3235 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3238 This calls returns the contents of the file C<path> as a
3241 Unlike C<guestfs_cat>, this function can correctly
3242 handle files that contain embedded ASCII NUL characters.
3243 However unlike C<guestfs_download>, this function is limited
3244 in the total size of file that can be handled.");
3246 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3247 [InitISOFS, Always, TestOutputList (
3248 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3249 InitISOFS, Always, TestOutputList (
3250 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3251 "return lines matching a pattern",
3253 This calls the external C<grep> program and returns the
3256 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3257 [InitISOFS, Always, TestOutputList (
3258 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3259 "return lines matching a pattern",
3261 This calls the external C<egrep> program and returns the
3264 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3265 [InitISOFS, Always, TestOutputList (
3266 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3267 "return lines matching a pattern",
3269 This calls the external C<fgrep> program and returns the
3272 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3273 [InitISOFS, Always, TestOutputList (
3274 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3275 "return lines matching a pattern",
3277 This calls the external C<grep -i> program and returns the
3280 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3281 [InitISOFS, Always, TestOutputList (
3282 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3283 "return lines matching a pattern",
3285 This calls the external C<egrep -i> program and returns the
3288 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3289 [InitISOFS, Always, TestOutputList (
3290 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3291 "return lines matching a pattern",
3293 This calls the external C<fgrep -i> program and returns the
3296 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3297 [InitISOFS, Always, TestOutputList (
3298 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3299 "return lines matching a pattern",
3301 This calls the external C<zgrep> program and returns the
3304 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3305 [InitISOFS, Always, TestOutputList (
3306 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3307 "return lines matching a pattern",
3309 This calls the external C<zegrep> program and returns the
3312 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3313 [InitISOFS, Always, TestOutputList (
3314 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3315 "return lines matching a pattern",
3317 This calls the external C<zfgrep> program and returns the
3320 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3321 [InitISOFS, Always, TestOutputList (
3322 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3323 "return lines matching a pattern",
3325 This calls the external C<zgrep -i> program and returns the
3328 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3329 [InitISOFS, Always, TestOutputList (
3330 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3331 "return lines matching a pattern",
3333 This calls the external C<zegrep -i> program and returns the
3336 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3337 [InitISOFS, Always, TestOutputList (
3338 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3339 "return lines matching a pattern",
3341 This calls the external C<zfgrep -i> program and returns the
3344 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3345 [InitISOFS, Always, TestOutput (
3346 [["realpath"; "/../directory"]], "/directory")],
3347 "canonicalized absolute pathname",
3349 Return the canonicalized absolute pathname of C<path>. The
3350 returned path has no C<.>, C<..> or symbolic link path elements.");
3352 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3353 [InitBasicFS, Always, TestOutputStruct (
3356 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357 "create a hard link",
3359 This command creates a hard link using the C<ln> command.");
3361 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3362 [InitBasicFS, Always, TestOutputStruct (
3365 ["ln_f"; "/a"; "/b"];
3366 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3367 "create a hard link",
3369 This command creates a hard link using the C<ln -f> command.
3370 The C<-f> option removes the link (C<linkname>) if it exists already.");
3372 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3373 [InitBasicFS, Always, TestOutputStruct (
3375 ["ln_s"; "a"; "/b"];
3376 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3377 "create a symbolic link",
3379 This command creates a symbolic link using the C<ln -s> command.");
3381 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3382 [InitBasicFS, Always, TestOutput (
3383 [["mkdir_p"; "/a/b"];
3384 ["touch"; "/a/b/c"];
3385 ["ln_sf"; "../d"; "/a/b/c"];
3386 ["readlink"; "/a/b/c"]], "../d")],
3387 "create a symbolic link",
3389 This command creates a symbolic link using the C<ln -sf> command,
3390 The C<-f> option removes the link (C<linkname>) if it exists already.");
3392 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3393 [] (* XXX tested above *),
3394 "read the target of a symbolic link",
3396 This command reads the target of a symbolic link.");
3398 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3399 [InitBasicFS, Always, TestOutputStruct (
3400 [["fallocate"; "/a"; "1000000"];
3401 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3402 "preallocate a file in the guest filesystem",
3404 This command preallocates a file (containing zero bytes) named
3405 C<path> of size C<len> bytes. If the file exists already, it
3408 Do not confuse this with the guestfish-specific
3409 C<alloc> command which allocates a file in the host and
3410 attaches it as a device.");
3412 ("swapon_device", (RErr, [Device "device"]), 170, [],
3413 [InitPartition, Always, TestRun (
3414 [["mkswap"; "/dev/sda1"];
3415 ["swapon_device"; "/dev/sda1"];
3416 ["swapoff_device"; "/dev/sda1"]])],
3417 "enable swap on device",
3419 This command enables the libguestfs appliance to use the
3420 swap device or partition named C<device>. The increased
3421 memory is made available for all commands, for example
3422 those run using C<guestfs_command> or C<guestfs_sh>.
3424 Note that you should not swap to existing guest swap
3425 partitions unless you know what you are doing. They may
3426 contain hibernation information, or other information that
3427 the guest doesn't want you to trash. You also risk leaking
3428 information about the host to the guest this way. Instead,
3429 attach a new host device to the guest and swap on that.");
3431 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3432 [], (* XXX tested by swapon_device *)
3433 "disable swap on device",
3435 This command disables the libguestfs appliance swap
3436 device or partition named C<device>.
3437 See C<guestfs_swapon_device>.");
3439 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3440 [InitBasicFS, Always, TestRun (
3441 [["fallocate"; "/swap"; "8388608"];
3442 ["mkswap_file"; "/swap"];
3443 ["swapon_file"; "/swap"];
3444 ["swapoff_file"; "/swap"]])],
3445 "enable swap on file",
3447 This command enables swap to a file.
3448 See C<guestfs_swapon_device> for other notes.");
3450 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3451 [], (* XXX tested by swapon_file *)
3452 "disable swap on file",
3454 This command disables the libguestfs appliance swap on file.");
3456 ("swapon_label", (RErr, [String "label"]), 174, [],
3457 [InitEmpty, Always, TestRun (
3458 [["part_disk"; "/dev/sdb"; "mbr"];
3459 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3460 ["swapon_label"; "swapit"];
3461 ["swapoff_label"; "swapit"];
3462 ["zero"; "/dev/sdb"];
3463 ["blockdev_rereadpt"; "/dev/sdb"]])],
3464 "enable swap on labeled swap partition",
3466 This command enables swap to a labeled swap partition.
3467 See C<guestfs_swapon_device> for other notes.");
3469 ("swapoff_label", (RErr, [String "label"]), 175, [],
3470 [], (* XXX tested by swapon_label *)
3471 "disable swap on labeled swap partition",
3473 This command disables the libguestfs appliance swap on
3474 labeled swap partition.");
3476 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3477 (let uuid = uuidgen () in
3478 [InitEmpty, Always, TestRun (
3479 [["mkswap_U"; uuid; "/dev/sdb"];
3480 ["swapon_uuid"; uuid];
3481 ["swapoff_uuid"; uuid]])]),
3482 "enable swap on swap partition by UUID",
3484 This command enables swap to a swap partition with the given UUID.
3485 See C<guestfs_swapon_device> for other notes.");
3487 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3488 [], (* XXX tested by swapon_uuid *)
3489 "disable swap on swap partition by UUID",
3491 This command disables the libguestfs appliance swap partition
3492 with the given UUID.");
3494 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3495 [InitBasicFS, Always, TestRun (
3496 [["fallocate"; "/swap"; "8388608"];
3497 ["mkswap_file"; "/swap"]])],
3498 "create a swap file",
3502 This command just writes a swap file signature to an existing
3503 file. To create the file itself, use something like C<guestfs_fallocate>.");
3505 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3506 [InitISOFS, Always, TestRun (
3507 [["inotify_init"; "0"]])],
3508 "create an inotify handle",
3510 This command creates a new inotify handle.
3511 The inotify subsystem can be used to notify events which happen to
3512 objects in the guest filesystem.
3514 C<maxevents> is the maximum number of events which will be
3515 queued up between calls to C<guestfs_inotify_read> or
3516 C<guestfs_inotify_files>.
3517 If this is passed as C<0>, then the kernel (or previously set)
3518 default is used. For Linux 2.6.29 the default was 16384 events.
3519 Beyond this limit, the kernel throws away events, but records
3520 the fact that it threw them away by setting a flag
3521 C<IN_Q_OVERFLOW> in the returned structure list (see
3522 C<guestfs_inotify_read>).
3524 Before any events are generated, you have to add some
3525 watches to the internal watch list. See:
3526 C<guestfs_inotify_add_watch>,
3527 C<guestfs_inotify_rm_watch> and
3528 C<guestfs_inotify_watch_all>.
3530 Queued up events should be read periodically by calling
3531 C<guestfs_inotify_read>
3532 (or C<guestfs_inotify_files> which is just a helpful
3533 wrapper around C<guestfs_inotify_read>). If you don't
3534 read the events out often enough then you risk the internal
3537 The handle should be closed after use by calling
3538 C<guestfs_inotify_close>. This also removes any
3539 watches automatically.
3541 See also L<inotify(7)> for an overview of the inotify interface
3542 as exposed by the Linux kernel, which is roughly what we expose
3543 via libguestfs. Note that there is one global inotify handle
3544 per libguestfs instance.");
3546 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3547 [InitBasicFS, Always, TestOutputList (
3548 [["inotify_init"; "0"];
3549 ["inotify_add_watch"; "/"; "1073741823"];
3552 ["inotify_files"]], ["a"; "b"])],
3553 "add an inotify watch",
3555 Watch C<path> for the events listed in C<mask>.
3557 Note that if C<path> is a directory then events within that
3558 directory are watched, but this does I<not> happen recursively
3559 (in subdirectories).
3561 Note for non-C or non-Linux callers: the inotify events are
3562 defined by the Linux kernel ABI and are listed in
3563 C</usr/include/sys/inotify.h>.");
3565 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3567 "remove an inotify watch",
3569 Remove a previously defined inotify watch.
3570 See C<guestfs_inotify_add_watch>.");
3572 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3574 "return list of inotify events",
3576 Return the complete queue of events that have happened
3577 since the previous read call.
3579 If no events have happened, this returns an empty list.
3581 I<Note>: In order to make sure that all events have been
3582 read, you must call this function repeatedly until it
3583 returns an empty list. The reason is that the call will
3584 read events up to the maximum appliance-to-host message
3585 size and leave remaining events in the queue.");
3587 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3589 "return list of watched files that had events",
3591 This function is a helpful wrapper around C<guestfs_inotify_read>
3592 which just returns a list of pathnames of objects that were
3593 touched. The returned pathnames are sorted and deduplicated.");
3595 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3597 "close the inotify handle",
3599 This closes the inotify handle which was previously
3600 opened by inotify_init. It removes all watches, throws
3601 away any pending events, and deallocates all resources.");
3603 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3605 "set SELinux security context",
3607 This sets the SELinux security context of the daemon
3608 to the string C<context>.
3610 See the documentation about SELINUX in L<guestfs(3)>.");
3612 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3614 "get SELinux security context",
3616 This gets the SELinux security context of the daemon.
3618 See the documentation about SELINUX in L<guestfs(3)>,
3619 and C<guestfs_setcon>");
3621 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3622 [InitEmpty, Always, TestOutput (
3623 [["part_disk"; "/dev/sda"; "mbr"];
3624 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3625 ["mount_options"; ""; "/dev/sda1"; "/"];
3626 ["write_file"; "/new"; "new file contents"; "0"];
3627 ["cat"; "/new"]], "new file contents")],
3628 "make a filesystem with block size",
3630 This call is similar to C<guestfs_mkfs>, but it allows you to
3631 control the block size of the resulting filesystem. Supported
3632 block sizes depend on the filesystem type, but typically they
3633 are C<1024>, C<2048> or C<4096> only.");
3635 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3636 [InitEmpty, Always, TestOutput (
3637 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3638 ["mke2journal"; "4096"; "/dev/sda1"];
3639 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3640 ["mount_options"; ""; "/dev/sda2"; "/"];
3641 ["write_file"; "/new"; "new file contents"; "0"];
3642 ["cat"; "/new"]], "new file contents")],
3643 "make ext2/3/4 external journal",
3645 This creates an ext2 external journal on C<device>. It is equivalent
3648 mke2fs -O journal_dev -b blocksize device");
3650 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3651 [InitEmpty, Always, TestOutput (
3652 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3654 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3655 ["mount_options"; ""; "/dev/sda2"; "/"];
3656 ["write_file"; "/new"; "new file contents"; "0"];
3657 ["cat"; "/new"]], "new file contents")],
3658 "make ext2/3/4 external journal with label",
3660 This creates an ext2 external journal on C<device> with label C<label>.");
3662 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3663 (let uuid = uuidgen () in
3664 [InitEmpty, Always, TestOutput (
3665 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3666 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3667 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3668 ["mount_options"; ""; "/dev/sda2"; "/"];
3669 ["write_file"; "/new"; "new file contents"; "0"];
3670 ["cat"; "/new"]], "new file contents")]),
3671 "make ext2/3/4 external journal with UUID",
3673 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3675 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3677 "make ext2/3/4 filesystem with external journal",
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on C<journal>. It is equivalent
3683 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3685 See also C<guestfs_mke2journal>.");
3687 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3689 "make ext2/3/4 filesystem with external journal",
3691 This creates an ext2/3/4 filesystem on C<device> with
3692 an external journal on the journal labeled C<label>.
3694 See also C<guestfs_mke2journal_L>.");
3696 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3698 "make ext2/3/4 filesystem with external journal",
3700 This creates an ext2/3/4 filesystem on C<device> with
3701 an external journal on the journal with UUID C<uuid>.
3703 See also C<guestfs_mke2journal_U>.");
3705 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3706 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3707 "load a kernel module",
3709 This loads a kernel module in the appliance.
3711 The kernel module must have been whitelisted when libguestfs
3712 was built (see C<appliance/kmod.whitelist.in> in the source).");
3714 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3715 [InitNone, Always, TestOutput (
3716 [["echo_daemon"; "This is a test"]], "This is a test"
3718 "echo arguments back to the client",
3720 This command concatenate the list of C<words> passed with single spaces between
3721 them and returns the resulting string.
3723 You can use this command to test the connection through to the daemon.
3725 See also C<guestfs_ping_daemon>.");
3727 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3728 [], (* There is a regression test for this. *)
3729 "find all files and directories, returning NUL-separated list",
3731 This command lists out all files and directories, recursively,
3732 starting at C<directory>, placing the resulting list in the
3733 external file called C<files>.
3735 This command works the same way as C<guestfs_find> with the
3736 following exceptions:
3742 The resulting list is written to an external file.
3746 Items (filenames) in the result are separated
3747 by C<\\0> characters. See L<find(1)> option I<-print0>.
3751 This command is not limited in the number of names that it
3756 The result list is not sorted.
3760 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3761 [InitISOFS, Always, TestOutput (
3762 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3763 InitISOFS, Always, TestOutput (
3764 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3765 InitISOFS, Always, TestOutput (
3766 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3767 InitISOFS, Always, TestLastFail (
3768 [["case_sensitive_path"; "/Known-1/"]]);
3769 InitBasicFS, Always, TestOutput (
3771 ["mkdir"; "/a/bbb"];
3772 ["touch"; "/a/bbb/c"];
3773 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3774 InitBasicFS, Always, TestOutput (
3776 ["mkdir"; "/a/bbb"];
3777 ["touch"; "/a/bbb/c"];
3778 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3779 InitBasicFS, Always, TestLastFail (
3781 ["mkdir"; "/a/bbb"];
3782 ["touch"; "/a/bbb/c"];
3783 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3784 "return true path on case-insensitive filesystem",
3786 This can be used to resolve case insensitive paths on
3787 a filesystem which is case sensitive. The use case is
3788 to resolve paths which you have read from Windows configuration
3789 files or the Windows Registry, to the true path.
3791 The command handles a peculiarity of the Linux ntfs-3g
3792 filesystem driver (and probably others), which is that although
3793 the underlying filesystem is case-insensitive, the driver
3794 exports the filesystem to Linux as case-sensitive.
3796 One consequence of this is that special directories such
3797 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3798 (or other things) depending on the precise details of how
3799 they were created. In Windows itself this would not be
3802 Bug or feature? You decide:
3803 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3805 This function resolves the true case of each element in the
3806 path and returns the case-sensitive path.
3808 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3809 might return C<\"/WINDOWS/system32\"> (the exact return value
3810 would depend on details of how the directories were originally
3811 created under Windows).
3814 This function does not handle drive names, backslashes etc.
3816 See also C<guestfs_realpath>.");
3818 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3819 [InitBasicFS, Always, TestOutput (
3820 [["vfs_type"; "/dev/sda1"]], "ext2")],
3821 "get the Linux VFS type corresponding to a mounted device",
3823 This command gets the block device type corresponding to
3824 a mounted device called C<device>.
3826 Usually the result is the name of the Linux VFS module that
3827 is used to mount this device (probably determined automatically
3828 if you used the C<guestfs_mount> call).");
3830 ("truncate", (RErr, [Pathname "path"]), 199, [],
3831 [InitBasicFS, Always, TestOutputStruct (
3832 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3833 ["truncate"; "/test"];
3834 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3835 "truncate a file to zero size",
3837 This command truncates C<path> to a zero-length file. The
3838 file must exist already.");
3840 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3841 [InitBasicFS, Always, TestOutputStruct (
3842 [["touch"; "/test"];
3843 ["truncate_size"; "/test"; "1000"];
3844 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3845 "truncate a file to a particular size",
3847 This command truncates C<path> to size C<size> bytes. The file
3848 must exist already. If the file is smaller than C<size> then
3849 the file is extended to the required size with null bytes.");
3851 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3852 [InitBasicFS, Always, TestOutputStruct (
3853 [["touch"; "/test"];
3854 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3855 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3856 "set timestamp of a file with nanosecond precision",
3858 This command sets the timestamps of a file with nanosecond
3861 C<atsecs, atnsecs> are the last access time (atime) in secs and
3862 nanoseconds from the epoch.
3864 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3865 secs and nanoseconds from the epoch.
3867 If the C<*nsecs> field contains the special value C<-1> then
3868 the corresponding timestamp is set to the current time. (The
3869 C<*secs> field is ignored in this case).
3871 If the C<*nsecs> field contains the special value C<-2> then
3872 the corresponding timestamp is left unchanged. (The
3873 C<*secs> field is ignored in this case).");
3875 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3876 [InitBasicFS, Always, TestOutputStruct (
3877 [["mkdir_mode"; "/test"; "0o111"];
3878 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3879 "create a directory with a particular mode",
3881 This command creates a directory, setting the initial permissions
3882 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3884 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3886 "change file owner and group",
3888 Change the file owner to C<owner> and group to C<group>.
3889 This is like C<guestfs_chown> but if C<path> is a symlink then
3890 the link itself is changed, not the target.
3892 Only numeric uid and gid are supported. If you want to use
3893 names, you will need to locate and parse the password file
3894 yourself (Augeas support makes this relatively easy).");
3896 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3898 "lstat on multiple files",
3900 This call allows you to perform the C<guestfs_lstat> operation
3901 on multiple files, where all files are in the directory C<path>.
3902 C<names> is the list of files from this directory.
3904 On return you get a list of stat structs, with a one-to-one
3905 correspondence to the C<names> list. If any name did not exist
3906 or could not be lstat'd, then the C<ino> field of that structure
3909 This call is intended for programs that want to efficiently
3910 list a directory contents without making many round-trips.
3911 See also C<guestfs_lxattrlist> for a similarly efficient call
3912 for getting extended attributes. Very long directory listings
3913 might cause the protocol message size to be exceeded, causing
3914 this call to fail. The caller must split up such requests
3915 into smaller groups of names.");
3917 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3919 "lgetxattr on multiple files",
3921 This call allows you to get the extended attributes
3922 of multiple files, where all files are in the directory C<path>.
3923 C<names> is the list of files from this directory.
3925 On return you get a flat list of xattr structs which must be
3926 interpreted sequentially. The first xattr struct always has a zero-length
3927 C<attrname>. C<attrval> in this struct is zero-length
3928 to indicate there was an error doing C<lgetxattr> for this
3929 file, I<or> is a C string which is a decimal number
3930 (the number of following attributes for this file, which could
3931 be C<\"0\">). Then after the first xattr struct are the
3932 zero or more attributes for the first named file.
3933 This repeats for the second and subsequent files.
3935 This call is intended for programs that want to efficiently
3936 list a directory contents without making many round-trips.
3937 See also C<guestfs_lstatlist> for a similarly efficient call
3938 for getting standard stats. Very long directory listings
3939 might cause the protocol message size to be exceeded, causing
3940 this call to fail. The caller must split up such requests
3941 into smaller groups of names.");
3943 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3945 "readlink on multiple files",
3947 This call allows you to do a C<readlink> operation
3948 on multiple files, where all files are in the directory C<path>.
3949 C<names> is the list of files from this directory.
3951 On return you get a list of strings, with a one-to-one
3952 correspondence to the C<names> list. Each string is the
3953 value of the symbol link.
3955 If the C<readlink(2)> operation fails on any name, then
3956 the corresponding result string is the empty string C<\"\">.
3957 However the whole operation is completed even if there
3958 were C<readlink(2)> errors, and so you can call this
3959 function with names where you don't know if they are
3960 symbolic links already (albeit slightly less efficient).
3962 This call is intended for programs that want to efficiently
3963 list a directory contents without making many round-trips.
3964 Very long directory listings might cause the protocol
3965 message size to be exceeded, causing
3966 this call to fail. The caller must split up such requests
3967 into smaller groups of names.");
3969 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3970 [InitISOFS, Always, TestOutputBuffer (
3971 [["pread"; "/known-4"; "1"; "3"]], "\n");
3972 InitISOFS, Always, TestOutputBuffer (
3973 [["pread"; "/empty"; "0"; "100"]], "")],
3974 "read part of a file",
3976 This command lets you read part of a file. It reads C<count>
3977 bytes of the file, starting at C<offset>, from file C<path>.
3979 This may read fewer bytes than requested. For further details
3980 see the L<pread(2)> system call.");
3982 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3983 [InitEmpty, Always, TestRun (
3984 [["part_init"; "/dev/sda"; "gpt"]])],
3985 "create an empty partition table",
3987 This creates an empty partition table on C<device> of one of the
3988 partition types listed below. Usually C<parttype> should be
3989 either C<msdos> or C<gpt> (for large disks).
3991 Initially there are no partitions. Following this, you should
3992 call C<guestfs_part_add> for each partition required.
3994 Possible values for C<parttype> are:
3998 =item B<efi> | B<gpt>
4000 Intel EFI / GPT partition table.
4002 This is recommended for >= 2 TB partitions that will be accessed
4003 from Linux and Intel-based Mac OS X. It also has limited backwards
4004 compatibility with the C<mbr> format.
4006 =item B<mbr> | B<msdos>
4008 The standard PC \"Master Boot Record\" (MBR) format used
4009 by MS-DOS and Windows. This partition type will B<only> work
4010 for device sizes up to 2 TB. For large disks we recommend
4015 Other partition table types that may work but are not
4024 =item B<amiga> | B<rdb>
4026 Amiga \"Rigid Disk Block\" format.
4034 DASD, used on IBM mainframes.
4042 Old Mac partition format. Modern Macs use C<gpt>.
4046 NEC PC-98 format, common in Japan apparently.
4054 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4055 [InitEmpty, Always, TestRun (
4056 [["part_init"; "/dev/sda"; "mbr"];
4057 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4058 InitEmpty, Always, TestRun (
4059 [["part_init"; "/dev/sda"; "gpt"];
4060 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4061 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4062 InitEmpty, Always, TestRun (
4063 [["part_init"; "/dev/sda"; "mbr"];
4064 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4065 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4066 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4067 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4068 "add a partition to the device",
4070 This command adds a partition to C<device>. If there is no partition
4071 table on the device, call C<guestfs_part_init> first.
4073 The C<prlogex> parameter is the type of partition. Normally you
4074 should pass C<p> or C<primary> here, but MBR partition tables also
4075 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4078 C<startsect> and C<endsect> are the start and end of the partition
4079 in I<sectors>. C<endsect> may be negative, which means it counts
4080 backwards from the end of the disk (C<-1> is the last sector).
4082 Creating a partition which covers the whole disk is not so easy.
4083 Use C<guestfs_part_disk> to do that.");
4085 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4086 [InitEmpty, Always, TestRun (
4087 [["part_disk"; "/dev/sda"; "mbr"]]);
4088 InitEmpty, Always, TestRun (
4089 [["part_disk"; "/dev/sda"; "gpt"]])],
4090 "partition whole disk with a single primary partition",
4092 This command is simply a combination of C<guestfs_part_init>
4093 followed by C<guestfs_part_add> to create a single primary partition
4094 covering the whole disk.
4096 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4097 but other possible values are described in C<guestfs_part_init>.");
4099 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4100 [InitEmpty, Always, TestRun (
4101 [["part_disk"; "/dev/sda"; "mbr"];
4102 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4103 "make a partition bootable",
4105 This sets the bootable flag on partition numbered C<partnum> on
4106 device C<device>. Note that partitions are numbered from 1.
4108 The bootable flag is used by some operating systems (notably
4109 Windows) to determine which partition to boot from. It is by
4110 no means universally recognized.");
4112 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4113 [InitEmpty, Always, TestRun (
4114 [["part_disk"; "/dev/sda"; "gpt"];
4115 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4116 "set partition name",
4118 This sets the partition name on partition numbered C<partnum> on
4119 device C<device>. Note that partitions are numbered from 1.
4121 The partition name can only be set on certain types of partition
4122 table. This works on C<gpt> but not on C<mbr> partitions.");
4124 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4125 [], (* XXX Add a regression test for this. *)
4126 "list partitions on a device",
4128 This command parses the partition table on C<device> and
4129 returns the list of partitions found.
4131 The fields in the returned structure are:
4137 Partition number, counting from 1.
4141 Start of the partition I<in bytes>. To get sectors you have to
4142 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4146 End of the partition in bytes.
4150 Size of the partition in bytes.
4154 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4155 [InitEmpty, Always, TestOutput (
4156 [["part_disk"; "/dev/sda"; "gpt"];
4157 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4158 "get the partition table type",
4160 This command examines the partition table on C<device> and
4161 returns the partition table type (format) being used.
4163 Common return values include: C<msdos> (a DOS/Windows style MBR
4164 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4165 values are possible, although unusual. See C<guestfs_part_init>
4168 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4169 [InitBasicFS, Always, TestOutputBuffer (
4170 [["fill"; "0x63"; "10"; "/test"];
4171 ["read_file"; "/test"]], "cccccccccc")],
4172 "fill a file with octets",
4174 This command creates a new file called C<path>. The initial
4175 content of the file is C<len> octets of C<c>, where C<c>
4176 must be a number in the range C<[0..255]>.
4178 To fill a file with zero bytes (sparsely), it is
4179 much more efficient to use C<guestfs_truncate_size>.");
4181 ("available", (RErr, [StringList "groups"]), 216, [],
4182 [InitNone, Always, TestRun [["available"; ""]]],
4183 "test availability of some parts of the API",
4185 This command is used to check the availability of some
4186 groups of functionality in the appliance, which not all builds of
4187 the libguestfs appliance will be able to provide.
4189 The libguestfs groups, and the functions that those
4190 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4192 The argument C<groups> is a list of group names, eg:
4193 C<[\"inotify\", \"augeas\"]> would check for the availability of
4194 the Linux inotify functions and Augeas (configuration file
4197 The command returns no error if I<all> requested groups are available.
4199 It fails with an error if one or more of the requested
4200 groups is unavailable in the appliance.
4202 If an unknown group name is included in the
4203 list of groups then an error is always returned.
4211 You must call C<guestfs_launch> before calling this function.
4213 The reason is because we don't know what groups are
4214 supported by the appliance/daemon until it is running and can
4219 If a group of functions is available, this does not necessarily
4220 mean that they will work. You still have to check for errors
4221 when calling individual API functions even if they are
4226 It is usually the job of distro packagers to build
4227 complete functionality into the libguestfs appliance.
4228 Upstream libguestfs, if built from source with all
4229 requirements satisfied, will support everything.
4233 This call was added in version C<1.0.80>. In previous
4234 versions of libguestfs all you could do would be to speculatively
4235 execute a command to find out if the daemon implemented it.
4236 See also C<guestfs_version>.
4240 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4241 [InitBasicFS, Always, TestOutputBuffer (
4242 [["write_file"; "/src"; "hello, world"; "0"];
4243 ["dd"; "/src"; "/dest"];
4244 ["read_file"; "/dest"]], "hello, world")],
4245 "copy from source to destination using dd",
4247 This command copies from one source device or file C<src>
4248 to another destination device or file C<dest>. Normally you
4249 would use this to copy to or from a device or partition, for
4250 example to duplicate a filesystem.
4252 If the destination is a device, it must be as large or larger
4253 than the source file or device, otherwise the copy will fail.
4254 This command cannot do partial copies (see C<guestfs_copy_size>).");
4256 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4257 [InitBasicFS, Always, TestOutputInt (
4258 [["write_file"; "/file"; "hello, world"; "0"];
4259 ["filesize"; "/file"]], 12)],
4260 "return the size of the file in bytes",
4262 This command returns the size of C<file> in bytes.
4264 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4265 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4266 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4268 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4269 [InitBasicFSonLVM, Always, TestOutputList (
4270 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4271 ["lvs"]], ["/dev/VG/LV2"])],
4272 "rename an LVM logical volume",
4274 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4276 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4277 [InitBasicFSonLVM, Always, TestOutputList (
4279 ["vg_activate"; "false"; "VG"];
4280 ["vgrename"; "VG"; "VG2"];
4281 ["vg_activate"; "true"; "VG2"];
4282 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4283 ["vgs"]], ["VG2"])],
4284 "rename an LVM volume group",
4286 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4288 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4289 [InitISOFS, Always, TestOutputBuffer (
4290 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4291 "list the contents of a single file in an initrd",
4293 This command unpacks the file C<filename> from the initrd file
4294 called C<initrdpath>. The filename must be given I<without> the
4295 initial C</> character.
4297 For example, in guestfish you could use the following command
4298 to examine the boot script (usually called C</init>)
4299 contained in a Linux initrd or initramfs image:
4301 initrd-cat /boot/initrd-<version>.img init
4303 See also C<guestfs_initrd_list>.");
4305 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4307 "get the UUID of a physical volume",
4309 This command returns the UUID of the LVM PV C<device>.");
4311 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4313 "get the UUID of a volume group",
4315 This command returns the UUID of the LVM VG named C<vgname>.");
4317 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4319 "get the UUID of a logical volume",
4321 This command returns the UUID of the LVM LV C<device>.");
4323 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4325 "get the PV UUIDs containing the volume group",
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the physical volumes that this volume group resides on.
4330 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4331 calls to associate physical volumes and volume groups.
4333 See also C<guestfs_vglvuuids>.");
4335 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4337 "get the LV UUIDs of all LVs in the volume group",
4339 Given a VG called C<vgname>, this returns the UUIDs of all
4340 the logical volumes created in this volume group.
4342 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4343 calls to associate logical volumes and volume groups.
4345 See also C<guestfs_vgpvuuids>.");
4347 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4348 [InitBasicFS, Always, TestOutputBuffer (
4349 [["write_file"; "/src"; "hello, world"; "0"];
4350 ["copy_size"; "/src"; "/dest"; "5"];
4351 ["read_file"; "/dest"]], "hello")],
4352 "copy size bytes from source to destination using dd",
4354 This command copies exactly C<size> bytes from one source device
4355 or file C<src> to another destination device or file C<dest>.
4357 Note this will fail if the source is too short or if the destination
4358 is not large enough.");
4360 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4361 [InitBasicFSonLVM, Always, TestRun (
4362 [["zero_device"; "/dev/VG/LV"]])],
4363 "write zeroes to an entire device",
4365 This command writes zeroes over the entire C<device>. Compare
4366 with C<guestfs_zero> which just zeroes the first few blocks of
4369 ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4370 [InitBasicFS, Always, TestOutput (
4371 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4372 ["cat"; "/hello"]], "hello\n")],
4373 "unpack compressed tarball to directory",
4375 This command uploads and unpacks local file C<tarball> (an
4376 I<xz compressed> tar file) into C<directory>.");
4378 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4380 "pack directory into compressed tarball",
4382 This command packs the contents of C<directory> and downloads
4383 it to local file C<tarball> (as an xz compressed tar archive).");
4385 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4387 "resize an NTFS filesystem",
4389 This command resizes an NTFS filesystem, expanding or
4390 shrinking it to the size of the underlying device.
4391 See also L<ntfsresize(8)>.");
4393 ("vgscan", (RErr, []), 232, [],
4394 [InitEmpty, Always, TestRun (
4396 "rescan for LVM physical volumes, volume groups and logical volumes",
4398 This rescans all block devices and rebuilds the list of LVM
4399 physical volumes, volume groups and logical volumes.");
4401 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4402 [InitEmpty, Always, TestRun (
4403 [["part_init"; "/dev/sda"; "mbr"];
4404 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4405 ["part_del"; "/dev/sda"; "1"]])],
4406 "delete a partition",
4408 This command deletes the partition numbered C<partnum> on C<device>.
4410 Note that in the case of MBR partitioning, deleting an
4411 extended partition also deletes any logical partitions
4414 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4415 [InitEmpty, Always, TestOutputTrue (
4416 [["part_init"; "/dev/sda"; "mbr"];
4417 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4418 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4419 ["part_get_bootable"; "/dev/sda"; "1"]])],
4420 "return true if a partition is bootable",
4422 This command returns true if the partition C<partnum> on
4423 C<device> has the bootable flag set.
4425 See also C<guestfs_part_set_bootable>.");
4427 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4428 [InitEmpty, Always, TestOutputInt (
4429 [["part_init"; "/dev/sda"; "mbr"];
4430 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4431 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4432 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4433 "get the MBR type byte (ID byte) from a partition",
4435 Returns the MBR type byte (also known as the ID byte) from
4436 the numbered partition C<partnum>.
4438 Note that only MBR (old DOS-style) partitions have type bytes.
4439 You will get undefined results for other partition table
4440 types (see C<guestfs_part_get_parttype>).");
4442 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4443 [], (* tested by part_get_mbr_id *)
4444 "set the MBR type byte (ID byte) of a partition",
4446 Sets the MBR type byte (also known as the ID byte) of
4447 the numbered partition C<partnum> to C<idbyte>. Note
4448 that the type bytes quoted in most documentation are
4449 in fact hexadecimal numbers, but usually documented
4450 without any leading \"0x\" which might be confusing.
4452 Note that only MBR (old DOS-style) partitions have type bytes.
4453 You will get undefined results for other partition table
4454 types (see C<guestfs_part_get_parttype>).");
4456 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4457 [InitISOFS, Always, TestOutput (
4458 [["checksum_device"; "md5"; "/dev/sdd"]],
4459 (Digest.to_hex (Digest.file "images/test.iso")))],
4460 "compute MD5, SHAx or CRC checksum of the contents of a device",
4462 This call computes the MD5, SHAx or CRC checksum of the
4463 contents of the device named C<device>. For the types of
4464 checksums supported see the C<guestfs_checksum> command.");
4466 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4467 [InitNone, Always, TestRun (
4468 [["part_disk"; "/dev/sda"; "mbr"];
4469 ["pvcreate"; "/dev/sda1"];
4470 ["vgcreate"; "VG"; "/dev/sda1"];
4471 ["lvcreate"; "LV"; "VG"; "10"];
4472 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4473 "expand an LV to fill free space",
4475 This expands an existing logical volume C<lv> so that it fills
4476 C<pc>% of the remaining free space in the volume group. Commonly
4477 you would call this with pc = 100 which expands the logical volume
4478 as much as possible, using all remaining free space in the volume
4481 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4482 [], (* XXX Augeas code needs tests. *)
4483 "clear Augeas path",
4485 Set the value associated with C<path> to C<NULL>. This
4486 is the same as the L<augtool(1)> C<clear> command.");
4488 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4489 [InitEmpty, Always, TestOutputInt (
4490 [["get_umask"]], 0o22)],
4491 "get the current umask",
4493 Return the current umask. By default the umask is C<022>
4494 unless it has been set by calling C<guestfs_umask>.");
4498 let all_functions = non_daemon_functions @ daemon_functions
4500 (* In some places we want the functions to be displayed sorted
4501 * alphabetically, so this is useful:
4503 let all_functions_sorted =
4504 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4505 compare n1 n2) all_functions
4507 (* Field types for structures. *)
4509 | FChar (* C 'char' (really, a 7 bit byte). *)
4510 | FString (* nul-terminated ASCII string, NOT NULL. *)
4511 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4516 | FBytes (* Any int measure that counts bytes. *)
4517 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4518 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4520 (* Because we generate extra parsing code for LVM command line tools,
4521 * we have to pull out the LVM columns separately here.
4531 "pv_attr", FString (* XXX *);
4532 "pv_pe_count", FInt64;
4533 "pv_pe_alloc_count", FInt64;
4536 "pv_mda_count", FInt64;
4537 "pv_mda_free", FBytes;
4538 (* Not in Fedora 10:
4539 "pv_mda_size", FBytes;
4546 "vg_attr", FString (* XXX *);
4549 "vg_sysid", FString;
4550 "vg_extent_size", FBytes;
4551 "vg_extent_count", FInt64;
4552 "vg_free_count", FInt64;
4557 "snap_count", FInt64;
4560 "vg_mda_count", FInt64;
4561 "vg_mda_free", FBytes;
4562 (* Not in Fedora 10:
4563 "vg_mda_size", FBytes;
4569 "lv_attr", FString (* XXX *);
4572 "lv_kernel_major", FInt64;
4573 "lv_kernel_minor", FInt64;
4575 "seg_count", FInt64;
4577 "snap_percent", FOptPercent;
4578 "copy_percent", FOptPercent;
4581 "mirror_log", FString;
4585 (* Names and fields in all structures (in RStruct and RStructList)
4589 (* The old RIntBool return type, only ever used for aug_defnode. Do
4590 * not use this struct in any new code.
4593 "i", FInt32; (* for historical compatibility *)
4594 "b", FInt32; (* for historical compatibility *)
4597 (* LVM PVs, VGs, LVs. *)
4598 "lvm_pv", lvm_pv_cols;
4599 "lvm_vg", lvm_vg_cols;
4600 "lvm_lv", lvm_lv_cols;
4602 (* Column names and types from stat structures.
4603 * NB. Can't use things like 'st_atime' because glibc header files
4604 * define some of these as macros. Ugh.
4635 (* Column names in dirent structure. *)
4638 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4643 (* Version numbers. *)
4651 (* Extended attribute. *)
4653 "attrname", FString;
4657 (* Inotify events. *)
4661 "in_cookie", FUInt32;
4665 (* Partition table entry. *)
4668 "part_start", FBytes;
4670 "part_size", FBytes;
4672 ] (* end of structs *)
4674 (* Ugh, Java has to be different ..
4675 * These names are also used by the Haskell bindings.
4677 let java_structs = [
4678 "int_bool", "IntBool";
4683 "statvfs", "StatVFS";
4685 "version", "Version";
4687 "inotify_event", "INotifyEvent";
4688 "partition", "Partition";
4691 (* What structs are actually returned. *)
4692 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4694 (* Returns a list of RStruct/RStructList structs that are returned
4695 * by any function. Each element of returned list is a pair:
4697 * (structname, RStructOnly)
4698 * == there exists function which returns RStruct (_, structname)
4699 * (structname, RStructListOnly)
4700 * == there exists function which returns RStructList (_, structname)
4701 * (structname, RStructAndList)
4702 * == there are functions returning both RStruct (_, structname)
4703 * and RStructList (_, structname)
4705 let rstructs_used_by functions =
4706 (* ||| is a "logical OR" for rstructs_used_t *)
4710 | _, RStructAndList -> RStructAndList
4711 | RStructOnly, RStructListOnly
4712 | RStructListOnly, RStructOnly -> RStructAndList
4713 | RStructOnly, RStructOnly -> RStructOnly
4714 | RStructListOnly, RStructListOnly -> RStructListOnly
4717 let h = Hashtbl.create 13 in
4719 (* if elem->oldv exists, update entry using ||| operator,
4720 * else just add elem->newv to the hash
4722 let update elem newv =
4723 try let oldv = Hashtbl.find h elem in
4724 Hashtbl.replace h elem (newv ||| oldv)
4725 with Not_found -> Hashtbl.add h elem newv
4729 fun (_, style, _, _, _, _, _) ->
4730 match fst style with
4731 | RStruct (_, structname) -> update structname RStructOnly
4732 | RStructList (_, structname) -> update structname RStructListOnly
4736 (* return key->values as a list of (key,value) *)
4737 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4739 (* Used for testing language bindings. *)
4741 | CallString of string
4742 | CallOptString of string option
4743 | CallStringList of string list
4745 | CallInt64 of int64
4748 (* Used to memoize the result of pod2text. *)
4749 let pod2text_memo_filename = "src/.pod2text.data"
4750 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4752 let chan = open_in pod2text_memo_filename in
4753 let v = input_value chan in
4757 _ -> Hashtbl.create 13
4758 let pod2text_memo_updated () =
4759 let chan = open_out pod2text_memo_filename in
4760 output_value chan pod2text_memo;
4763 (* Useful functions.
4764 * Note we don't want to use any external OCaml libraries which
4765 * makes this a bit harder than it should be.
4767 module StringMap = Map.Make (String)
4769 let failwithf fs = ksprintf failwith fs
4771 let unique = let i = ref 0 in fun () -> incr i; !i
4773 let replace_char s c1 c2 =
4774 let s2 = String.copy s in
4775 let r = ref false in
4776 for i = 0 to String.length s2 - 1 do
4777 if String.unsafe_get s2 i = c1 then (
4778 String.unsafe_set s2 i c2;
4782 if not !r then s else s2
4786 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4788 let triml ?(test = isspace) str =
4790 let n = ref (String.length str) in
4791 while !n > 0 && test str.[!i]; do
4796 else String.sub str !i !n
4798 let trimr ?(test = isspace) str =
4799 let n = ref (String.length str) in
4800 while !n > 0 && test str.[!n-1]; do
4803 if !n = String.length str then str
4804 else String.sub str 0 !n
4806 let trim ?(test = isspace) str =
4807 trimr ~test (triml ~test str)
4809 let rec find s sub =
4810 let len = String.length s in
4811 let sublen = String.length sub in
4813 if i <= len-sublen then (
4815 if j < sublen then (
4816 if s.[i+j] = sub.[j] then loop2 (j+1)
4822 if r = -1 then loop (i+1) else r
4828 let rec replace_str s s1 s2 =
4829 let len = String.length s in
4830 let sublen = String.length s1 in
4831 let i = find s s1 in
4834 let s' = String.sub s 0 i in
4835 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4836 s' ^ s2 ^ replace_str s'' s1 s2
4839 let rec string_split sep str =
4840 let len = String.length str in
4841 let seplen = String.length sep in
4842 let i = find str sep in
4843 if i = -1 then [str]
4845 let s' = String.sub str 0 i in
4846 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4847 s' :: string_split sep s''
4850 let files_equal n1 n2 =
4851 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4852 match Sys.command cmd with
4855 | i -> failwithf "%s: failed with error code %d" cmd i
4857 let rec filter_map f = function
4861 | Some y -> y :: filter_map f xs
4862 | None -> filter_map f xs
4864 let rec find_map f = function
4865 | [] -> raise Not_found
4869 | None -> find_map f xs
4872 let rec loop i = function
4874 | x :: xs -> f i x; loop (i+1) xs
4879 let rec loop i = function
4881 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4885 let count_chars c str =
4886 let count = ref 0 in
4887 for i = 0 to String.length str - 1 do
4888 if c = String.unsafe_get str i then incr count
4892 let name_of_argt = function
4893 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4894 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4895 | FileIn n | FileOut n -> n
4897 let java_name_of_struct typ =
4898 try List.assoc typ java_structs
4901 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4903 let cols_of_struct typ =
4904 try List.assoc typ structs
4906 failwithf "cols_of_struct: unknown struct %s" typ
4908 let seq_of_test = function
4909 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4910 | TestOutputListOfDevices (s, _)
4911 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4912 | TestOutputTrue s | TestOutputFalse s
4913 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4914 | TestOutputStruct (s, _)
4915 | TestLastFail s -> s
4917 (* Handling for function flags. *)
4918 let protocol_limit_warning =
4919 "Because of the message protocol, there is a transfer limit
4920 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4922 let danger_will_robinson =
4923 "B<This command is dangerous. Without careful use you
4924 can easily destroy all your data>."
4926 let deprecation_notice flags =
4929 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4931 sprintf "This function is deprecated.
4932 In new code, use the C<%s> call instead.
4934 Deprecated functions will not be removed from the API, but the
4935 fact that they are deprecated indicates that there are problems
4936 with correct use of these functions." alt in
4941 (* Create list of optional groups. *)
4943 let h = Hashtbl.create 13 in
4945 fun (name, _, _, flags, _, _, _) ->
4949 let names = try Hashtbl.find h group with Not_found -> [] in
4950 Hashtbl.replace h group (name :: names)
4954 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4957 fun group -> group, List.sort compare (Hashtbl.find h group)
4959 List.sort (fun x y -> compare (fst x) (fst y)) groups
4961 (* Check function names etc. for consistency. *)
4962 let check_functions () =
4963 let contains_uppercase str =
4964 let len = String.length str in
4966 if i >= len then false
4969 if c >= 'A' && c <= 'Z' then true
4976 (* Check function names. *)
4978 fun (name, _, _, _, _, _, _) ->
4979 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4980 failwithf "function name %s does not need 'guestfs' prefix" name;
4982 failwithf "function name is empty";
4983 if name.[0] < 'a' || name.[0] > 'z' then
4984 failwithf "function name %s must start with lowercase a-z" name;
4985 if String.contains name '-' then
4986 failwithf "function name %s should not contain '-', use '_' instead."
4990 (* Check function parameter/return names. *)
4992 fun (name, style, _, _, _, _, _) ->
4993 let check_arg_ret_name n =
4994 if contains_uppercase n then
4995 failwithf "%s param/ret %s should not contain uppercase chars"
4997 if String.contains n '-' || String.contains n '_' then
4998 failwithf "%s param/ret %s should not contain '-' or '_'"
5001 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;
5002 if n = "int" || n = "char" || n = "short" || n = "long" then
5003 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5004 if n = "i" || n = "n" then
5005 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5006 if n = "argv" || n = "args" then
5007 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5009 (* List Haskell, OCaml and C keywords here.
5010 * http://www.haskell.org/haskellwiki/Keywords
5011 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5012 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5013 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5014 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5015 * Omitting _-containing words, since they're handled above.
5016 * Omitting the OCaml reserved word, "val", is ok,
5017 * and saves us from renaming several parameters.
5020 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5021 "char"; "class"; "const"; "constraint"; "continue"; "data";
5022 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5023 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5024 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5025 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5026 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5028 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5029 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5030 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5031 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5032 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5033 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5034 "volatile"; "when"; "where"; "while";
5036 if List.mem n reserved then
5037 failwithf "%s has param/ret using reserved word %s" name n;
5040 (match fst style with
5042 | RInt n | RInt64 n | RBool n
5043 | RConstString n | RConstOptString n | RString n
5044 | RStringList n | RStruct (n, _) | RStructList (n, _)
5045 | RHashtable n | RBufferOut n ->
5046 check_arg_ret_name n
5048 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5051 (* Check short descriptions. *)
5053 fun (name, _, _, _, _, shortdesc, _) ->
5054 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5055 failwithf "short description of %s should begin with lowercase." name;
5056 let c = shortdesc.[String.length shortdesc-1] in
5057 if c = '\n' || c = '.' then
5058 failwithf "short description of %s should not end with . or \\n." name
5061 (* Check long dscriptions. *)
5063 fun (name, _, _, _, _, _, longdesc) ->
5064 if longdesc.[String.length longdesc-1] = '\n' then
5065 failwithf "long description of %s should not end with \\n." name
5068 (* Check proc_nrs. *)
5070 fun (name, _, proc_nr, _, _, _, _) ->
5071 if proc_nr <= 0 then
5072 failwithf "daemon function %s should have proc_nr > 0" name
5076 fun (name, _, proc_nr, _, _, _, _) ->
5077 if proc_nr <> -1 then
5078 failwithf "non-daemon function %s should have proc_nr -1" name
5079 ) non_daemon_functions;
5082 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5085 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5086 let rec loop = function
5089 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5091 | (name1,nr1) :: (name2,nr2) :: _ ->
5092 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5100 (* Ignore functions that have no tests. We generate a
5101 * warning when the user does 'make check' instead.
5103 | name, _, _, _, [], _, _ -> ()
5104 | name, _, _, _, tests, _, _ ->
5108 match seq_of_test test with
5110 failwithf "%s has a test containing an empty sequence" name
5111 | cmds -> List.map List.hd cmds
5113 let funcs = List.flatten funcs in
5115 let tested = List.mem name funcs in
5118 failwithf "function %s has tests but does not test itself" name
5121 (* 'pr' prints to the current output file. *)
5122 let chan = ref Pervasives.stdout
5127 let i = count_chars '\n' str in
5128 lines := !lines + i;
5129 output_string !chan str
5132 let copyright_years =
5133 let this_year = 1900 + (localtime (time ())).tm_year in
5134 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5136 (* Generate a header block in a number of standard styles. *)
5137 type comment_style =
5138 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5139 type license = GPLv2plus | LGPLv2plus
5141 let generate_header ?(extra_inputs = []) comment license =
5142 let inputs = "src/generator.ml" :: extra_inputs in
5143 let c = match comment with
5144 | CStyle -> pr "/* "; " *"
5145 | CPlusPlusStyle -> pr "// "; "//"
5146 | HashStyle -> pr "# "; "#"
5147 | OCamlStyle -> pr "(* "; " *"
5148 | HaskellStyle -> pr "{- "; " " in
5149 pr "libguestfs generated file\n";
5150 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5151 List.iter (pr "%s %s\n" c) inputs;
5152 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5154 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5158 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5159 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5160 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5161 pr "%s (at your option) any later version.\n" c;
5163 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5164 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5165 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5166 pr "%s GNU General Public License for more details.\n" c;
5168 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5169 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5170 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5173 pr "%s This library is free software; you can redistribute it and/or\n" c;
5174 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5175 pr "%s License as published by the Free Software Foundation; either\n" c;
5176 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5178 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5179 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5180 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5181 pr "%s Lesser General Public License for more details.\n" c;
5183 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5184 pr "%s License along with this library; if not, write to the Free Software\n" c;
5185 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5188 | CStyle -> pr " */\n"
5191 | OCamlStyle -> pr " *)\n"
5192 | HaskellStyle -> pr "-}\n"
5196 (* Start of main code generation functions below this line. *)
5198 (* Generate the pod documentation for the C API. *)
5199 let rec generate_actions_pod () =
5201 fun (shortname, style, _, flags, _, _, longdesc) ->
5202 if not (List.mem NotInDocs flags) then (
5203 let name = "guestfs_" ^ shortname in
5204 pr "=head2 %s\n\n" name;
5206 generate_prototype ~extern:false ~handle:"handle" name style;
5208 pr "%s\n\n" longdesc;
5209 (match fst style with
5211 pr "This function returns 0 on success or -1 on error.\n\n"
5213 pr "On error this function returns -1.\n\n"
5215 pr "On error this function returns -1.\n\n"
5217 pr "This function returns a C truth value on success or -1 on error.\n\n"
5219 pr "This function returns a string, or NULL on error.
5220 The string is owned by the guest handle and must I<not> be freed.\n\n"
5221 | RConstOptString _ ->
5222 pr "This function returns a string which may be NULL.
5223 There is way to return an error from this function.
5224 The string is owned by the guest handle and must I<not> be freed.\n\n"
5226 pr "This function returns a string, or NULL on error.
5227 I<The caller must free the returned string after use>.\n\n"
5229 pr "This function returns a NULL-terminated array of strings
5230 (like L<environ(3)>), or NULL if there was an error.
5231 I<The caller must free the strings and the array after use>.\n\n"
5232 | RStruct (_, typ) ->
5233 pr "This function returns a C<struct guestfs_%s *>,
5234 or NULL if there was an error.
5235 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5236 | RStructList (_, typ) ->
5237 pr "This function returns a C<struct guestfs_%s_list *>
5238 (see E<lt>guestfs-structs.hE<gt>),
5239 or NULL if there was an error.
5240 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5242 pr "This function returns a NULL-terminated array of
5243 strings, or NULL if there was an error.
5244 The array of strings will always have length C<2n+1>, where
5245 C<n> keys and values alternate, followed by the trailing NULL entry.
5246 I<The caller must free the strings and the array after use>.\n\n"
5248 pr "This function returns a buffer, or NULL on error.
5249 The size of the returned buffer is written to C<*size_r>.
5250 I<The caller must free the returned buffer after use>.\n\n"
5252 if List.mem ProtocolLimitWarning flags then
5253 pr "%s\n\n" protocol_limit_warning;
5254 if List.mem DangerWillRobinson flags then
5255 pr "%s\n\n" danger_will_robinson;
5256 match deprecation_notice flags with
5258 | Some txt -> pr "%s\n\n" txt
5260 ) all_functions_sorted
5262 and generate_structs_pod () =
5263 (* Structs documentation. *)
5266 pr "=head2 guestfs_%s\n" typ;
5268 pr " struct guestfs_%s {\n" typ;
5271 | name, FChar -> pr " char %s;\n" name
5272 | name, FUInt32 -> pr " uint32_t %s;\n" name
5273 | name, FInt32 -> pr " int32_t %s;\n" name
5274 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5275 | name, FInt64 -> pr " int64_t %s;\n" name
5276 | name, FString -> pr " char *%s;\n" name
5278 pr " /* The next two fields describe a byte array. */\n";
5279 pr " uint32_t %s_len;\n" name;
5280 pr " char *%s;\n" name
5282 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5283 pr " char %s[32];\n" name
5284 | name, FOptPercent ->
5285 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5286 pr " float %s;\n" name
5290 pr " struct guestfs_%s_list {\n" typ;
5291 pr " uint32_t len; /* Number of elements in list. */\n";
5292 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5295 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5296 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5301 and generate_availability_pod () =
5302 (* Availability documentation. *)
5306 fun (group, functions) ->
5307 pr "=item B<%s>\n" group;
5309 pr "The following functions:\n";
5310 List.iter (pr "L</guestfs_%s>\n") functions;
5316 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5317 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5319 * We have to use an underscore instead of a dash because otherwise
5320 * rpcgen generates incorrect code.
5322 * This header is NOT exported to clients, but see also generate_structs_h.
5324 and generate_xdr () =
5325 generate_header CStyle LGPLv2plus;
5327 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5328 pr "typedef string str<>;\n";
5331 (* Internal structures. *)
5335 pr "struct guestfs_int_%s {\n" typ;
5337 | name, FChar -> pr " char %s;\n" name
5338 | name, FString -> pr " string %s<>;\n" name
5339 | name, FBuffer -> pr " opaque %s<>;\n" name
5340 | name, FUUID -> pr " opaque %s[32];\n" name
5341 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5342 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5343 | name, FOptPercent -> pr " float %s;\n" name
5347 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5352 fun (shortname, style, _, _, _, _, _) ->
5353 let name = "guestfs_" ^ shortname in
5355 (match snd style with
5358 pr "struct %s_args {\n" name;
5361 | Pathname n | Device n | Dev_or_Path n | String n ->
5362 pr " string %s<>;\n" n
5363 | OptString n -> pr " str *%s;\n" n
5364 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5365 | Bool n -> pr " bool %s;\n" n
5366 | Int n -> pr " int %s;\n" n
5367 | Int64 n -> pr " hyper %s;\n" n
5368 | FileIn _ | FileOut _ -> ()
5372 (match fst style with
5375 pr "struct %s_ret {\n" name;
5379 pr "struct %s_ret {\n" name;
5380 pr " hyper %s;\n" n;
5383 pr "struct %s_ret {\n" name;
5386 | RConstString _ | RConstOptString _ ->
5387 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5389 pr "struct %s_ret {\n" name;
5390 pr " string %s<>;\n" n;
5393 pr "struct %s_ret {\n" name;
5394 pr " str %s<>;\n" n;
5396 | RStruct (n, typ) ->
5397 pr "struct %s_ret {\n" name;
5398 pr " guestfs_int_%s %s;\n" typ n;
5400 | RStructList (n, typ) ->
5401 pr "struct %s_ret {\n" name;
5402 pr " guestfs_int_%s_list %s;\n" typ n;
5405 pr "struct %s_ret {\n" name;
5406 pr " str %s<>;\n" n;
5409 pr "struct %s_ret {\n" name;
5410 pr " opaque %s<>;\n" n;
5415 (* Table of procedure numbers. *)
5416 pr "enum guestfs_procedure {\n";
5418 fun (shortname, _, proc_nr, _, _, _, _) ->
5419 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5421 pr " GUESTFS_PROC_NR_PROCS\n";
5425 (* Having to choose a maximum message size is annoying for several
5426 * reasons (it limits what we can do in the API), but it (a) makes
5427 * the protocol a lot simpler, and (b) provides a bound on the size
5428 * of the daemon which operates in limited memory space.
5430 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5433 (* Message header, etc. *)
5435 /* The communication protocol is now documented in the guestfs(3)
5439 const GUESTFS_PROGRAM = 0x2000F5F5;
5440 const GUESTFS_PROTOCOL_VERSION = 1;
5442 /* These constants must be larger than any possible message length. */
5443 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5444 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5446 enum guestfs_message_direction {
5447 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5448 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5451 enum guestfs_message_status {
5452 GUESTFS_STATUS_OK = 0,
5453 GUESTFS_STATUS_ERROR = 1
5456 const GUESTFS_ERROR_LEN = 256;
5458 struct guestfs_message_error {
5459 string error_message<GUESTFS_ERROR_LEN>;
5462 struct guestfs_message_header {
5463 unsigned prog; /* GUESTFS_PROGRAM */
5464 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5465 guestfs_procedure proc; /* GUESTFS_PROC_x */
5466 guestfs_message_direction direction;
5467 unsigned serial; /* message serial number */
5468 guestfs_message_status status;
5471 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5473 struct guestfs_chunk {
5474 int cancel; /* if non-zero, transfer is cancelled */
5475 /* data size is 0 bytes if the transfer has finished successfully */
5476 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5480 (* Generate the guestfs-structs.h file. *)
5481 and generate_structs_h () =
5482 generate_header CStyle LGPLv2plus;
5484 (* This is a public exported header file containing various
5485 * structures. The structures are carefully written to have
5486 * exactly the same in-memory format as the XDR structures that
5487 * we use on the wire to the daemon. The reason for creating
5488 * copies of these structures here is just so we don't have to
5489 * export the whole of guestfs_protocol.h (which includes much
5490 * unrelated and XDR-dependent stuff that we don't want to be
5491 * public, or required by clients).
5493 * To reiterate, we will pass these structures to and from the
5494 * client with a simple assignment or memcpy, so the format
5495 * must be identical to what rpcgen / the RFC defines.
5498 (* Public structures. *)
5501 pr "struct guestfs_%s {\n" typ;
5504 | name, FChar -> pr " char %s;\n" name
5505 | name, FString -> pr " char *%s;\n" name
5507 pr " uint32_t %s_len;\n" name;
5508 pr " char *%s;\n" name
5509 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5510 | name, FUInt32 -> pr " uint32_t %s;\n" name
5511 | name, FInt32 -> pr " int32_t %s;\n" name
5512 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5513 | name, FInt64 -> pr " int64_t %s;\n" name
5514 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5518 pr "struct guestfs_%s_list {\n" typ;
5519 pr " uint32_t len;\n";
5520 pr " struct guestfs_%s *val;\n" typ;
5523 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5524 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5528 (* Generate the guestfs-actions.h file. *)
5529 and generate_actions_h () =
5530 generate_header CStyle LGPLv2plus;
5532 fun (shortname, style, _, _, _, _, _) ->
5533 let name = "guestfs_" ^ shortname in
5534 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5538 (* Generate the guestfs-internal-actions.h file. *)
5539 and generate_internal_actions_h () =
5540 generate_header CStyle LGPLv2plus;
5542 fun (shortname, style, _, _, _, _, _) ->
5543 let name = "guestfs__" ^ shortname in
5544 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5546 ) non_daemon_functions
5548 (* Generate the client-side dispatch stubs. *)
5549 and generate_client_actions () =
5550 generate_header CStyle LGPLv2plus;
5557 #include <inttypes.h>
5559 #include \"guestfs.h\"
5560 #include \"guestfs-internal.h\"
5561 #include \"guestfs-internal-actions.h\"
5562 #include \"guestfs_protocol.h\"
5564 #define error guestfs_error
5565 //#define perrorf guestfs_perrorf
5566 #define safe_malloc guestfs_safe_malloc
5567 #define safe_realloc guestfs_safe_realloc
5568 //#define safe_strdup guestfs_safe_strdup
5569 #define safe_memdup guestfs_safe_memdup
5571 /* Check the return message from a call for validity. */
5573 check_reply_header (guestfs_h *g,
5574 const struct guestfs_message_header *hdr,
5575 unsigned int proc_nr, unsigned int serial)
5577 if (hdr->prog != GUESTFS_PROGRAM) {
5578 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5581 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5582 error (g, \"wrong protocol version (%%d/%%d)\",
5583 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5586 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5587 error (g, \"unexpected message direction (%%d/%%d)\",
5588 hdr->direction, GUESTFS_DIRECTION_REPLY);
5591 if (hdr->proc != proc_nr) {
5592 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5595 if (hdr->serial != serial) {
5596 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5603 /* Check we are in the right state to run a high-level action. */
5605 check_state (guestfs_h *g, const char *caller)
5607 if (!guestfs__is_ready (g)) {
5608 if (guestfs__is_config (g) || guestfs__is_launching (g))
5609 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5612 error (g, \"%%s called from the wrong state, %%d != READY\",
5613 caller, guestfs__get_state (g));
5621 (* Generate code to generate guestfish call traces. *)
5622 let trace_call shortname style =
5623 pr " if (guestfs__get_trace (g)) {\n";
5626 List.exists (function
5627 | StringList _ | DeviceList _ -> true
5628 | _ -> false) (snd style) in
5634 pr " printf (\"%s\");\n" shortname;
5637 | String n (* strings *)
5643 (* guestfish doesn't support string escaping, so neither do we *)
5644 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5645 | OptString n -> (* string option *)
5646 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5647 pr " else printf (\" null\");\n"
5649 | DeviceList n -> (* string list *)
5650 pr " putchar (' ');\n";
5651 pr " putchar ('\"');\n";
5652 pr " for (i = 0; %s[i]; ++i) {\n" n;
5653 pr " if (i > 0) putchar (' ');\n";
5654 pr " fputs (%s[i], stdout);\n" n;
5656 pr " putchar ('\"');\n";
5657 | Bool n -> (* boolean *)
5658 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5659 | Int n -> (* int *)
5660 pr " printf (\" %%d\", %s);\n" n
5662 pr " printf (\" %%\" PRIi64, %s);\n" n
5664 pr " putchar ('\\n');\n";
5669 (* For non-daemon functions, generate a wrapper around each function. *)
5671 fun (shortname, style, _, _, _, _, _) ->
5672 let name = "guestfs_" ^ shortname in
5674 generate_prototype ~extern:false ~semicolon:false ~newline:true
5675 ~handle:"g" name style;
5677 trace_call shortname style;
5678 pr " return guestfs__%s " shortname;
5679 generate_c_call_args ~handle:"g" style;
5683 ) non_daemon_functions;
5685 (* Client-side stubs for each function. *)
5687 fun (shortname, style, _, _, _, _, _) ->
5688 let name = "guestfs_" ^ shortname in
5690 (* Generate the action stub. *)
5691 generate_prototype ~extern:false ~semicolon:false ~newline:true
5692 ~handle:"g" name style;
5695 match fst style with
5696 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5697 | RConstString _ | RConstOptString _ ->
5698 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5699 | RString _ | RStringList _
5700 | RStruct _ | RStructList _
5701 | RHashtable _ | RBufferOut _ ->
5706 (match snd style with
5708 | _ -> pr " struct %s_args args;\n" name
5711 pr " guestfs_message_header hdr;\n";
5712 pr " guestfs_message_error err;\n";
5714 match fst style with
5716 | RConstString _ | RConstOptString _ ->
5717 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5719 | RBool _ | RString _ | RStringList _
5720 | RStruct _ | RStructList _
5721 | RHashtable _ | RBufferOut _ ->
5722 pr " struct %s_ret ret;\n" name;
5725 pr " int serial;\n";
5728 trace_call shortname style;
5729 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5730 pr " guestfs___set_busy (g);\n";
5733 (* Send the main header and arguments. *)
5734 (match snd style with
5736 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5737 (String.uppercase shortname)
5741 | Pathname n | Device n | Dev_or_Path n | String n ->
5742 pr " args.%s = (char *) %s;\n" n n
5744 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5745 | StringList n | DeviceList n ->
5746 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5747 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5749 pr " args.%s = %s;\n" n n
5751 pr " args.%s = %s;\n" n n
5753 pr " args.%s = %s;\n" n n
5754 | FileIn _ | FileOut _ -> ()
5756 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5757 (String.uppercase shortname);
5758 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5761 pr " if (serial == -1) {\n";
5762 pr " guestfs___end_busy (g);\n";
5763 pr " return %s;\n" error_code;
5767 (* Send any additional files (FileIn) requested. *)
5768 let need_read_reply_label = ref false in
5772 pr " r = guestfs___send_file (g, %s);\n" n;
5773 pr " if (r == -1) {\n";
5774 pr " guestfs___end_busy (g);\n";
5775 pr " return %s;\n" error_code;
5777 pr " if (r == -2) /* daemon cancelled */\n";
5778 pr " goto read_reply;\n";
5779 need_read_reply_label := true;
5784 (* Wait for the reply from the remote end. *)
5785 if !need_read_reply_label then pr " read_reply:\n";
5786 pr " memset (&hdr, 0, sizeof hdr);\n";
5787 pr " memset (&err, 0, sizeof err);\n";
5788 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5790 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5794 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5797 pr " if (r == -1) {\n";
5798 pr " guestfs___end_busy (g);\n";
5799 pr " return %s;\n" error_code;
5803 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5804 (String.uppercase shortname);
5805 pr " guestfs___end_busy (g);\n";
5806 pr " return %s;\n" error_code;
5810 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5811 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5812 pr " free (err.error_message);\n";
5813 pr " guestfs___end_busy (g);\n";
5814 pr " return %s;\n" error_code;
5818 (* Expecting to receive further files (FileOut)? *)
5822 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5823 pr " guestfs___end_busy (g);\n";
5824 pr " return %s;\n" error_code;
5830 pr " guestfs___end_busy (g);\n";
5832 (match fst style with
5833 | RErr -> pr " return 0;\n"
5834 | RInt n | RInt64 n | RBool n ->
5835 pr " return ret.%s;\n" n
5836 | RConstString _ | RConstOptString _ ->
5837 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5839 pr " return ret.%s; /* caller will free */\n" n
5840 | RStringList n | RHashtable n ->
5841 pr " /* caller will free this, but we need to add a NULL entry */\n";
5842 pr " ret.%s.%s_val =\n" n n;
5843 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5844 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5846 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5847 pr " return ret.%s.%s_val;\n" n n
5849 pr " /* caller will free this */\n";
5850 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5851 | RStructList (n, _) ->
5852 pr " /* caller will free this */\n";
5853 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5855 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5856 pr " * _val might be NULL here. To make the API saner for\n";
5857 pr " * callers, we turn this case into a unique pointer (using\n";
5858 pr " * malloc(1)).\n";
5860 pr " if (ret.%s.%s_len > 0) {\n" n n;
5861 pr " *size_r = ret.%s.%s_len;\n" n n;
5862 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5864 pr " free (ret.%s.%s_val);\n" n n;
5865 pr " char *p = safe_malloc (g, 1);\n";
5866 pr " *size_r = ret.%s.%s_len;\n" n n;
5874 (* Functions to free structures. *)
5875 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5876 pr " * structure format is identical to the XDR format. See note in\n";
5877 pr " * generator.ml.\n";
5884 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5886 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5892 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5894 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5901 (* Generate daemon/actions.h. *)
5902 and generate_daemon_actions_h () =
5903 generate_header CStyle GPLv2plus;
5905 pr "#include \"../src/guestfs_protocol.h\"\n";
5909 fun (name, style, _, _, _, _, _) ->
5911 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5915 (* Generate the linker script which controls the visibility of
5916 * symbols in the public ABI and ensures no other symbols get
5917 * exported accidentally.
5919 and generate_linker_script () =
5920 generate_header HashStyle GPLv2plus;
5925 "guestfs_get_error_handler";
5926 "guestfs_get_out_of_memory_handler";
5927 "guestfs_last_error";
5928 "guestfs_set_error_handler";
5929 "guestfs_set_launch_done_callback";
5930 "guestfs_set_log_message_callback";
5931 "guestfs_set_out_of_memory_handler";
5932 "guestfs_set_subprocess_quit_callback";
5934 (* Unofficial parts of the API: the bindings code use these
5935 * functions, so it is useful to export them.
5937 "guestfs_safe_calloc";
5938 "guestfs_safe_malloc";
5941 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5945 List.map (fun (typ, _) ->
5946 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5949 let globals = List.sort compare (globals @ functions @ structs) in
5953 List.iter (pr " %s;\n") globals;
5960 (* Generate the server-side stubs. *)
5961 and generate_daemon_actions () =
5962 generate_header CStyle GPLv2plus;
5964 pr "#include <config.h>\n";
5966 pr "#include <stdio.h>\n";
5967 pr "#include <stdlib.h>\n";
5968 pr "#include <string.h>\n";
5969 pr "#include <inttypes.h>\n";
5970 pr "#include <rpc/types.h>\n";
5971 pr "#include <rpc/xdr.h>\n";
5973 pr "#include \"daemon.h\"\n";
5974 pr "#include \"c-ctype.h\"\n";
5975 pr "#include \"../src/guestfs_protocol.h\"\n";
5976 pr "#include \"actions.h\"\n";
5980 fun (name, style, _, _, _, _, _) ->
5981 (* Generate server-side stubs. *)
5982 pr "static void %s_stub (XDR *xdr_in)\n" name;
5985 match fst style with
5986 | RErr | RInt _ -> pr " int r;\n"; "-1"
5987 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5988 | RBool _ -> pr " int r;\n"; "-1"
5989 | RConstString _ | RConstOptString _ ->
5990 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5991 | RString _ -> pr " char *r;\n"; "NULL"
5992 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5993 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5994 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5996 pr " size_t size = 1;\n";
6000 (match snd style with
6003 pr " struct guestfs_%s_args args;\n" name;
6006 | Device n | Dev_or_Path n
6009 | OptString n -> pr " char *%s;\n" n
6010 | StringList n | DeviceList n -> pr " char **%s;\n" n
6011 | Bool n -> pr " int %s;\n" n
6012 | Int n -> pr " int %s;\n" n
6013 | Int64 n -> pr " int64_t %s;\n" n
6014 | FileIn _ | FileOut _ -> ()
6019 (match snd style with
6022 pr " memset (&args, 0, sizeof args);\n";
6024 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6025 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6029 pr " char *%s = args.%s;\n" n n
6031 let pr_list_handling_code n =
6032 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6033 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6034 pr " if (%s == NULL) {\n" n;
6035 pr " reply_with_perror (\"realloc\");\n";
6038 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6039 pr " args.%s.%s_val = %s;\n" n n n;
6045 pr " ABS_PATH (%s, goto done);\n" n;
6048 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6051 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6052 | String n -> pr_args n
6053 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6055 pr_list_handling_code n;
6057 pr_list_handling_code n;
6058 pr " /* Ensure that each is a device,\n";
6059 pr " * and perform device name translation. */\n";
6060 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6061 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6063 | Bool n -> pr " %s = args.%s;\n" n n
6064 | Int n -> pr " %s = args.%s;\n" n n
6065 | Int64 n -> pr " %s = args.%s;\n" n n
6066 | FileIn _ | FileOut _ -> ()
6072 (* this is used at least for do_equal *)
6073 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6074 (* Emit NEED_ROOT just once, even when there are two or
6075 more Pathname args *)
6076 pr " NEED_ROOT (goto done);\n";
6079 (* Don't want to call the impl with any FileIn or FileOut
6080 * parameters, since these go "outside" the RPC protocol.
6083 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6085 pr " r = do_%s " name;
6086 generate_c_call_args (fst style, args');
6089 (match fst style with
6090 | RErr | RInt _ | RInt64 _ | RBool _
6091 | RConstString _ | RConstOptString _
6092 | RString _ | RStringList _ | RHashtable _
6093 | RStruct (_, _) | RStructList (_, _) ->
6094 pr " if (r == %s)\n" error_code;
6095 pr " /* do_%s has already called reply_with_error */\n" name;
6099 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6100 pr " * an ordinary zero-length buffer), so be careful ...\n";
6102 pr " if (size == 1 && r == %s)\n" error_code;
6103 pr " /* do_%s has already called reply_with_error */\n" name;
6108 (* If there are any FileOut parameters, then the impl must
6109 * send its own reply.
6112 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6114 pr " /* do_%s has already sent a reply */\n" name
6116 match fst style with
6117 | RErr -> pr " reply (NULL, NULL);\n"
6118 | RInt n | RInt64 n | RBool n ->
6119 pr " struct guestfs_%s_ret ret;\n" name;
6120 pr " ret.%s = r;\n" n;
6121 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6123 | RConstString _ | RConstOptString _ ->
6124 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6126 pr " struct guestfs_%s_ret ret;\n" name;
6127 pr " ret.%s = r;\n" n;
6128 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6131 | RStringList n | RHashtable n ->
6132 pr " struct guestfs_%s_ret ret;\n" name;
6133 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6134 pr " ret.%s.%s_val = r;\n" n n;
6135 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6137 pr " free_strings (r);\n"
6139 pr " struct guestfs_%s_ret ret;\n" name;
6140 pr " ret.%s = *r;\n" n;
6141 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6143 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6145 | RStructList (n, _) ->
6146 pr " struct guestfs_%s_ret ret;\n" name;
6147 pr " ret.%s = *r;\n" n;
6148 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6150 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6153 pr " struct guestfs_%s_ret ret;\n" name;
6154 pr " ret.%s.%s_val = r;\n" n n;
6155 pr " ret.%s.%s_len = size;\n" n n;
6156 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6161 (* Free the args. *)
6162 (match snd style with
6167 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6174 (* Dispatch function. *)
6175 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6177 pr " switch (proc_nr) {\n";
6180 fun (name, style, _, _, _, _, _) ->
6181 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6182 pr " %s_stub (xdr_in);\n" name;
6187 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";
6192 (* LVM columns and tokenization functions. *)
6193 (* XXX This generates crap code. We should rethink how we
6199 pr "static const char *lvm_%s_cols = \"%s\";\n"
6200 typ (String.concat "," (List.map fst cols));
6203 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6205 pr " char *tok, *p, *next;\n";
6209 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6212 pr " if (!str) {\n";
6213 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6216 pr " if (!*str || c_isspace (*str)) {\n";
6217 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6222 fun (name, coltype) ->
6223 pr " if (!tok) {\n";
6224 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6227 pr " p = strchrnul (tok, ',');\n";
6228 pr " if (*p) next = p+1; else next = NULL;\n";
6229 pr " *p = '\\0';\n";
6232 pr " r->%s = strdup (tok);\n" name;
6233 pr " if (r->%s == NULL) {\n" name;
6234 pr " perror (\"strdup\");\n";
6238 pr " for (i = j = 0; i < 32; ++j) {\n";
6239 pr " if (tok[j] == '\\0') {\n";
6240 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6242 pr " } else if (tok[j] != '-')\n";
6243 pr " r->%s[i++] = tok[j];\n" name;
6246 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6247 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6251 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6252 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6256 pr " if (tok[0] == '\\0')\n";
6257 pr " r->%s = -1;\n" name;
6258 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6259 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6262 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6263 assert false (* can never be an LVM column *)
6265 pr " tok = next;\n";
6268 pr " if (tok != NULL) {\n";
6269 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6276 pr "guestfs_int_lvm_%s_list *\n" typ;
6277 pr "parse_command_line_%ss (void)\n" typ;
6279 pr " char *out, *err;\n";
6280 pr " char *p, *pend;\n";
6282 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6283 pr " void *newp;\n";
6285 pr " ret = malloc (sizeof *ret);\n";
6286 pr " if (!ret) {\n";
6287 pr " reply_with_perror (\"malloc\");\n";
6288 pr " return NULL;\n";
6291 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6292 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6294 pr " r = command (&out, &err,\n";
6295 pr " \"lvm\", \"%ss\",\n" typ;
6296 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6297 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6298 pr " if (r == -1) {\n";
6299 pr " reply_with_error (\"%%s\", err);\n";
6300 pr " free (out);\n";
6301 pr " free (err);\n";
6302 pr " free (ret);\n";
6303 pr " return NULL;\n";
6306 pr " free (err);\n";
6308 pr " /* Tokenize each line of the output. */\n";
6311 pr " while (p) {\n";
6312 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6313 pr " if (pend) {\n";
6314 pr " *pend = '\\0';\n";
6318 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6321 pr " if (!*p) { /* Empty line? Skip it. */\n";
6326 pr " /* Allocate some space to store this next entry. */\n";
6327 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6328 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6329 pr " if (newp == NULL) {\n";
6330 pr " reply_with_perror (\"realloc\");\n";
6331 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6332 pr " free (ret);\n";
6333 pr " free (out);\n";
6334 pr " return NULL;\n";
6336 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6338 pr " /* Tokenize the next entry. */\n";
6339 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6340 pr " if (r == -1) {\n";
6341 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6342 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6343 pr " free (ret);\n";
6344 pr " free (out);\n";
6345 pr " return NULL;\n";
6352 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6354 pr " free (out);\n";
6355 pr " return ret;\n";
6358 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6360 (* Generate a list of function names, for debugging in the daemon.. *)
6361 and generate_daemon_names () =
6362 generate_header CStyle GPLv2plus;
6364 pr "#include <config.h>\n";
6366 pr "#include \"daemon.h\"\n";
6369 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6370 pr "const char *function_names[] = {\n";
6372 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6376 (* Generate the optional groups for the daemon to implement
6377 * guestfs_available.
6379 and generate_daemon_optgroups_c () =
6380 generate_header CStyle GPLv2plus;
6382 pr "#include <config.h>\n";
6384 pr "#include \"daemon.h\"\n";
6385 pr "#include \"optgroups.h\"\n";
6388 pr "struct optgroup optgroups[] = {\n";
6391 pr " { \"%s\", optgroup_%s_available },\n" group group
6393 pr " { NULL, NULL }\n";
6396 and generate_daemon_optgroups_h () =
6397 generate_header CStyle GPLv2plus;
6401 pr "extern int optgroup_%s_available (void);\n" group
6404 (* Generate the tests. *)
6405 and generate_tests () =
6406 generate_header CStyle GPLv2plus;
6413 #include <sys/types.h>
6416 #include \"guestfs.h\"
6417 #include \"guestfs-internal.h\"
6419 static guestfs_h *g;
6420 static int suppress_error = 0;
6422 static void print_error (guestfs_h *g, void *data, const char *msg)
6424 if (!suppress_error)
6425 fprintf (stderr, \"%%s\\n\", msg);
6428 /* FIXME: nearly identical code appears in fish.c */
6429 static void print_strings (char *const *argv)
6433 for (argc = 0; argv[argc] != NULL; ++argc)
6434 printf (\"\\t%%s\\n\", argv[argc]);
6438 static void print_table (char const *const *argv)
6442 for (i = 0; argv[i] != NULL; i += 2)
6443 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6449 (* Generate a list of commands which are not tested anywhere. *)
6450 pr "static void no_test_warnings (void)\n";
6453 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6455 fun (_, _, _, _, tests, _, _) ->
6456 let tests = filter_map (
6458 | (_, (Always|If _|Unless _), test) -> Some test
6459 | (_, Disabled, _) -> None
6461 let seq = List.concat (List.map seq_of_test tests) in
6462 let cmds_tested = List.map List.hd seq in
6463 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6467 fun (name, _, _, _, _, _, _) ->
6468 if not (Hashtbl.mem hash name) then
6469 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6475 (* Generate the actual tests. Note that we generate the tests
6476 * in reverse order, deliberately, so that (in general) the
6477 * newest tests run first. This makes it quicker and easier to
6482 fun (name, _, _, flags, tests, _, _) ->
6483 mapi (generate_one_test name flags) tests
6484 ) (List.rev all_functions) in
6485 let test_names = List.concat test_names in
6486 let nr_tests = List.length test_names in
6489 int main (int argc, char *argv[])
6492 unsigned long int n_failed = 0;
6493 const char *filename;
6495 int nr_tests, test_num = 0;
6497 setbuf (stdout, NULL);
6499 no_test_warnings ();
6501 g = guestfs_create ();
6503 printf (\"guestfs_create FAILED\\n\");
6504 exit (EXIT_FAILURE);
6507 guestfs_set_error_handler (g, print_error, NULL);
6509 guestfs_set_path (g, \"../appliance\");
6511 filename = \"test1.img\";
6512 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6515 exit (EXIT_FAILURE);
6517 if (lseek (fd, %d, SEEK_SET) == -1) {
6521 exit (EXIT_FAILURE);
6523 if (write (fd, &c, 1) == -1) {
6527 exit (EXIT_FAILURE);
6529 if (close (fd) == -1) {
6532 exit (EXIT_FAILURE);
6534 if (guestfs_add_drive (g, filename) == -1) {
6535 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6536 exit (EXIT_FAILURE);
6539 filename = \"test2.img\";
6540 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6543 exit (EXIT_FAILURE);
6545 if (lseek (fd, %d, SEEK_SET) == -1) {
6549 exit (EXIT_FAILURE);
6551 if (write (fd, &c, 1) == -1) {
6555 exit (EXIT_FAILURE);
6557 if (close (fd) == -1) {
6560 exit (EXIT_FAILURE);
6562 if (guestfs_add_drive (g, filename) == -1) {
6563 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6564 exit (EXIT_FAILURE);
6567 filename = \"test3.img\";
6568 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6571 exit (EXIT_FAILURE);
6573 if (lseek (fd, %d, SEEK_SET) == -1) {
6577 exit (EXIT_FAILURE);
6579 if (write (fd, &c, 1) == -1) {
6583 exit (EXIT_FAILURE);
6585 if (close (fd) == -1) {
6588 exit (EXIT_FAILURE);
6590 if (guestfs_add_drive (g, filename) == -1) {
6591 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6592 exit (EXIT_FAILURE);
6595 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6596 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6597 exit (EXIT_FAILURE);
6600 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6603 if (guestfs_launch (g) == -1) {
6604 printf (\"guestfs_launch FAILED\\n\");
6605 exit (EXIT_FAILURE);
6608 /* Cancel previous alarm. */
6613 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6617 pr " test_num++;\n";
6618 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6619 pr " if (%s () == -1) {\n" test_name;
6620 pr " printf (\"%s FAILED\\n\");\n" test_name;
6621 pr " n_failed++;\n";
6626 pr " guestfs_close (g);\n";
6627 pr " unlink (\"test1.img\");\n";
6628 pr " unlink (\"test2.img\");\n";
6629 pr " unlink (\"test3.img\");\n";
6632 pr " if (n_failed > 0) {\n";
6633 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6634 pr " exit (EXIT_FAILURE);\n";
6638 pr " exit (EXIT_SUCCESS);\n";
6641 and generate_one_test name flags i (init, prereq, test) =
6642 let test_name = sprintf "test_%s_%d" name i in
6645 static int %s_skip (void)
6649 str = getenv (\"TEST_ONLY\");
6651 return strstr (str, \"%s\") == NULL;
6652 str = getenv (\"SKIP_%s\");
6653 if (str && STREQ (str, \"1\")) return 1;
6654 str = getenv (\"SKIP_TEST_%s\");
6655 if (str && STREQ (str, \"1\")) return 1;
6659 " test_name name (String.uppercase test_name) (String.uppercase name);
6662 | Disabled | Always -> ()
6663 | If code | Unless code ->
6664 pr "static int %s_prereq (void)\n" test_name;
6672 static int %s (void)
6675 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6679 " test_name test_name test_name;
6681 (* Optional functions should only be tested if the relevant
6682 * support is available in the daemon.
6688 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6690 pr " suppress_error = 1;\n";
6691 pr " r = guestfs_available (g, (char **) groups);\n";
6692 pr " suppress_error = 0;\n";
6693 pr " if (r == -1) {\n";
6694 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6703 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6705 pr " if (! %s_prereq ()) {\n" test_name;
6706 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6710 generate_one_test_body name i test_name init test;
6712 pr " if (%s_prereq ()) {\n" test_name;
6713 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6717 generate_one_test_body name i test_name init test;
6719 generate_one_test_body name i test_name init test
6727 and generate_one_test_body name i test_name init test =
6729 | InitNone (* XXX at some point, InitNone and InitEmpty became
6730 * folded together as the same thing. Really we should
6731 * make InitNone do nothing at all, but the tests may
6732 * need to be checked to make sure this is OK.
6735 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6736 List.iter (generate_test_command_call test_name)
6737 [["blockdev_setrw"; "/dev/sda"];
6741 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6742 List.iter (generate_test_command_call test_name)
6743 [["blockdev_setrw"; "/dev/sda"];
6746 ["part_disk"; "/dev/sda"; "mbr"]]
6748 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6749 List.iter (generate_test_command_call test_name)
6750 [["blockdev_setrw"; "/dev/sda"];
6753 ["part_disk"; "/dev/sda"; "mbr"];
6754 ["mkfs"; "ext2"; "/dev/sda1"];
6755 ["mount_options"; ""; "/dev/sda1"; "/"]]
6756 | InitBasicFSonLVM ->
6757 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6759 List.iter (generate_test_command_call test_name)
6760 [["blockdev_setrw"; "/dev/sda"];
6763 ["part_disk"; "/dev/sda"; "mbr"];
6764 ["pvcreate"; "/dev/sda1"];
6765 ["vgcreate"; "VG"; "/dev/sda1"];
6766 ["lvcreate"; "LV"; "VG"; "8"];
6767 ["mkfs"; "ext2"; "/dev/VG/LV"];
6768 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6770 pr " /* InitISOFS for %s */\n" test_name;
6771 List.iter (generate_test_command_call test_name)
6772 [["blockdev_setrw"; "/dev/sda"];
6775 ["mount_ro"; "/dev/sdd"; "/"]]
6778 let get_seq_last = function
6780 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6783 let seq = List.rev seq in
6784 List.rev (List.tl seq), List.hd seq
6789 pr " /* TestRun for %s (%d) */\n" name i;
6790 List.iter (generate_test_command_call test_name) seq
6791 | TestOutput (seq, expected) ->
6792 pr " /* TestOutput for %s (%d) */\n" name i;
6793 pr " const char *expected = \"%s\";\n" (c_quote expected);
6794 let seq, last = get_seq_last seq in
6796 pr " if (STRNEQ (r, expected)) {\n";
6797 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6801 List.iter (generate_test_command_call test_name) seq;
6802 generate_test_command_call ~test test_name last
6803 | TestOutputList (seq, expected) ->
6804 pr " /* TestOutputList for %s (%d) */\n" name i;
6805 let seq, last = get_seq_last seq in
6809 pr " if (!r[%d]) {\n" i;
6810 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6811 pr " print_strings (r);\n";
6815 pr " const char *expected = \"%s\";\n" (c_quote str);
6816 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6817 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6822 pr " if (r[%d] != NULL) {\n" (List.length expected);
6823 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6825 pr " print_strings (r);\n";
6829 List.iter (generate_test_command_call test_name) seq;
6830 generate_test_command_call ~test test_name last
6831 | TestOutputListOfDevices (seq, expected) ->
6832 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6833 let seq, last = get_seq_last seq in
6837 pr " if (!r[%d]) {\n" i;
6838 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6839 pr " print_strings (r);\n";
6843 pr " const char *expected = \"%s\";\n" (c_quote str);
6844 pr " r[%d][5] = 's';\n" i;
6845 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6846 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6851 pr " if (r[%d] != NULL) {\n" (List.length expected);
6852 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6854 pr " print_strings (r);\n";
6858 List.iter (generate_test_command_call test_name) seq;
6859 generate_test_command_call ~test test_name last
6860 | TestOutputInt (seq, expected) ->
6861 pr " /* TestOutputInt for %s (%d) */\n" name i;
6862 let seq, last = get_seq_last seq in
6864 pr " if (r != %d) {\n" expected;
6865 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6871 List.iter (generate_test_command_call test_name) seq;
6872 generate_test_command_call ~test test_name last
6873 | TestOutputIntOp (seq, op, expected) ->
6874 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6875 let seq, last = get_seq_last seq in
6877 pr " if (! (r %s %d)) {\n" op expected;
6878 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6879 test_name op expected;
6884 List.iter (generate_test_command_call test_name) seq;
6885 generate_test_command_call ~test test_name last
6886 | TestOutputTrue seq ->
6887 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6888 let seq, last = get_seq_last seq in
6891 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6896 List.iter (generate_test_command_call test_name) seq;
6897 generate_test_command_call ~test test_name last
6898 | TestOutputFalse seq ->
6899 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6900 let seq, last = get_seq_last seq in
6903 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6908 List.iter (generate_test_command_call test_name) seq;
6909 generate_test_command_call ~test test_name last
6910 | TestOutputLength (seq, expected) ->
6911 pr " /* TestOutputLength for %s (%d) */\n" name i;
6912 let seq, last = get_seq_last seq in
6915 pr " for (j = 0; j < %d; ++j)\n" expected;
6916 pr " if (r[j] == NULL) {\n";
6917 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6919 pr " print_strings (r);\n";
6922 pr " if (r[j] != NULL) {\n";
6923 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6925 pr " print_strings (r);\n";
6929 List.iter (generate_test_command_call test_name) seq;
6930 generate_test_command_call ~test test_name last
6931 | TestOutputBuffer (seq, expected) ->
6932 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6933 pr " const char *expected = \"%s\";\n" (c_quote expected);
6934 let seq, last = get_seq_last seq in
6935 let len = String.length expected in
6937 pr " if (size != %d) {\n" len;
6938 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6941 pr " if (STRNEQLEN (r, expected, size)) {\n";
6942 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6946 List.iter (generate_test_command_call test_name) seq;
6947 generate_test_command_call ~test test_name last
6948 | TestOutputStruct (seq, checks) ->
6949 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6950 let seq, last = get_seq_last seq in
6954 | CompareWithInt (field, expected) ->
6955 pr " if (r->%s != %d) {\n" field expected;
6956 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6957 test_name field expected;
6958 pr " (int) r->%s);\n" field;
6961 | CompareWithIntOp (field, op, expected) ->
6962 pr " if (!(r->%s %s %d)) {\n" field op expected;
6963 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6964 test_name field op expected;
6965 pr " (int) r->%s);\n" field;
6968 | CompareWithString (field, expected) ->
6969 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6970 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6971 test_name field expected;
6972 pr " r->%s);\n" field;
6975 | CompareFieldsIntEq (field1, field2) ->
6976 pr " if (r->%s != r->%s) {\n" field1 field2;
6977 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6978 test_name field1 field2;
6979 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6982 | CompareFieldsStrEq (field1, field2) ->
6983 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6984 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6985 test_name field1 field2;
6986 pr " r->%s, r->%s);\n" field1 field2;
6991 List.iter (generate_test_command_call test_name) seq;
6992 generate_test_command_call ~test test_name last
6993 | TestLastFail seq ->
6994 pr " /* TestLastFail for %s (%d) */\n" name i;
6995 let seq, last = get_seq_last seq in
6996 List.iter (generate_test_command_call test_name) seq;
6997 generate_test_command_call test_name ~expect_error:true last
6999 (* Generate the code to run a command, leaving the result in 'r'.
7000 * If you expect to get an error then you should set expect_error:true.
7002 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7004 | [] -> assert false
7006 (* Look up the command to find out what args/ret it has. *)
7009 let _, style, _, _, _, _, _ =
7010 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7013 failwithf "%s: in test, command %s was not found" test_name name in
7015 if List.length (snd style) <> List.length args then
7016 failwithf "%s: in test, wrong number of args given to %s"
7023 | OptString n, "NULL" -> ()
7026 | Dev_or_Path n, arg
7028 | OptString n, arg ->
7029 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7033 | FileIn _, _ | FileOut _, _ -> ()
7034 | StringList n, "" | DeviceList n, "" ->
7035 pr " const char *const %s[1] = { NULL };\n" n
7036 | StringList n, arg | DeviceList n, arg ->
7037 let strs = string_split " " arg in
7040 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7042 pr " const char *const %s[] = {\n" n;
7044 fun i _ -> pr " %s_%d,\n" n i
7048 ) (List.combine (snd style) args);
7051 match fst style with
7052 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7053 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7054 | RConstString _ | RConstOptString _ ->
7055 pr " const char *r;\n"; "NULL"
7056 | RString _ -> pr " char *r;\n"; "NULL"
7057 | RStringList _ | RHashtable _ ->
7061 | RStruct (_, typ) ->
7062 pr " struct guestfs_%s *r;\n" typ; "NULL"
7063 | RStructList (_, typ) ->
7064 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7067 pr " size_t size;\n";
7070 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7071 pr " r = guestfs_%s (g" name;
7073 (* Generate the parameters. *)
7076 | OptString _, "NULL" -> pr ", NULL"
7078 | Device n, _ | Dev_or_Path n, _
7082 | FileIn _, arg | FileOut _, arg ->
7083 pr ", \"%s\"" (c_quote arg)
7084 | StringList n, _ | DeviceList n, _ ->
7085 pr ", (char **) %s" n
7088 try int_of_string arg
7089 with Failure "int_of_string" ->
7090 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7094 try Int64.of_string arg
7095 with Failure "int_of_string" ->
7096 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7099 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7100 ) (List.combine (snd style) args);
7102 (match fst style with
7103 | RBufferOut _ -> pr ", &size"
7109 if not expect_error then
7110 pr " if (r == %s)\n" error_code
7112 pr " if (r != %s)\n" error_code;
7115 (* Insert the test code. *)
7121 (match fst style with
7122 | RErr | RInt _ | RInt64 _ | RBool _
7123 | RConstString _ | RConstOptString _ -> ()
7124 | RString _ | RBufferOut _ -> pr " free (r);\n"
7125 | RStringList _ | RHashtable _ ->
7126 pr " for (i = 0; r[i] != NULL; ++i)\n";
7127 pr " free (r[i]);\n";
7129 | RStruct (_, typ) ->
7130 pr " guestfs_free_%s (r);\n" typ
7131 | RStructList (_, typ) ->
7132 pr " guestfs_free_%s_list (r);\n" typ
7138 let str = replace_str str "\r" "\\r" in
7139 let str = replace_str str "\n" "\\n" in
7140 let str = replace_str str "\t" "\\t" in
7141 let str = replace_str str "\000" "\\0" in
7144 (* Generate a lot of different functions for guestfish. *)
7145 and generate_fish_cmds () =
7146 generate_header CStyle GPLv2plus;
7150 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7152 let all_functions_sorted =
7154 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7155 ) all_functions_sorted in
7157 pr "#include <config.h>\n";
7159 pr "#include <stdio.h>\n";
7160 pr "#include <stdlib.h>\n";
7161 pr "#include <string.h>\n";
7162 pr "#include <inttypes.h>\n";
7164 pr "#include <guestfs.h>\n";
7165 pr "#include \"c-ctype.h\"\n";
7166 pr "#include \"full-write.h\"\n";
7167 pr "#include \"xstrtol.h\"\n";
7168 pr "#include \"fish.h\"\n";
7171 (* list_commands function, which implements guestfish -h *)
7172 pr "void list_commands (void)\n";
7174 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7175 pr " list_builtin_commands ();\n";
7177 fun (name, _, _, flags, _, shortdesc, _) ->
7178 let name = replace_char name '_' '-' in
7179 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7181 ) all_functions_sorted;
7182 pr " printf (\" %%s\\n\",";
7183 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7187 (* display_command function, which implements guestfish -h cmd *)
7188 pr "void display_command (const char *cmd)\n";
7191 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7192 let name2 = replace_char name '_' '-' in
7194 try find_map (function FishAlias n -> Some n | _ -> None) flags
7195 with Not_found -> name in
7196 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7198 match snd style with
7202 name2 (String.concat " " (List.map name_of_argt args)) in
7205 if List.mem ProtocolLimitWarning flags then
7206 ("\n\n" ^ protocol_limit_warning)
7209 (* For DangerWillRobinson commands, we should probably have
7210 * guestfish prompt before allowing you to use them (especially
7211 * in interactive mode). XXX
7215 if List.mem DangerWillRobinson flags then
7216 ("\n\n" ^ danger_will_robinson)
7221 match deprecation_notice flags with
7223 | Some txt -> "\n\n" ^ txt in
7225 let describe_alias =
7226 if name <> alias then
7227 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7231 pr "STRCASEEQ (cmd, \"%s\")" name;
7232 if name <> name2 then
7233 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7234 if name <> alias then
7235 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7237 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7239 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7240 "=head1 DESCRIPTION\n\n" ^
7241 longdesc ^ warnings ^ describe_alias);
7244 pr " display_builtin_command (cmd);\n";
7248 let emit_print_list_function typ =
7249 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7252 pr " unsigned int i;\n";
7254 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7255 pr " printf (\"[%%d] = {\\n\", i);\n";
7256 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7257 pr " printf (\"}\\n\");\n";
7263 (* print_* functions *)
7267 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7269 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7272 pr " unsigned int i;\n";
7278 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7280 pr " printf (\"%%s%s: \", indent);\n" name;
7281 pr " for (i = 0; i < 32; ++i)\n";
7282 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7283 pr " printf (\"\\n\");\n"
7285 pr " printf (\"%%s%s: \", indent);\n" name;
7286 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7287 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7288 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7290 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7291 pr " printf (\"\\n\");\n"
7292 | name, (FUInt64|FBytes) ->
7293 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7296 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7299 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7302 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7305 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7307 | name, FOptPercent ->
7308 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7309 typ name name typ name;
7310 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7316 (* Emit a print_TYPE_list function definition only if that function is used. *)
7319 | typ, (RStructListOnly | RStructAndList) ->
7320 (* generate the function for typ *)
7321 emit_print_list_function typ
7322 | typ, _ -> () (* empty *)
7323 ) (rstructs_used_by all_functions);
7325 (* Emit a print_TYPE function definition only if that function is used. *)
7328 | typ, (RStructOnly | RStructAndList) ->
7329 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7331 pr " print_%s_indent (%s, \"\");\n" typ typ;
7334 | typ, _ -> () (* empty *)
7335 ) (rstructs_used_by all_functions);
7337 (* run_<action> actions *)
7339 fun (name, style, _, flags, _, _, _) ->
7340 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7342 (match fst style with
7345 | RBool _ -> pr " int r;\n"
7346 | RInt64 _ -> pr " int64_t r;\n"
7347 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7348 | RString _ -> pr " char *r;\n"
7349 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7350 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7351 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7354 pr " size_t size;\n";
7362 | FileOut n -> pr " const char *%s;\n" n
7364 | Dev_or_Path n -> pr " char *%s;\n" n
7365 | StringList n | DeviceList n -> pr " char **%s;\n" n
7366 | Bool n -> pr " int %s;\n" n
7367 | Int n -> pr " int %s;\n" n
7368 | Int64 n -> pr " int64_t %s;\n" n
7371 (* Check and convert parameters. *)
7372 let argc_expected = List.length (snd style) in
7373 pr " if (argc != %d) {\n" argc_expected;
7374 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7376 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7380 let parse_integer fn fntyp rtyp range name i =
7382 pr " strtol_error xerr;\n";
7383 pr " %s r;\n" fntyp;
7385 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7386 pr " if (xerr != LONGINT_OK) {\n";
7387 pr " fprintf (stderr,\n";
7388 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7389 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7394 | Some (min, max, comment) ->
7395 pr " /* %s */\n" comment;
7396 pr " if (r < %s || r > %s) {\n" min max;
7397 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7401 pr " /* The check above should ensure this assignment does not overflow. */\n";
7403 pr " %s = r;\n" name;
7412 pr " %s = argv[%d];\n" name i
7414 | Dev_or_Path name ->
7415 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7416 pr " if (%s == NULL) return -1;\n" name
7418 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7421 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7424 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7426 | StringList name | DeviceList name ->
7427 pr " %s = parse_string_list (argv[%d]);\n" name i;
7428 pr " if (%s == NULL) return -1;\n" name;
7430 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7433 let min = "(-(2LL<<30))"
7434 and max = "((2LL<<30)-1)"
7436 "The Int type in the generator is a signed 31 bit int." in
7437 Some (min, max, comment) in
7438 parse_integer "xstrtoll" "long long" "int" range name i
7440 parse_integer "xstrtoll" "long long" "int64_t" None name i
7443 (* Call C API function. *)
7445 try find_map (function FishAction n -> Some n | _ -> None) flags
7446 with Not_found -> sprintf "guestfs_%s" name in
7448 generate_c_call_args ~handle:"g" style;
7453 | Device name | String name
7454 | OptString name | FileIn name | FileOut name | Bool name
7455 | Int name | Int64 name -> ()
7456 | Pathname name | Dev_or_Path name ->
7457 pr " free (%s);\n" name
7458 | StringList name | DeviceList name ->
7459 pr " free_strings (%s);\n" name
7462 (* Any output flags? *)
7464 let flags = filter_map (
7465 function FishOutput flag -> Some flag | _ -> None
7471 failwithf "%s: more than one FishOutput flag is not allowed" name in
7473 (* Check return value for errors and display command results. *)
7474 (match fst style with
7475 | RErr -> pr " return r;\n"
7477 pr " if (r == -1) return -1;\n";
7478 (match fish_output with
7480 pr " printf (\"%%d\\n\", r);\n";
7481 | Some FishOutputOctal ->
7482 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7483 | Some FishOutputHexadecimal ->
7484 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7487 pr " if (r == -1) return -1;\n";
7488 (match fish_output with
7490 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7491 | Some FishOutputOctal ->
7492 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7493 | Some FishOutputHexadecimal ->
7494 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7497 pr " if (r == -1) return -1;\n";
7498 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7501 pr " if (r == NULL) return -1;\n";
7502 pr " printf (\"%%s\\n\", r);\n";
7504 | RConstOptString _ ->
7505 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7508 pr " if (r == NULL) return -1;\n";
7509 pr " printf (\"%%s\\n\", r);\n";
7513 pr " if (r == NULL) return -1;\n";
7514 pr " print_strings (r);\n";
7515 pr " free_strings (r);\n";
7517 | RStruct (_, typ) ->
7518 pr " if (r == NULL) return -1;\n";
7519 pr " print_%s (r);\n" typ;
7520 pr " guestfs_free_%s (r);\n" typ;
7522 | RStructList (_, typ) ->
7523 pr " if (r == NULL) return -1;\n";
7524 pr " print_%s_list (r);\n" typ;
7525 pr " guestfs_free_%s_list (r);\n" typ;
7528 pr " if (r == NULL) return -1;\n";
7529 pr " print_table (r);\n";
7530 pr " free_strings (r);\n";
7533 pr " if (r == NULL) return -1;\n";
7534 pr " if (full_write (1, r, size) != size) {\n";
7535 pr " perror (\"write\");\n";
7546 (* run_action function *)
7547 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7550 fun (name, _, _, flags, _, _, _) ->
7551 let name2 = replace_char name '_' '-' in
7553 try find_map (function FishAlias n -> Some n | _ -> None) flags
7554 with Not_found -> name in
7556 pr "STRCASEEQ (cmd, \"%s\")" name;
7557 if name <> name2 then
7558 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7559 if name <> alias then
7560 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7562 pr " return run_%s (cmd, argc, argv);\n" name;
7566 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7567 pr " if (command_num == 1)\n";
7568 pr " extended_help_message ();\n";
7575 (* Readline completion for guestfish. *)
7576 and generate_fish_completion () =
7577 generate_header CStyle GPLv2plus;
7581 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7591 #ifdef HAVE_LIBREADLINE
7592 #include <readline/readline.h>
7597 #ifdef HAVE_LIBREADLINE
7599 static const char *const commands[] = {
7600 BUILTIN_COMMANDS_FOR_COMPLETION,
7603 (* Get the commands, including the aliases. They don't need to be
7604 * sorted - the generator() function just does a dumb linear search.
7608 fun (name, _, _, flags, _, _, _) ->
7609 let name2 = replace_char name '_' '-' in
7611 try find_map (function FishAlias n -> Some n | _ -> None) flags
7612 with Not_found -> name in
7614 if name <> alias then [name2; alias] else [name2]
7616 let commands = List.flatten commands in
7618 List.iter (pr " \"%s\",\n") commands;
7624 generator (const char *text, int state)
7626 static int index, len;
7631 len = strlen (text);
7634 rl_attempted_completion_over = 1;
7636 while ((name = commands[index]) != NULL) {
7638 if (STRCASEEQLEN (name, text, len))
7639 return strdup (name);
7645 #endif /* HAVE_LIBREADLINE */
7647 #ifdef HAVE_RL_COMPLETION_MATCHES
7648 #define RL_COMPLETION_MATCHES rl_completion_matches
7650 #ifdef HAVE_COMPLETION_MATCHES
7651 #define RL_COMPLETION_MATCHES completion_matches
7653 #endif /* else just fail if we don't have either symbol */
7656 do_completion (const char *text, int start, int end)
7658 char **matches = NULL;
7660 #ifdef HAVE_LIBREADLINE
7661 rl_completion_append_character = ' ';
7664 matches = RL_COMPLETION_MATCHES (text, generator);
7665 else if (complete_dest_paths)
7666 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7673 (* Generate the POD documentation for guestfish. *)
7674 and generate_fish_actions_pod () =
7675 let all_functions_sorted =
7677 fun (_, _, _, flags, _, _, _) ->
7678 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7679 ) all_functions_sorted in
7681 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7684 fun (name, style, _, flags, _, _, longdesc) ->
7686 Str.global_substitute rex (
7689 try Str.matched_group 1 s
7691 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7692 "C<" ^ replace_char sub '_' '-' ^ ">"
7694 let name = replace_char name '_' '-' in
7696 try find_map (function FishAlias n -> Some n | _ -> None) flags
7697 with Not_found -> name in
7699 pr "=head2 %s" name;
7700 if name <> alias then
7707 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7708 | OptString n -> pr " %s" n
7709 | StringList n | DeviceList n -> pr " '%s ...'" n
7710 | Bool _ -> pr " true|false"
7711 | Int n -> pr " %s" n
7712 | Int64 n -> pr " %s" n
7713 | FileIn n | FileOut n -> pr " (%s|-)" n
7717 pr "%s\n\n" longdesc;
7719 if List.exists (function FileIn _ | FileOut _ -> true
7720 | _ -> false) (snd style) then
7721 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7723 if List.mem ProtocolLimitWarning flags then
7724 pr "%s\n\n" protocol_limit_warning;
7726 if List.mem DangerWillRobinson flags then
7727 pr "%s\n\n" danger_will_robinson;
7729 match deprecation_notice flags with
7731 | Some txt -> pr "%s\n\n" txt
7732 ) all_functions_sorted
7734 (* Generate a C function prototype. *)
7735 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7736 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7738 ?handle name style =
7739 if extern then pr "extern ";
7740 if static then pr "static ";
7741 (match fst style with
7743 | RInt _ -> pr "int "
7744 | RInt64 _ -> pr "int64_t "
7745 | RBool _ -> pr "int "
7746 | RConstString _ | RConstOptString _ -> pr "const char *"
7747 | RString _ | RBufferOut _ -> pr "char *"
7748 | RStringList _ | RHashtable _ -> pr "char **"
7749 | RStruct (_, typ) ->
7750 if not in_daemon then pr "struct guestfs_%s *" typ
7751 else pr "guestfs_int_%s *" typ
7752 | RStructList (_, typ) ->
7753 if not in_daemon then pr "struct guestfs_%s_list *" typ
7754 else pr "guestfs_int_%s_list *" typ
7756 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7757 pr "%s%s (" prefix name;
7758 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7761 let comma = ref false in
7764 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7768 if single_line then pr ", " else pr ",\n\t\t"
7775 | Device n | Dev_or_Path n
7779 pr "const char *%s" n
7780 | StringList n | DeviceList n ->
7782 pr "char *const *%s" n
7783 | Bool n -> next (); pr "int %s" n
7784 | Int n -> next (); pr "int %s" n
7785 | Int64 n -> next (); pr "int64_t %s" n
7788 if not in_daemon then (next (); pr "const char *%s" n)
7790 if is_RBufferOut then (next (); pr "size_t *size_r");
7793 if semicolon then pr ";";
7794 if newline then pr "\n"
7796 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7797 and generate_c_call_args ?handle ?(decl = false) style =
7799 let comma = ref false in
7801 if !comma then pr ", ";
7806 | Some handle -> pr "%s" handle; comma := true
7811 pr "%s" (name_of_argt arg)
7813 (* For RBufferOut calls, add implicit &size parameter. *)
7815 match fst style with
7823 (* Generate the OCaml bindings interface. *)
7824 and generate_ocaml_mli () =
7825 generate_header OCamlStyle LGPLv2plus;
7828 (** For API documentation you should refer to the C API
7829 in the guestfs(3) manual page. The OCaml API uses almost
7830 exactly the same calls. *)
7833 (** A [guestfs_h] handle. *)
7835 exception Error of string
7836 (** This exception is raised when there is an error. *)
7838 exception Handle_closed of string
7839 (** This exception is raised if you use a {!Guestfs.t} handle
7840 after calling {!close} on it. The string is the name of
7843 val create : unit -> t
7844 (** Create a {!Guestfs.t} handle. *)
7846 val close : t -> unit
7847 (** Close the {!Guestfs.t} handle and free up all resources used
7850 Handles are closed by the garbage collector when they become
7851 unreferenced, but callers can call this in order to provide
7852 predictable cleanup. *)
7855 generate_ocaml_structure_decls ();
7859 fun (name, style, _, _, _, shortdesc, _) ->
7860 generate_ocaml_prototype name style;
7861 pr "(** %s *)\n" shortdesc;
7863 ) all_functions_sorted
7865 (* Generate the OCaml bindings implementation. *)
7866 and generate_ocaml_ml () =
7867 generate_header OCamlStyle LGPLv2plus;
7872 exception Error of string
7873 exception Handle_closed of string
7875 external create : unit -> t = \"ocaml_guestfs_create\"
7876 external close : t -> unit = \"ocaml_guestfs_close\"
7878 (* Give the exceptions names, so they can be raised from the C code. *)
7880 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7881 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7885 generate_ocaml_structure_decls ();
7889 fun (name, style, _, _, _, shortdesc, _) ->
7890 generate_ocaml_prototype ~is_external:true name style;
7891 ) all_functions_sorted
7893 (* Generate the OCaml bindings C implementation. *)
7894 and generate_ocaml_c () =
7895 generate_header CStyle LGPLv2plus;
7902 #include <caml/config.h>
7903 #include <caml/alloc.h>
7904 #include <caml/callback.h>
7905 #include <caml/fail.h>
7906 #include <caml/memory.h>
7907 #include <caml/mlvalues.h>
7908 #include <caml/signals.h>
7910 #include <guestfs.h>
7912 #include \"guestfs_c.h\"
7914 /* Copy a hashtable of string pairs into an assoc-list. We return
7915 * the list in reverse order, but hashtables aren't supposed to be
7918 static CAMLprim value
7919 copy_table (char * const * argv)
7922 CAMLlocal5 (rv, pairv, kv, vv, cons);
7926 for (i = 0; argv[i] != NULL; i += 2) {
7927 kv = caml_copy_string (argv[i]);
7928 vv = caml_copy_string (argv[i+1]);
7929 pairv = caml_alloc (2, 0);
7930 Store_field (pairv, 0, kv);
7931 Store_field (pairv, 1, vv);
7932 cons = caml_alloc (2, 0);
7933 Store_field (cons, 1, rv);
7935 Store_field (cons, 0, pairv);
7943 (* Struct copy functions. *)
7945 let emit_ocaml_copy_list_function typ =
7946 pr "static CAMLprim value\n";
7947 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7949 pr " CAMLparam0 ();\n";
7950 pr " CAMLlocal2 (rv, v);\n";
7951 pr " unsigned int i;\n";
7953 pr " if (%ss->len == 0)\n" typ;
7954 pr " CAMLreturn (Atom (0));\n";
7956 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7957 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7958 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7959 pr " caml_modify (&Field (rv, i), v);\n";
7961 pr " CAMLreturn (rv);\n";
7969 let has_optpercent_col =
7970 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7972 pr "static CAMLprim value\n";
7973 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7975 pr " CAMLparam0 ();\n";
7976 if has_optpercent_col then
7977 pr " CAMLlocal3 (rv, v, v2);\n"
7979 pr " CAMLlocal2 (rv, v);\n";
7981 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7986 pr " v = caml_copy_string (%s->%s);\n" typ name
7988 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7989 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7992 pr " v = caml_alloc_string (32);\n";
7993 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7994 | name, (FBytes|FInt64|FUInt64) ->
7995 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7996 | name, (FInt32|FUInt32) ->
7997 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7998 | name, FOptPercent ->
7999 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8000 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8001 pr " v = caml_alloc (1, 0);\n";
8002 pr " Store_field (v, 0, v2);\n";
8003 pr " } else /* None */\n";
8004 pr " v = Val_int (0);\n";
8006 pr " v = Val_int (%s->%s);\n" typ name
8008 pr " Store_field (rv, %d, v);\n" i
8010 pr " CAMLreturn (rv);\n";
8015 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8018 | typ, (RStructListOnly | RStructAndList) ->
8019 (* generate the function for typ *)
8020 emit_ocaml_copy_list_function typ
8021 | typ, _ -> () (* empty *)
8022 ) (rstructs_used_by all_functions);
8026 fun (name, style, _, _, _, _, _) ->
8027 pr "/* Automatically generated wrapper for function\n";
8029 generate_ocaml_prototype name style;
8034 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8036 let needs_extra_vs =
8037 match fst style with RConstOptString _ -> true | _ -> false in
8039 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8040 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8041 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8044 pr "CAMLprim value\n";
8045 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8046 List.iter (pr ", value %s") (List.tl params);
8051 | [p1; p2; p3; p4; p5] ->
8052 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8053 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8054 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8055 pr " CAMLxparam%d (%s);\n"
8056 (List.length rest) (String.concat ", " rest)
8058 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8060 if not needs_extra_vs then
8061 pr " CAMLlocal1 (rv);\n"
8063 pr " CAMLlocal3 (rv, v, v2);\n";
8066 pr " guestfs_h *g = Guestfs_val (gv);\n";
8067 pr " if (g == NULL)\n";
8068 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8074 | Device n | Dev_or_Path n
8078 pr " const char *%s = String_val (%sv);\n" n n
8080 pr " const char *%s =\n" n;
8081 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8083 | StringList n | DeviceList n ->
8084 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8086 pr " int %s = Bool_val (%sv);\n" n n
8088 pr " int %s = Int_val (%sv);\n" n n
8090 pr " int64_t %s = Int64_val (%sv);\n" n n
8093 match fst style with
8094 | RErr -> pr " int r;\n"; "-1"
8095 | RInt _ -> pr " int r;\n"; "-1"
8096 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8097 | RBool _ -> pr " int r;\n"; "-1"
8098 | RConstString _ | RConstOptString _ ->
8099 pr " const char *r;\n"; "NULL"
8100 | RString _ -> pr " char *r;\n"; "NULL"
8105 | RStruct (_, typ) ->
8106 pr " struct guestfs_%s *r;\n" typ; "NULL"
8107 | RStructList (_, typ) ->
8108 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8115 pr " size_t size;\n";
8119 pr " caml_enter_blocking_section ();\n";
8120 pr " r = guestfs_%s " name;
8121 generate_c_call_args ~handle:"g" style;
8123 pr " caml_leave_blocking_section ();\n";
8127 | StringList n | DeviceList n ->
8128 pr " ocaml_guestfs_free_strings (%s);\n" n;
8129 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8130 | Bool _ | Int _ | Int64 _
8131 | FileIn _ | FileOut _ -> ()
8134 pr " if (r == %s)\n" error_code;
8135 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8138 (match fst style with
8139 | RErr -> pr " rv = Val_unit;\n"
8140 | RInt _ -> pr " rv = Val_int (r);\n"
8142 pr " rv = caml_copy_int64 (r);\n"
8143 | RBool _ -> pr " rv = Val_bool (r);\n"
8145 pr " rv = caml_copy_string (r);\n"
8146 | RConstOptString _ ->
8147 pr " if (r) { /* Some string */\n";
8148 pr " v = caml_alloc (1, 0);\n";
8149 pr " v2 = caml_copy_string (r);\n";
8150 pr " Store_field (v, 0, v2);\n";
8151 pr " } else /* None */\n";
8152 pr " v = Val_int (0);\n";
8154 pr " rv = caml_copy_string (r);\n";
8157 pr " rv = caml_copy_string_array ((const char **) r);\n";
8158 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8160 | RStruct (_, typ) ->
8161 pr " rv = copy_%s (r);\n" typ;
8162 pr " guestfs_free_%s (r);\n" typ;
8163 | RStructList (_, typ) ->
8164 pr " rv = copy_%s_list (r);\n" typ;
8165 pr " guestfs_free_%s_list (r);\n" typ;
8167 pr " rv = copy_table (r);\n";
8168 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8171 pr " rv = caml_alloc_string (size);\n";
8172 pr " memcpy (String_val (rv), r, size);\n";
8175 pr " CAMLreturn (rv);\n";
8179 if List.length params > 5 then (
8180 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8181 pr "CAMLprim value ";
8182 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8183 pr "CAMLprim value\n";
8184 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8186 pr " return ocaml_guestfs_%s (argv[0]" name;
8187 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8192 ) all_functions_sorted
8194 and generate_ocaml_structure_decls () =
8197 pr "type %s = {\n" typ;
8200 | name, FString -> pr " %s : string;\n" name
8201 | name, FBuffer -> pr " %s : string;\n" name
8202 | name, FUUID -> pr " %s : string;\n" name
8203 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8204 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8205 | name, FChar -> pr " %s : char;\n" name
8206 | name, FOptPercent -> pr " %s : float option;\n" name
8212 and generate_ocaml_prototype ?(is_external = false) name style =
8213 if is_external then pr "external " else pr "val ";
8214 pr "%s : t -> " name;
8217 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8218 | OptString _ -> pr "string option -> "
8219 | StringList _ | DeviceList _ -> pr "string array -> "
8220 | Bool _ -> pr "bool -> "
8221 | Int _ -> pr "int -> "
8222 | Int64 _ -> pr "int64 -> "
8224 (match fst style with
8225 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8226 | RInt _ -> pr "int"
8227 | RInt64 _ -> pr "int64"
8228 | RBool _ -> pr "bool"
8229 | RConstString _ -> pr "string"
8230 | RConstOptString _ -> pr "string option"
8231 | RString _ | RBufferOut _ -> pr "string"
8232 | RStringList _ -> pr "string array"
8233 | RStruct (_, typ) -> pr "%s" typ
8234 | RStructList (_, typ) -> pr "%s array" typ
8235 | RHashtable _ -> pr "(string * string) list"
8237 if is_external then (
8239 if List.length (snd style) + 1 > 5 then
8240 pr "\"ocaml_guestfs_%s_byte\" " name;
8241 pr "\"ocaml_guestfs_%s\"" name
8245 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8246 and generate_perl_xs () =
8247 generate_header CStyle LGPLv2plus;
8250 #include \"EXTERN.h\"
8254 #include <guestfs.h>
8257 #define PRId64 \"lld\"
8261 my_newSVll(long long val) {
8262 #ifdef USE_64_BIT_ALL
8263 return newSViv(val);
8267 len = snprintf(buf, 100, \"%%\" PRId64, val);
8268 return newSVpv(buf, len);
8273 #define PRIu64 \"llu\"
8277 my_newSVull(unsigned long long val) {
8278 #ifdef USE_64_BIT_ALL
8279 return newSVuv(val);
8283 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8284 return newSVpv(buf, len);
8288 /* http://www.perlmonks.org/?node_id=680842 */
8290 XS_unpack_charPtrPtr (SV *arg) {
8295 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8296 croak (\"array reference expected\");
8298 av = (AV *)SvRV (arg);
8299 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8301 croak (\"malloc failed\");
8303 for (i = 0; i <= av_len (av); i++) {
8304 SV **elem = av_fetch (av, i, 0);
8306 if (!elem || !*elem)
8307 croak (\"missing element in list\");
8309 ret[i] = SvPV_nolen (*elem);
8317 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8324 RETVAL = guestfs_create ();
8326 croak (\"could not create guestfs handle\");
8327 guestfs_set_error_handler (RETVAL, NULL, NULL);
8340 fun (name, style, _, _, _, _, _) ->
8341 (match fst style with
8342 | RErr -> pr "void\n"
8343 | RInt _ -> pr "SV *\n"
8344 | RInt64 _ -> pr "SV *\n"
8345 | RBool _ -> pr "SV *\n"
8346 | RConstString _ -> pr "SV *\n"
8347 | RConstOptString _ -> pr "SV *\n"
8348 | RString _ -> pr "SV *\n"
8349 | RBufferOut _ -> pr "SV *\n"
8351 | RStruct _ | RStructList _
8353 pr "void\n" (* all lists returned implictly on the stack *)
8355 (* Call and arguments. *)
8357 generate_c_call_args ~handle:"g" ~decl:true style;
8359 pr " guestfs_h *g;\n";
8363 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8366 (* http://www.perlmonks.org/?node_id=554277
8367 * Note that the implicit handle argument means we have
8368 * to add 1 to the ST(x) operator.
8370 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8371 | StringList n | DeviceList n -> pr " char **%s;\n" n
8372 | Bool n -> pr " int %s;\n" n
8373 | Int n -> pr " int %s;\n" n
8374 | Int64 n -> pr " int64_t %s;\n" n
8377 let do_cleanups () =
8380 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8381 | Bool _ | Int _ | Int64 _
8382 | FileIn _ | FileOut _ -> ()
8383 | StringList n | DeviceList n -> pr " free (%s);\n" n
8388 (match fst style with
8393 pr " r = guestfs_%s " name;
8394 generate_c_call_args ~handle:"g" style;
8397 pr " if (r == -1)\n";
8398 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8404 pr " %s = guestfs_%s " n name;
8405 generate_c_call_args ~handle:"g" style;
8408 pr " if (%s == -1)\n" n;
8409 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8410 pr " RETVAL = newSViv (%s);\n" n;
8415 pr " int64_t %s;\n" n;
8417 pr " %s = guestfs_%s " n name;
8418 generate_c_call_args ~handle:"g" style;
8421 pr " if (%s == -1)\n" n;
8422 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8423 pr " RETVAL = my_newSVll (%s);\n" n;
8428 pr " const char *%s;\n" n;
8430 pr " %s = guestfs_%s " n name;
8431 generate_c_call_args ~handle:"g" style;
8434 pr " if (%s == NULL)\n" n;
8435 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8436 pr " RETVAL = newSVpv (%s, 0);\n" n;
8439 | RConstOptString n ->
8441 pr " const char *%s;\n" n;
8443 pr " %s = guestfs_%s " n name;
8444 generate_c_call_args ~handle:"g" style;
8447 pr " if (%s == NULL)\n" n;
8448 pr " RETVAL = &PL_sv_undef;\n";
8450 pr " RETVAL = newSVpv (%s, 0);\n" n;
8455 pr " char *%s;\n" n;
8457 pr " %s = guestfs_%s " n name;
8458 generate_c_call_args ~handle:"g" style;
8461 pr " if (%s == NULL)\n" n;
8462 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8463 pr " RETVAL = newSVpv (%s, 0);\n" n;
8464 pr " free (%s);\n" n;
8467 | RStringList n | RHashtable n ->
8469 pr " char **%s;\n" n;
8472 pr " %s = guestfs_%s " n name;
8473 generate_c_call_args ~handle:"g" style;
8476 pr " if (%s == NULL)\n" n;
8477 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8478 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8479 pr " EXTEND (SP, n);\n";
8480 pr " for (i = 0; i < n; ++i) {\n";
8481 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8482 pr " free (%s[i]);\n" n;
8484 pr " free (%s);\n" n;
8485 | RStruct (n, typ) ->
8486 let cols = cols_of_struct typ in
8487 generate_perl_struct_code typ cols name style n do_cleanups
8488 | RStructList (n, typ) ->
8489 let cols = cols_of_struct typ in
8490 generate_perl_struct_list_code typ cols name style n do_cleanups
8493 pr " char *%s;\n" n;
8494 pr " size_t size;\n";
8496 pr " %s = guestfs_%s " n name;
8497 generate_c_call_args ~handle:"g" style;
8500 pr " if (%s == NULL)\n" n;
8501 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8502 pr " RETVAL = newSVpvn (%s, size);\n" n;
8503 pr " free (%s);\n" n;
8511 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8513 pr " struct guestfs_%s_list *%s;\n" typ n;
8517 pr " %s = guestfs_%s " n name;
8518 generate_c_call_args ~handle:"g" style;
8521 pr " if (%s == NULL)\n" n;
8522 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8523 pr " EXTEND (SP, %s->len);\n" n;
8524 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8525 pr " hv = newHV ();\n";
8529 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8530 name (String.length name) n name
8532 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8533 name (String.length name) n name
8535 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8536 name (String.length name) n name n name
8537 | name, (FBytes|FUInt64) ->
8538 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8539 name (String.length name) n name
8541 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8542 name (String.length name) n name
8543 | name, (FInt32|FUInt32) ->
8544 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8545 name (String.length name) n name
8547 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8548 name (String.length name) n name
8549 | name, FOptPercent ->
8550 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8551 name (String.length name) n name
8553 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8555 pr " guestfs_free_%s_list (%s);\n" typ n
8557 and generate_perl_struct_code typ cols name style n do_cleanups =
8559 pr " struct guestfs_%s *%s;\n" typ n;
8561 pr " %s = guestfs_%s " n name;
8562 generate_c_call_args ~handle:"g" style;
8565 pr " if (%s == NULL)\n" n;
8566 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8567 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8569 fun ((name, _) as col) ->
8570 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8574 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8577 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8580 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8582 | name, (FBytes|FUInt64) ->
8583 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8586 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8588 | name, (FInt32|FUInt32) ->
8589 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8592 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8594 | name, FOptPercent ->
8595 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8598 pr " free (%s);\n" n
8600 (* Generate Sys/Guestfs.pm. *)
8601 and generate_perl_pm () =
8602 generate_header HashStyle LGPLv2plus;
8609 Sys::Guestfs - Perl bindings for libguestfs
8615 my $h = Sys::Guestfs->new ();
8616 $h->add_drive ('guest.img');
8618 $h->mount ('/dev/sda1', '/');
8619 $h->touch ('/hello');
8624 The C<Sys::Guestfs> module provides a Perl XS binding to the
8625 libguestfs API for examining and modifying virtual machine
8628 Amongst the things this is good for: making batch configuration
8629 changes to guests, getting disk used/free statistics (see also:
8630 virt-df), migrating between virtualization systems (see also:
8631 virt-p2v), performing partial backups, performing partial guest
8632 clones, cloning guests and changing registry/UUID/hostname info, and
8635 Libguestfs uses Linux kernel and qemu code, and can access any type of
8636 guest filesystem that Linux and qemu can, including but not limited
8637 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8638 schemes, qcow, qcow2, vmdk.
8640 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8641 LVs, what filesystem is in each LV, etc.). It can also run commands
8642 in the context of the guest. Also you can access filesystems over
8645 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8646 functions for using libguestfs from Perl, including integration
8651 All errors turn into calls to C<croak> (see L<Carp(3)>).
8659 package Sys::Guestfs;
8665 XSLoader::load ('Sys::Guestfs');
8667 =item $h = Sys::Guestfs->new ();
8669 Create a new guestfs handle.
8675 my $class = ref ($proto) || $proto;
8677 my $self = Sys::Guestfs::_create ();
8678 bless $self, $class;
8684 (* Actions. We only need to print documentation for these as
8685 * they are pulled in from the XS code automatically.
8688 fun (name, style, _, flags, _, _, longdesc) ->
8689 if not (List.mem NotInDocs flags) then (
8690 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8692 generate_perl_prototype name style;
8694 pr "%s\n\n" longdesc;
8695 if List.mem ProtocolLimitWarning flags then
8696 pr "%s\n\n" protocol_limit_warning;
8697 if List.mem DangerWillRobinson flags then
8698 pr "%s\n\n" danger_will_robinson;
8699 match deprecation_notice flags with
8701 | Some txt -> pr "%s\n\n" txt
8703 ) all_functions_sorted;
8715 Copyright (C) %s Red Hat Inc.
8719 Please see the file COPYING.LIB for the full license.
8725 L<http://libguestfs.org>,
8726 L<Sys::Guestfs::Lib(3)>.
8731 and generate_perl_prototype name style =
8732 (match fst style with
8740 | RBufferOut n -> pr "$%s = " n
8742 | RHashtable n -> pr "%%%s = " n
8744 | RStructList (n,_) -> pr "@%s = " n
8747 let comma = ref false in
8750 if !comma then pr ", ";
8753 | Pathname n | Device n | Dev_or_Path n | String n
8754 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8756 | StringList n | DeviceList n ->
8761 (* Generate Python C module. *)
8762 and generate_python_c () =
8763 generate_header CStyle LGPLv2plus;
8772 #include \"guestfs.h\"
8780 get_handle (PyObject *obj)
8783 assert (obj != Py_None);
8784 return ((Pyguestfs_Object *) obj)->g;
8788 put_handle (guestfs_h *g)
8792 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8795 /* This list should be freed (but not the strings) after use. */
8797 get_string_list (PyObject *obj)
8804 if (!PyList_Check (obj)) {
8805 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8809 len = PyList_Size (obj);
8810 r = malloc (sizeof (char *) * (len+1));
8812 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8816 for (i = 0; i < len; ++i)
8817 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8824 put_string_list (char * const * const argv)
8829 for (argc = 0; argv[argc] != NULL; ++argc)
8832 list = PyList_New (argc);
8833 for (i = 0; i < argc; ++i)
8834 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8840 put_table (char * const * const argv)
8842 PyObject *list, *item;
8845 for (argc = 0; argv[argc] != NULL; ++argc)
8848 list = PyList_New (argc >> 1);
8849 for (i = 0; i < argc; i += 2) {
8850 item = PyTuple_New (2);
8851 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8852 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8853 PyList_SetItem (list, i >> 1, item);
8860 free_strings (char **argv)
8864 for (argc = 0; argv[argc] != NULL; ++argc)
8870 py_guestfs_create (PyObject *self, PyObject *args)
8874 g = guestfs_create ();
8876 PyErr_SetString (PyExc_RuntimeError,
8877 \"guestfs.create: failed to allocate handle\");
8880 guestfs_set_error_handler (g, NULL, NULL);
8881 return put_handle (g);
8885 py_guestfs_close (PyObject *self, PyObject *args)
8890 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8892 g = get_handle (py_g);
8896 Py_INCREF (Py_None);
8902 let emit_put_list_function typ =
8903 pr "static PyObject *\n";
8904 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8906 pr " PyObject *list;\n";
8909 pr " list = PyList_New (%ss->len);\n" typ;
8910 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8911 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8912 pr " return list;\n";
8917 (* Structures, turned into Python dictionaries. *)
8920 pr "static PyObject *\n";
8921 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8923 pr " PyObject *dict;\n";
8925 pr " dict = PyDict_New ();\n";
8929 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8930 pr " PyString_FromString (%s->%s));\n"
8933 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8934 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8937 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8938 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8940 | name, (FBytes|FUInt64) ->
8941 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8942 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8945 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8946 pr " PyLong_FromLongLong (%s->%s));\n"
8949 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8950 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8953 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8954 pr " PyLong_FromLong (%s->%s));\n"
8956 | name, FOptPercent ->
8957 pr " if (%s->%s >= 0)\n" typ name;
8958 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8959 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8962 pr " Py_INCREF (Py_None);\n";
8963 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8966 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8967 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8969 pr " return dict;\n";
8975 (* Emit a put_TYPE_list function definition only if that function is used. *)
8978 | typ, (RStructListOnly | RStructAndList) ->
8979 (* generate the function for typ *)
8980 emit_put_list_function typ
8981 | typ, _ -> () (* empty *)
8982 ) (rstructs_used_by all_functions);
8984 (* Python wrapper functions. *)
8986 fun (name, style, _, _, _, _, _) ->
8987 pr "static PyObject *\n";
8988 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8991 pr " PyObject *py_g;\n";
8992 pr " guestfs_h *g;\n";
8993 pr " PyObject *py_r;\n";
8996 match fst style with
8997 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8998 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8999 | RConstString _ | RConstOptString _ ->
9000 pr " const char *r;\n"; "NULL"
9001 | RString _ -> pr " char *r;\n"; "NULL"
9002 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9003 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9004 | RStructList (_, typ) ->
9005 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9008 pr " size_t size;\n";
9013 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9014 pr " const char *%s;\n" n
9015 | OptString n -> pr " const char *%s;\n" n
9016 | StringList n | DeviceList n ->
9017 pr " PyObject *py_%s;\n" n;
9018 pr " char **%s;\n" n
9019 | Bool n -> pr " int %s;\n" n
9020 | Int n -> pr " int %s;\n" n
9021 | Int64 n -> pr " long long %s;\n" n
9026 (* Convert the parameters. *)
9027 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9030 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9031 | OptString _ -> pr "z"
9032 | StringList _ | DeviceList _ -> pr "O"
9033 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9035 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9036 * emulate C's int/long/long long in Python?
9039 pr ":guestfs_%s\",\n" name;
9043 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9044 | OptString n -> pr ", &%s" n
9045 | StringList n | DeviceList n -> pr ", &py_%s" n
9046 | Bool n -> pr ", &%s" n
9047 | Int n -> pr ", &%s" n
9048 | Int64 n -> pr ", &%s" n
9052 pr " return NULL;\n";
9054 pr " g = get_handle (py_g);\n";
9057 | Pathname _ | Device _ | Dev_or_Path _ | String _
9058 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9059 | StringList n | DeviceList n ->
9060 pr " %s = get_string_list (py_%s);\n" n n;
9061 pr " if (!%s) return NULL;\n" n
9066 pr " r = guestfs_%s " name;
9067 generate_c_call_args ~handle:"g" style;
9072 | Pathname _ | Device _ | Dev_or_Path _ | String _
9073 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9074 | StringList n | DeviceList n ->
9075 pr " free (%s);\n" n
9078 pr " if (r == %s) {\n" error_code;
9079 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9080 pr " return NULL;\n";
9084 (match fst style with
9086 pr " Py_INCREF (Py_None);\n";
9087 pr " py_r = Py_None;\n"
9089 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9090 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9091 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9092 | RConstOptString _ ->
9094 pr " py_r = PyString_FromString (r);\n";
9096 pr " Py_INCREF (Py_None);\n";
9097 pr " py_r = Py_None;\n";
9100 pr " py_r = PyString_FromString (r);\n";
9103 pr " py_r = put_string_list (r);\n";
9104 pr " free_strings (r);\n"
9105 | RStruct (_, typ) ->
9106 pr " py_r = put_%s (r);\n" typ;
9107 pr " guestfs_free_%s (r);\n" typ
9108 | RStructList (_, typ) ->
9109 pr " py_r = put_%s_list (r);\n" typ;
9110 pr " guestfs_free_%s_list (r);\n" typ
9112 pr " py_r = put_table (r);\n";
9113 pr " free_strings (r);\n"
9115 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9119 pr " return py_r;\n";
9124 (* Table of functions. *)
9125 pr "static PyMethodDef methods[] = {\n";
9126 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9127 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9129 fun (name, _, _, _, _, _, _) ->
9130 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9133 pr " { NULL, NULL, 0, NULL }\n";
9137 (* Init function. *)
9140 initlibguestfsmod (void)
9142 static int initialized = 0;
9144 if (initialized) return;
9145 Py_InitModule ((char *) \"libguestfsmod\", methods);
9150 (* Generate Python module. *)
9151 and generate_python_py () =
9152 generate_header HashStyle LGPLv2plus;
9155 u\"\"\"Python bindings for libguestfs
9158 g = guestfs.GuestFS ()
9159 g.add_drive (\"guest.img\")
9161 parts = g.list_partitions ()
9163 The guestfs module provides a Python binding to the libguestfs API
9164 for examining and modifying virtual machine disk images.
9166 Amongst the things this is good for: making batch configuration
9167 changes to guests, getting disk used/free statistics (see also:
9168 virt-df), migrating between virtualization systems (see also:
9169 virt-p2v), performing partial backups, performing partial guest
9170 clones, cloning guests and changing registry/UUID/hostname info, and
9173 Libguestfs uses Linux kernel and qemu code, and can access any type of
9174 guest filesystem that Linux and qemu can, including but not limited
9175 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9176 schemes, qcow, qcow2, vmdk.
9178 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9179 LVs, what filesystem is in each LV, etc.). It can also run commands
9180 in the context of the guest. Also you can access filesystems over
9183 Errors which happen while using the API are turned into Python
9184 RuntimeError exceptions.
9186 To create a guestfs handle you usually have to perform the following
9189 # Create the handle, call add_drive at least once, and possibly
9190 # several times if the guest has multiple block devices:
9191 g = guestfs.GuestFS ()
9192 g.add_drive (\"guest.img\")
9194 # Launch the qemu subprocess and wait for it to become ready:
9197 # Now you can issue commands, for example:
9202 import libguestfsmod
9205 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9207 def __init__ (self):
9208 \"\"\"Create a new libguestfs handle.\"\"\"
9209 self._o = libguestfsmod.create ()
9212 libguestfsmod.close (self._o)
9217 fun (name, style, _, flags, _, _, longdesc) ->
9219 generate_py_call_args ~handle:"self" (snd style);
9222 if not (List.mem NotInDocs flags) then (
9223 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9225 match fst style with
9226 | RErr | RInt _ | RInt64 _ | RBool _
9227 | RConstOptString _ | RConstString _
9228 | RString _ | RBufferOut _ -> doc
9230 doc ^ "\n\nThis function returns a list of strings."
9231 | RStruct (_, typ) ->
9232 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9233 | RStructList (_, typ) ->
9234 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9236 doc ^ "\n\nThis function returns a dictionary." in
9238 if List.mem ProtocolLimitWarning flags then
9239 doc ^ "\n\n" ^ protocol_limit_warning
9242 if List.mem DangerWillRobinson flags then
9243 doc ^ "\n\n" ^ danger_will_robinson
9246 match deprecation_notice flags with
9248 | Some txt -> doc ^ "\n\n" ^ txt in
9249 let doc = pod2text ~width:60 name doc in
9250 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9251 let doc = String.concat "\n " doc in
9252 pr " u\"\"\"%s\"\"\"\n" doc;
9254 pr " return libguestfsmod.%s " name;
9255 generate_py_call_args ~handle:"self._o" (snd style);
9260 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9261 and generate_py_call_args ~handle args =
9263 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9266 (* Useful if you need the longdesc POD text as plain text. Returns a
9269 * Because this is very slow (the slowest part of autogeneration),
9270 * we memoize the results.
9272 and pod2text ~width name longdesc =
9273 let key = width, name, longdesc in
9274 try Hashtbl.find pod2text_memo key
9276 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9277 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9279 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9280 let chan = open_process_in cmd in
9281 let lines = ref [] in
9283 let line = input_line chan in
9284 if i = 1 then (* discard the first line of output *)
9287 let line = triml line in
9288 lines := line :: !lines;
9291 let lines = try loop 1 with End_of_file -> List.rev !lines in
9293 (match close_process_in chan with
9296 failwithf "pod2text: process exited with non-zero status (%d)" i
9297 | WSIGNALED i | WSTOPPED i ->
9298 failwithf "pod2text: process signalled or stopped by signal %d" i
9300 Hashtbl.add pod2text_memo key lines;
9301 pod2text_memo_updated ();
9304 (* Generate ruby bindings. *)
9305 and generate_ruby_c () =
9306 generate_header CStyle LGPLv2plus;
9314 #include \"guestfs.h\"
9316 #include \"extconf.h\"
9318 /* For Ruby < 1.9 */
9320 #define RARRAY_LEN(r) (RARRAY((r))->len)
9323 static VALUE m_guestfs; /* guestfs module */
9324 static VALUE c_guestfs; /* guestfs_h handle */
9325 static VALUE e_Error; /* used for all errors */
9327 static void ruby_guestfs_free (void *p)
9330 guestfs_close ((guestfs_h *) p);
9333 static VALUE ruby_guestfs_create (VALUE m)
9337 g = guestfs_create ();
9339 rb_raise (e_Error, \"failed to create guestfs handle\");
9341 /* Don't print error messages to stderr by default. */
9342 guestfs_set_error_handler (g, NULL, NULL);
9344 /* Wrap it, and make sure the close function is called when the
9347 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9350 static VALUE ruby_guestfs_close (VALUE gv)
9353 Data_Get_Struct (gv, guestfs_h, g);
9355 ruby_guestfs_free (g);
9356 DATA_PTR (gv) = NULL;
9364 fun (name, style, _, _, _, _, _) ->
9365 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9366 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9369 pr " guestfs_h *g;\n";
9370 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9372 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9378 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9379 pr " Check_Type (%sv, T_STRING);\n" n;
9380 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9382 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9383 pr " \"%s\", \"%s\");\n" n name
9385 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9386 | StringList n | DeviceList n ->
9387 pr " char **%s;\n" n;
9388 pr " Check_Type (%sv, T_ARRAY);\n" n;
9390 pr " int i, len;\n";
9391 pr " len = RARRAY_LEN (%sv);\n" n;
9392 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9394 pr " for (i = 0; i < len; ++i) {\n";
9395 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9396 pr " %s[i] = StringValueCStr (v);\n" n;
9398 pr " %s[len] = NULL;\n" n;
9401 pr " int %s = RTEST (%sv);\n" n n
9403 pr " int %s = NUM2INT (%sv);\n" n n
9405 pr " long long %s = NUM2LL (%sv);\n" n n
9410 match fst style with
9411 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9412 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9413 | RConstString _ | RConstOptString _ ->
9414 pr " const char *r;\n"; "NULL"
9415 | RString _ -> pr " char *r;\n"; "NULL"
9416 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9417 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9418 | RStructList (_, typ) ->
9419 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9422 pr " size_t size;\n";
9426 pr " r = guestfs_%s " name;
9427 generate_c_call_args ~handle:"g" style;
9432 | Pathname _ | Device _ | Dev_or_Path _ | String _
9433 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9434 | StringList n | DeviceList n ->
9435 pr " free (%s);\n" n
9438 pr " if (r == %s)\n" error_code;
9439 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9442 (match fst style with
9444 pr " return Qnil;\n"
9445 | RInt _ | RBool _ ->
9446 pr " return INT2NUM (r);\n"
9448 pr " return ULL2NUM (r);\n"
9450 pr " return rb_str_new2 (r);\n";
9451 | RConstOptString _ ->
9453 pr " return rb_str_new2 (r);\n";
9455 pr " return Qnil;\n";
9457 pr " VALUE rv = rb_str_new2 (r);\n";
9461 pr " int i, len = 0;\n";
9462 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9463 pr " VALUE rv = rb_ary_new2 (len);\n";
9464 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9465 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9466 pr " free (r[i]);\n";
9470 | RStruct (_, typ) ->
9471 let cols = cols_of_struct typ in
9472 generate_ruby_struct_code typ cols
9473 | RStructList (_, typ) ->
9474 let cols = cols_of_struct typ in
9475 generate_ruby_struct_list_code typ cols
9477 pr " VALUE rv = rb_hash_new ();\n";
9479 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9480 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9481 pr " free (r[i]);\n";
9482 pr " free (r[i+1]);\n";
9487 pr " VALUE rv = rb_str_new (r, size);\n";
9497 /* Initialize the module. */
9498 void Init__guestfs ()
9500 m_guestfs = rb_define_module (\"Guestfs\");
9501 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9502 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9504 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9505 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9508 (* Define the rest of the methods. *)
9510 fun (name, style, _, _, _, _, _) ->
9511 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9512 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9517 (* Ruby code to return a struct. *)
9518 and generate_ruby_struct_code typ cols =
9519 pr " VALUE rv = rb_hash_new ();\n";
9523 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9525 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9527 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9528 | name, (FBytes|FUInt64) ->
9529 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9531 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9533 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9535 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9536 | name, FOptPercent ->
9537 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9538 | name, FChar -> (* XXX wrong? *)
9539 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9541 pr " guestfs_free_%s (r);\n" typ;
9544 (* Ruby code to return a struct list. *)
9545 and generate_ruby_struct_list_code typ cols =
9546 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9548 pr " for (i = 0; i < r->len; ++i) {\n";
9549 pr " VALUE hv = rb_hash_new ();\n";
9553 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9555 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
9557 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9558 | name, (FBytes|FUInt64) ->
9559 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9561 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9563 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9565 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9566 | name, FOptPercent ->
9567 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9568 | name, FChar -> (* XXX wrong? *)
9569 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9571 pr " rb_ary_push (rv, hv);\n";
9573 pr " guestfs_free_%s_list (r);\n" typ;
9576 (* Generate Java bindings GuestFS.java file. *)
9577 and generate_java_java () =
9578 generate_header CStyle LGPLv2plus;
9581 package com.redhat.et.libguestfs;
9583 import java.util.HashMap;
9584 import com.redhat.et.libguestfs.LibGuestFSException;
9585 import com.redhat.et.libguestfs.PV;
9586 import com.redhat.et.libguestfs.VG;
9587 import com.redhat.et.libguestfs.LV;
9588 import com.redhat.et.libguestfs.Stat;
9589 import com.redhat.et.libguestfs.StatVFS;
9590 import com.redhat.et.libguestfs.IntBool;
9591 import com.redhat.et.libguestfs.Dirent;
9594 * The GuestFS object is a libguestfs handle.
9598 public class GuestFS {
9599 // Load the native code.
9601 System.loadLibrary (\"guestfs_jni\");
9605 * The native guestfs_h pointer.
9610 * Create a libguestfs handle.
9612 * @throws LibGuestFSException
9614 public GuestFS () throws LibGuestFSException
9618 private native long _create () throws LibGuestFSException;
9621 * Close a libguestfs handle.
9623 * You can also leave handles to be collected by the garbage
9624 * collector, but this method ensures that the resources used
9625 * by the handle are freed up immediately. If you call any
9626 * other methods after closing the handle, you will get an
9629 * @throws LibGuestFSException
9631 public void close () throws LibGuestFSException
9637 private native void _close (long g) throws LibGuestFSException;
9639 public void finalize () throws LibGuestFSException
9647 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9648 if not (List.mem NotInDocs flags); then (
9649 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9651 if List.mem ProtocolLimitWarning flags then
9652 doc ^ "\n\n" ^ protocol_limit_warning
9655 if List.mem DangerWillRobinson flags then
9656 doc ^ "\n\n" ^ danger_will_robinson
9659 match deprecation_notice flags with
9661 | Some txt -> doc ^ "\n\n" ^ txt in
9662 let doc = pod2text ~width:60 name doc in
9663 let doc = List.map ( (* RHBZ#501883 *)
9666 | nonempty -> nonempty
9668 let doc = String.concat "\n * " doc in
9671 pr " * %s\n" shortdesc;
9674 pr " * @throws LibGuestFSException\n";
9678 generate_java_prototype ~public:true ~semicolon:false name style;
9681 pr " if (g == 0)\n";
9682 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9685 if fst style <> RErr then pr "return ";
9687 generate_java_call_args ~handle:"g" (snd style);
9691 generate_java_prototype ~privat:true ~native:true name style;
9698 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9699 and generate_java_call_args ~handle args =
9701 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9704 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9705 ?(semicolon=true) name style =
9706 if privat then pr "private ";
9707 if public then pr "public ";
9708 if native then pr "native ";
9711 (match fst style with
9712 | RErr -> pr "void ";
9713 | RInt _ -> pr "int ";
9714 | RInt64 _ -> pr "long ";
9715 | RBool _ -> pr "boolean ";
9716 | RConstString _ | RConstOptString _ | RString _
9717 | RBufferOut _ -> pr "String ";
9718 | RStringList _ -> pr "String[] ";
9719 | RStruct (_, typ) ->
9720 let name = java_name_of_struct typ in
9722 | RStructList (_, typ) ->
9723 let name = java_name_of_struct typ in
9725 | RHashtable _ -> pr "HashMap<String,String> ";
9728 if native then pr "_%s " name else pr "%s " name;
9730 let needs_comma = ref false in
9739 if !needs_comma then pr ", ";
9740 needs_comma := true;
9744 | Device n | Dev_or_Path n
9750 | StringList n | DeviceList n ->
9761 pr " throws LibGuestFSException";
9762 if semicolon then pr ";"
9764 and generate_java_struct jtyp cols () =
9765 generate_header CStyle LGPLv2plus;
9768 package com.redhat.et.libguestfs;
9771 * Libguestfs %s structure.
9783 | name, FBuffer -> pr " public String %s;\n" name
9784 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9785 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9786 | name, FChar -> pr " public char %s;\n" name
9787 | name, FOptPercent ->
9788 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9789 pr " public float %s;\n" name
9794 and generate_java_c () =
9795 generate_header CStyle LGPLv2plus;
9802 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9803 #include \"guestfs.h\"
9805 /* Note that this function returns. The exception is not thrown
9806 * until after the wrapper function returns.
9809 throw_exception (JNIEnv *env, const char *msg)
9812 cl = (*env)->FindClass (env,
9813 \"com/redhat/et/libguestfs/LibGuestFSException\");
9814 (*env)->ThrowNew (env, cl, msg);
9817 JNIEXPORT jlong JNICALL
9818 Java_com_redhat_et_libguestfs_GuestFS__1create
9819 (JNIEnv *env, jobject obj)
9823 g = guestfs_create ();
9825 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9828 guestfs_set_error_handler (g, NULL, NULL);
9829 return (jlong) (long) g;
9832 JNIEXPORT void JNICALL
9833 Java_com_redhat_et_libguestfs_GuestFS__1close
9834 (JNIEnv *env, jobject obj, jlong jg)
9836 guestfs_h *g = (guestfs_h *) (long) jg;
9843 fun (name, style, _, _, _, _, _) ->
9845 (match fst style with
9846 | RErr -> pr "void ";
9847 | RInt _ -> pr "jint ";
9848 | RInt64 _ -> pr "jlong ";
9849 | RBool _ -> pr "jboolean ";
9850 | RConstString _ | RConstOptString _ | RString _
9851 | RBufferOut _ -> pr "jstring ";
9852 | RStruct _ | RHashtable _ ->
9854 | RStringList _ | RStructList _ ->
9858 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9859 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9861 pr " (JNIEnv *env, jobject obj, jlong jg";
9865 | Device n | Dev_or_Path n
9870 pr ", jstring j%s" n
9871 | StringList n | DeviceList n ->
9872 pr ", jobjectArray j%s" n
9874 pr ", jboolean j%s" n
9882 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9883 let error_code, no_ret =
9884 match fst style with
9885 | RErr -> pr " int r;\n"; "-1", ""
9887 | RInt _ -> pr " int r;\n"; "-1", "0"
9888 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9889 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9890 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9892 pr " jstring jr;\n";
9893 pr " char *r;\n"; "NULL", "NULL"
9895 pr " jobjectArray jr;\n";
9898 pr " jstring jstr;\n";
9899 pr " char **r;\n"; "NULL", "NULL"
9900 | RStruct (_, typ) ->
9901 pr " jobject jr;\n";
9903 pr " jfieldID fl;\n";
9904 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9905 | RStructList (_, typ) ->
9906 pr " jobjectArray jr;\n";
9908 pr " jfieldID fl;\n";
9909 pr " jobject jfl;\n";
9910 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9911 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9913 pr " jstring jr;\n";
9915 pr " size_t size;\n";
9920 | Device n | Dev_or_Path n
9925 pr " const char *%s;\n" n
9926 | StringList n | DeviceList n ->
9927 pr " int %s_len;\n" n;
9928 pr " const char **%s;\n" n
9933 pr " int64_t %s;\n" n
9937 (match fst style with
9938 | RStringList _ | RStructList _ -> true
9939 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9941 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9942 List.exists (function
9943 | StringList _ -> true
9944 | DeviceList _ -> true
9945 | _ -> false) (snd style) in
9951 (* Get the parameters. *)
9955 | Device n | Dev_or_Path n
9959 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9961 (* This is completely undocumented, but Java null becomes
9964 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9965 | StringList n | DeviceList n ->
9966 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9967 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9968 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9969 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9971 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9973 pr " %s[%s_len] = NULL;\n" n n;
9977 pr " %s = j%s;\n" n n
9980 (* Make the call. *)
9981 pr " r = guestfs_%s " name;
9982 generate_c_call_args ~handle:"g" style;
9985 (* Release the parameters. *)
9989 | Device n | Dev_or_Path n
9993 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9996 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9997 | StringList n | DeviceList n ->
9998 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9999 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10001 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10003 pr " free (%s);\n" n
10009 (* Check for errors. *)
10010 pr " if (r == %s) {\n" error_code;
10011 pr " throw_exception (env, guestfs_last_error (g));\n";
10012 pr " return %s;\n" no_ret;
10015 (* Return value. *)
10016 (match fst style with
10018 | RInt _ -> pr " return (jint) r;\n"
10019 | RBool _ -> pr " return (jboolean) r;\n"
10020 | RInt64 _ -> pr " return (jlong) r;\n"
10021 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10022 | RConstOptString _ ->
10023 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10025 pr " jr = (*env)->NewStringUTF (env, r);\n";
10029 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10030 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10031 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10032 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10033 pr " for (i = 0; i < r_len; ++i) {\n";
10034 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10035 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10036 pr " free (r[i]);\n";
10040 | RStruct (_, typ) ->
10041 let jtyp = java_name_of_struct typ in
10042 let cols = cols_of_struct typ in
10043 generate_java_struct_return typ jtyp cols
10044 | RStructList (_, typ) ->
10045 let jtyp = java_name_of_struct typ in
10046 let cols = cols_of_struct typ in
10047 generate_java_struct_list_return typ jtyp cols
10050 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10051 pr " return NULL;\n"
10053 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10062 and generate_java_struct_return typ jtyp cols =
10063 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10064 pr " jr = (*env)->AllocObject (env, cl);\n";
10068 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10069 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10072 pr " char s[33];\n";
10073 pr " memcpy (s, r->%s, 32);\n" name;
10074 pr " s[32] = 0;\n";
10075 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10076 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10080 pr " int len = r->%s_len;\n" name;
10081 pr " char s[len+1];\n";
10082 pr " memcpy (s, r->%s, len);\n" name;
10083 pr " s[len] = 0;\n";
10084 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10085 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10087 | name, (FBytes|FUInt64|FInt64) ->
10088 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10089 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10090 | name, (FUInt32|FInt32) ->
10091 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10092 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10093 | name, FOptPercent ->
10094 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10095 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10097 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10098 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10103 and generate_java_struct_list_return typ jtyp cols =
10104 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10105 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10106 pr " for (i = 0; i < r->len; ++i) {\n";
10107 pr " jfl = (*env)->AllocObject (env, cl);\n";
10111 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10112 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10115 pr " char s[33];\n";
10116 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10117 pr " s[32] = 0;\n";
10118 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10119 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10123 pr " int len = r->val[i].%s_len;\n" name;
10124 pr " char s[len+1];\n";
10125 pr " memcpy (s, r->val[i].%s, len);\n" name;
10126 pr " s[len] = 0;\n";
10127 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10128 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10130 | name, (FBytes|FUInt64|FInt64) ->
10131 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10132 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10133 | name, (FUInt32|FInt32) ->
10134 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10135 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10136 | name, FOptPercent ->
10137 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10138 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10140 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10141 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10143 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10145 pr " guestfs_free_%s_list (r);\n" typ;
10148 and generate_java_makefile_inc () =
10149 generate_header HashStyle GPLv2plus;
10151 pr "java_built_sources = \\\n";
10154 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10156 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10158 and generate_haskell_hs () =
10159 generate_header HaskellStyle LGPLv2plus;
10161 (* XXX We only know how to generate partial FFI for Haskell
10162 * at the moment. Please help out!
10164 let can_generate style =
10168 | RInt64 _, _ -> true
10170 | RConstString _, _
10171 | RConstOptString _, _
10177 | RBufferOut _, _ -> false in
10180 {-# INCLUDE <guestfs.h> #-}
10181 {-# LANGUAGE ForeignFunctionInterface #-}
10186 (* List out the names of the actions we want to export. *)
10188 fun (name, style, _, _, _, _, _) ->
10189 if can_generate style then pr ",\n %s" name
10195 -- Unfortunately some symbols duplicate ones already present
10196 -- in Prelude. We don't know which, so we hard-code a list
10198 import Prelude hiding (truncate)
10202 import Foreign.C.Types
10204 import Control.Exception
10205 import Data.Typeable
10207 data GuestfsS = GuestfsS -- represents the opaque C struct
10208 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10209 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10211 -- XXX define properly later XXX
10215 data IntBool = IntBool
10217 data StatVFS = StatVFS
10218 data Hashtable = Hashtable
10220 foreign import ccall unsafe \"guestfs_create\" c_create
10222 foreign import ccall unsafe \"&guestfs_close\" c_close
10223 :: FunPtr (GuestfsP -> IO ())
10224 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10225 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10227 create :: IO GuestfsH
10230 c_set_error_handler p nullPtr nullPtr
10231 h <- newForeignPtr c_close p
10234 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10235 :: GuestfsP -> IO CString
10237 -- last_error :: GuestfsH -> IO (Maybe String)
10238 -- last_error h = do
10239 -- str <- withForeignPtr h (\\p -> c_last_error p)
10240 -- maybePeek peekCString str
10242 last_error :: GuestfsH -> IO (String)
10244 str <- withForeignPtr h (\\p -> c_last_error p)
10245 if (str == nullPtr)
10246 then return \"no error\"
10247 else peekCString str
10251 (* Generate wrappers for each foreign function. *)
10253 fun (name, style, _, _, _, _, _) ->
10254 if can_generate style then (
10255 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10257 generate_haskell_prototype ~handle:"GuestfsP" style;
10261 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10263 pr "%s %s = do\n" name
10264 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10266 (* Convert pointer arguments using with* functions. *)
10271 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10272 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10273 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10274 | Bool _ | Int _ | Int64 _ -> ()
10276 (* Convert integer arguments. *)
10280 | Bool n -> sprintf "(fromBool %s)" n
10281 | Int n -> sprintf "(fromIntegral %s)" n
10282 | Int64 n -> sprintf "(fromIntegral %s)" n
10283 | FileIn n | FileOut n
10284 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10286 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10287 (String.concat " " ("p" :: args));
10288 (match fst style with
10289 | RErr | RInt _ | RInt64 _ | RBool _ ->
10290 pr " if (r == -1)\n";
10292 pr " err <- last_error h\n";
10294 | RConstString _ | RConstOptString _ | RString _
10295 | RStringList _ | RStruct _
10296 | RStructList _ | RHashtable _ | RBufferOut _ ->
10297 pr " if (r == nullPtr)\n";
10299 pr " err <- last_error h\n";
10302 (match fst style with
10304 pr " else return ()\n"
10306 pr " else return (fromIntegral r)\n"
10308 pr " else return (fromIntegral r)\n"
10310 pr " else return (toBool r)\n"
10312 | RConstOptString _
10319 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10325 and generate_haskell_prototype ~handle ?(hs = false) style =
10326 pr "%s -> " handle;
10327 let string = if hs then "String" else "CString" in
10328 let int = if hs then "Int" else "CInt" in
10329 let bool = if hs then "Bool" else "CInt" in
10330 let int64 = if hs then "Integer" else "Int64" in
10334 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10335 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10336 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10337 | Bool _ -> pr "%s" bool
10338 | Int _ -> pr "%s" int
10339 | Int64 _ -> pr "%s" int
10340 | FileIn _ -> pr "%s" string
10341 | FileOut _ -> pr "%s" string
10346 (match fst style with
10347 | RErr -> if not hs then pr "CInt"
10348 | RInt _ -> pr "%s" int
10349 | RInt64 _ -> pr "%s" int64
10350 | RBool _ -> pr "%s" bool
10351 | RConstString _ -> pr "%s" string
10352 | RConstOptString _ -> pr "Maybe %s" string
10353 | RString _ -> pr "%s" string
10354 | RStringList _ -> pr "[%s]" string
10355 | RStruct (_, typ) ->
10356 let name = java_name_of_struct typ in
10358 | RStructList (_, typ) ->
10359 let name = java_name_of_struct typ in
10361 | RHashtable _ -> pr "Hashtable"
10362 | RBufferOut _ -> pr "%s" string
10366 and generate_csharp () =
10367 generate_header CPlusPlusStyle LGPLv2plus;
10369 (* XXX Make this configurable by the C# assembly users. *)
10370 let library = "libguestfs.so.0" in
10373 // These C# bindings are highly experimental at present.
10375 // Firstly they only work on Linux (ie. Mono). In order to get them
10376 // to work on Windows (ie. .Net) you would need to port the library
10377 // itself to Windows first.
10379 // The second issue is that some calls are known to be incorrect and
10380 // can cause Mono to segfault. Particularly: calls which pass or
10381 // return string[], or return any structure value. This is because
10382 // we haven't worked out the correct way to do this from C#.
10384 // The third issue is that when compiling you get a lot of warnings.
10385 // We are not sure whether the warnings are important or not.
10387 // Fourthly we do not routinely build or test these bindings as part
10388 // of the make && make check cycle, which means that regressions might
10391 // Suggestions and patches are welcome.
10395 // gmcs Libguestfs.cs
10396 // mono Libguestfs.exe
10398 // (You'll probably want to add a Test class / static main function
10399 // otherwise this won't do anything useful).
10403 using System.Runtime.InteropServices;
10404 using System.Runtime.Serialization;
10405 using System.Collections;
10409 class Error : System.ApplicationException
10411 public Error (string message) : base (message) {}
10412 protected Error (SerializationInfo info, StreamingContext context) {}
10419 [DllImport (\"%s\")]
10420 static extern IntPtr guestfs_create ();
10424 _handle = guestfs_create ();
10425 if (_handle == IntPtr.Zero)
10426 throw new Error (\"could not create guestfs handle\");
10429 [DllImport (\"%s\")]
10430 static extern void guestfs_close (IntPtr h);
10434 guestfs_close (_handle);
10437 [DllImport (\"%s\")]
10438 static extern string guestfs_last_error (IntPtr h);
10440 " library library library;
10442 (* Generate C# structure bindings. We prefix struct names with
10443 * underscore because C# cannot have conflicting struct names and
10444 * method names (eg. "class stat" and "stat").
10448 pr " [StructLayout (LayoutKind.Sequential)]\n";
10449 pr " public class _%s {\n" typ;
10452 | name, FChar -> pr " char %s;\n" name
10453 | name, FString -> pr " string %s;\n" name
10455 pr " uint %s_len;\n" name;
10456 pr " string %s;\n" name
10458 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10459 pr " string %s;\n" name
10460 | name, FUInt32 -> pr " uint %s;\n" name
10461 | name, FInt32 -> pr " int %s;\n" name
10462 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10463 | name, FInt64 -> pr " long %s;\n" name
10464 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10470 (* Generate C# function bindings. *)
10472 fun (name, style, _, _, _, shortdesc, _) ->
10473 let rec csharp_return_type () =
10474 match fst style with
10476 | RBool n -> "bool"
10478 | RInt64 n -> "long"
10480 | RConstOptString n
10482 | RBufferOut n -> "string"
10483 | RStruct (_,n) -> "_" ^ n
10484 | RHashtable n -> "Hashtable"
10485 | RStringList n -> "string[]"
10486 | RStructList (_,n) -> sprintf "_%s[]" n
10488 and c_return_type () =
10489 match fst style with
10493 | RInt64 _ -> "long"
10495 | RConstOptString _
10497 | RBufferOut _ -> "string"
10498 | RStruct (_,n) -> "_" ^ n
10500 | RStringList _ -> "string[]"
10501 | RStructList (_,n) -> sprintf "_%s[]" n
10503 and c_error_comparison () =
10504 match fst style with
10508 | RInt64 _ -> "== -1"
10510 | RConstOptString _
10516 | RStructList (_,_) -> "== null"
10518 and generate_extern_prototype () =
10519 pr " static extern %s guestfs_%s (IntPtr h"
10520 (c_return_type ()) name;
10523 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10524 | FileIn n | FileOut n ->
10525 pr ", [In] string %s" n
10526 | StringList n | DeviceList n ->
10527 pr ", [In] string[] %s" n
10537 and generate_public_prototype () =
10538 pr " public %s %s (" (csharp_return_type ()) name;
10539 let comma = ref false in
10541 if !comma then pr ", ";
10546 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10547 | FileIn n | FileOut n ->
10548 next (); pr "string %s" n
10549 | StringList n | DeviceList n ->
10550 next (); pr "string[] %s" n
10552 next (); pr "bool %s" n
10554 next (); pr "int %s" n
10556 next (); pr "long %s" n
10560 and generate_call () =
10561 pr "guestfs_%s (_handle" name;
10562 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10566 pr " [DllImport (\"%s\")]\n" library;
10567 generate_extern_prototype ();
10569 pr " /// <summary>\n";
10570 pr " /// %s\n" shortdesc;
10571 pr " /// </summary>\n";
10572 generate_public_prototype ();
10574 pr " %s r;\n" (c_return_type ());
10577 pr " if (r %s)\n" (c_error_comparison ());
10578 pr " throw new Error (guestfs_last_error (_handle));\n";
10579 (match fst style with
10582 pr " return r != 0 ? true : false;\n"
10584 pr " Hashtable rr = new Hashtable ();\n";
10585 pr " for (int i = 0; i < r.Length; i += 2)\n";
10586 pr " rr.Add (r[i], r[i+1]);\n";
10588 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10589 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10595 ) all_functions_sorted;
10601 and generate_bindtests () =
10602 generate_header CStyle LGPLv2plus;
10606 #include <stdlib.h>
10607 #include <inttypes.h>
10608 #include <string.h>
10610 #include \"guestfs.h\"
10611 #include \"guestfs-internal.h\"
10612 #include \"guestfs-internal-actions.h\"
10613 #include \"guestfs_protocol.h\"
10615 #define error guestfs_error
10616 #define safe_calloc guestfs_safe_calloc
10617 #define safe_malloc guestfs_safe_malloc
10620 print_strings (char *const *argv)
10625 for (argc = 0; argv[argc] != NULL; ++argc) {
10626 if (argc > 0) printf (\", \");
10627 printf (\"\\\"%%s\\\"\", argv[argc]);
10632 /* The test0 function prints its parameters to stdout. */
10636 match test_functions with
10637 | [] -> assert false
10638 | test0 :: tests -> test0, tests in
10641 let (name, style, _, _, _, _, _) = test0 in
10642 generate_prototype ~extern:false ~semicolon:false ~newline:true
10643 ~handle:"g" ~prefix:"guestfs__" name style;
10648 | Device n | Dev_or_Path n
10651 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10652 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10653 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10654 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10655 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10656 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10658 pr " /* Java changes stdout line buffering so we need this: */\n";
10659 pr " fflush (stdout);\n";
10665 fun (name, style, _, _, _, _, _) ->
10666 if String.sub name (String.length name - 3) 3 <> "err" then (
10667 pr "/* Test normal return. */\n";
10668 generate_prototype ~extern:false ~semicolon:false ~newline:true
10669 ~handle:"g" ~prefix:"guestfs__" name style;
10671 (match fst style with
10676 pr " sscanf (val, \"%%d\", &r);\n";
10679 pr " int64_t r;\n";
10680 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10683 pr " return STREQ (val, \"true\");\n"
10685 | RConstOptString _ ->
10686 (* Can't return the input string here. Return a static
10687 * string so we ensure we get a segfault if the caller
10688 * tries to free it.
10690 pr " return \"static string\";\n"
10692 pr " return strdup (val);\n"
10694 pr " char **strs;\n";
10696 pr " sscanf (val, \"%%d\", &n);\n";
10697 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10698 pr " for (i = 0; i < n; ++i) {\n";
10699 pr " strs[i] = safe_malloc (g, 16);\n";
10700 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10702 pr " strs[n] = NULL;\n";
10703 pr " return strs;\n"
10704 | RStruct (_, typ) ->
10705 pr " struct guestfs_%s *r;\n" typ;
10706 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10708 | RStructList (_, typ) ->
10709 pr " struct guestfs_%s_list *r;\n" typ;
10710 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10711 pr " sscanf (val, \"%%d\", &r->len);\n";
10712 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10715 pr " char **strs;\n";
10717 pr " sscanf (val, \"%%d\", &n);\n";
10718 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10719 pr " for (i = 0; i < n; ++i) {\n";
10720 pr " strs[i*2] = safe_malloc (g, 16);\n";
10721 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10722 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10723 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10725 pr " strs[n*2] = NULL;\n";
10726 pr " return strs;\n"
10728 pr " return strdup (val);\n"
10733 pr "/* Test error return. */\n";
10734 generate_prototype ~extern:false ~semicolon:false ~newline:true
10735 ~handle:"g" ~prefix:"guestfs__" name style;
10737 pr " error (g, \"error\");\n";
10738 (match fst style with
10739 | RErr | RInt _ | RInt64 _ | RBool _ ->
10741 | RConstString _ | RConstOptString _
10742 | RString _ | RStringList _ | RStruct _
10746 pr " return NULL;\n"
10753 and generate_ocaml_bindtests () =
10754 generate_header OCamlStyle GPLv2plus;
10758 let g = Guestfs.create () in
10762 String.concat " " (
10765 | CallString s -> "\"" ^ s ^ "\""
10766 | CallOptString None -> "None"
10767 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10768 | CallStringList xs ->
10769 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10770 | CallInt i when i >= 0 -> string_of_int i
10771 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10772 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10773 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10774 | CallBool b -> string_of_bool b
10779 generate_lang_bindtests (
10780 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10783 pr "print_endline \"EOF\"\n"
10785 and generate_perl_bindtests () =
10786 pr "#!/usr/bin/perl -w\n";
10787 generate_header HashStyle GPLv2plus;
10794 my $g = Sys::Guestfs->new ();
10798 String.concat ", " (
10801 | CallString s -> "\"" ^ s ^ "\""
10802 | CallOptString None -> "undef"
10803 | CallOptString (Some s) -> sprintf "\"%s\"" s
10804 | CallStringList xs ->
10805 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10806 | CallInt i -> string_of_int i
10807 | CallInt64 i -> Int64.to_string i
10808 | CallBool b -> if b then "1" else "0"
10813 generate_lang_bindtests (
10814 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10817 pr "print \"EOF\\n\"\n"
10819 and generate_python_bindtests () =
10820 generate_header HashStyle GPLv2plus;
10825 g = guestfs.GuestFS ()
10829 String.concat ", " (
10832 | CallString s -> "\"" ^ s ^ "\""
10833 | CallOptString None -> "None"
10834 | CallOptString (Some s) -> sprintf "\"%s\"" s
10835 | CallStringList xs ->
10836 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10837 | CallInt i -> string_of_int i
10838 | CallInt64 i -> Int64.to_string i
10839 | CallBool b -> if b then "1" else "0"
10844 generate_lang_bindtests (
10845 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10848 pr "print \"EOF\"\n"
10850 and generate_ruby_bindtests () =
10851 generate_header HashStyle GPLv2plus;
10856 g = Guestfs::create()
10860 String.concat ", " (
10863 | CallString s -> "\"" ^ s ^ "\""
10864 | CallOptString None -> "nil"
10865 | CallOptString (Some s) -> sprintf "\"%s\"" s
10866 | CallStringList xs ->
10867 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10868 | CallInt i -> string_of_int i
10869 | CallInt64 i -> Int64.to_string i
10870 | CallBool b -> string_of_bool b
10875 generate_lang_bindtests (
10876 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10879 pr "print \"EOF\\n\"\n"
10881 and generate_java_bindtests () =
10882 generate_header CStyle GPLv2plus;
10885 import com.redhat.et.libguestfs.*;
10887 public class Bindtests {
10888 public static void main (String[] argv)
10891 GuestFS g = new GuestFS ();
10895 String.concat ", " (
10898 | CallString s -> "\"" ^ s ^ "\""
10899 | CallOptString None -> "null"
10900 | CallOptString (Some s) -> sprintf "\"%s\"" s
10901 | CallStringList xs ->
10903 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10904 | CallInt i -> string_of_int i
10905 | CallInt64 i -> Int64.to_string i
10906 | CallBool b -> string_of_bool b
10911 generate_lang_bindtests (
10912 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10916 System.out.println (\"EOF\");
10918 catch (Exception exn) {
10919 System.err.println (exn);
10926 and generate_haskell_bindtests () =
10927 generate_header HaskellStyle GPLv2plus;
10930 module Bindtests where
10931 import qualified Guestfs
10934 g <- Guestfs.create
10938 String.concat " " (
10941 | CallString s -> "\"" ^ s ^ "\""
10942 | CallOptString None -> "Nothing"
10943 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10944 | CallStringList xs ->
10945 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10946 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10947 | CallInt i -> string_of_int i
10948 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10949 | CallInt64 i -> Int64.to_string i
10950 | CallBool true -> "True"
10951 | CallBool false -> "False"
10956 generate_lang_bindtests (
10957 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10960 pr " putStrLn \"EOF\"\n"
10962 (* Language-independent bindings tests - we do it this way to
10963 * ensure there is parity in testing bindings across all languages.
10965 and generate_lang_bindtests call =
10966 call "test0" [CallString "abc"; CallOptString (Some "def");
10967 CallStringList []; CallBool false;
10968 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10969 call "test0" [CallString "abc"; CallOptString None;
10970 CallStringList []; CallBool false;
10971 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10972 call "test0" [CallString ""; CallOptString (Some "def");
10973 CallStringList []; CallBool false;
10974 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10975 call "test0" [CallString ""; CallOptString (Some "");
10976 CallStringList []; CallBool false;
10977 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10978 call "test0" [CallString "abc"; CallOptString (Some "def");
10979 CallStringList ["1"]; CallBool false;
10980 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10981 call "test0" [CallString "abc"; CallOptString (Some "def");
10982 CallStringList ["1"; "2"]; CallBool false;
10983 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10984 call "test0" [CallString "abc"; CallOptString (Some "def");
10985 CallStringList ["1"]; CallBool true;
10986 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10987 call "test0" [CallString "abc"; CallOptString (Some "def");
10988 CallStringList ["1"]; CallBool false;
10989 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10990 call "test0" [CallString "abc"; CallOptString (Some "def");
10991 CallStringList ["1"]; CallBool false;
10992 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10993 call "test0" [CallString "abc"; CallOptString (Some "def");
10994 CallStringList ["1"]; CallBool false;
10995 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10996 call "test0" [CallString "abc"; CallOptString (Some "def");
10997 CallStringList ["1"]; CallBool false;
10998 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10999 call "test0" [CallString "abc"; CallOptString (Some "def");
11000 CallStringList ["1"]; CallBool false;
11001 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11002 call "test0" [CallString "abc"; CallOptString (Some "def");
11003 CallStringList ["1"]; CallBool false;
11004 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11006 (* XXX Add here tests of the return and error functions. *)
11008 (* Code to generator bindings for virt-inspector. Currently only
11009 * implemented for OCaml code (for virt-p2v 2.0).
11011 let rng_input = "inspector/virt-inspector.rng"
11013 (* Read the input file and parse it into internal structures. This is
11014 * by no means a complete RELAX NG parser, but is just enough to be
11015 * able to parse the specific input file.
11018 | Element of string * rng list (* <element name=name/> *)
11019 | Attribute of string * rng list (* <attribute name=name/> *)
11020 | Interleave of rng list (* <interleave/> *)
11021 | ZeroOrMore of rng (* <zeroOrMore/> *)
11022 | OneOrMore of rng (* <oneOrMore/> *)
11023 | Optional of rng (* <optional/> *)
11024 | Choice of string list (* <choice><value/>*</choice> *)
11025 | Value of string (* <value>str</value> *)
11026 | Text (* <text/> *)
11028 let rec string_of_rng = function
11029 | Element (name, xs) ->
11030 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11031 | Attribute (name, xs) ->
11032 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11033 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11034 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11035 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11036 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11037 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11038 | Value value -> "Value \"" ^ value ^ "\""
11041 and string_of_rng_list xs =
11042 String.concat ", " (List.map string_of_rng xs)
11044 let rec parse_rng ?defines context = function
11046 | Xml.Element ("element", ["name", name], children) :: rest ->
11047 Element (name, parse_rng ?defines context children)
11048 :: parse_rng ?defines context rest
11049 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11050 Attribute (name, parse_rng ?defines context children)
11051 :: parse_rng ?defines context rest
11052 | Xml.Element ("interleave", [], children) :: rest ->
11053 Interleave (parse_rng ?defines context children)
11054 :: parse_rng ?defines context rest
11055 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11056 let rng = parse_rng ?defines context [child] in
11058 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11060 failwithf "%s: <zeroOrMore> contains more than one child element"
11063 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11064 let rng = parse_rng ?defines context [child] in
11066 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11068 failwithf "%s: <oneOrMore> contains more than one child element"
11071 | Xml.Element ("optional", [], [child]) :: rest ->
11072 let rng = parse_rng ?defines context [child] in
11074 | [child] -> Optional child :: parse_rng ?defines context rest
11076 failwithf "%s: <optional> contains more than one child element"
11079 | Xml.Element ("choice", [], children) :: rest ->
11080 let values = List.map (
11081 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11083 failwithf "%s: can't handle anything except <value> in <choice>"
11087 :: parse_rng ?defines context rest
11088 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11089 Value value :: parse_rng ?defines context rest
11090 | Xml.Element ("text", [], []) :: rest ->
11091 Text :: parse_rng ?defines context rest
11092 | Xml.Element ("ref", ["name", name], []) :: rest ->
11093 (* Look up the reference. Because of limitations in this parser,
11094 * we can't handle arbitrarily nested <ref> yet. You can only
11095 * use <ref> from inside <start>.
11097 (match defines with
11099 failwithf "%s: contains <ref>, but no refs are defined yet" context
11101 let rng = StringMap.find name map in
11102 rng @ parse_rng ?defines context rest
11105 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11108 let xml = Xml.parse_file rng_input in
11110 | Xml.Element ("grammar", _,
11111 Xml.Element ("start", _, gram) :: defines) ->
11112 (* The <define/> elements are referenced in the <start> section,
11113 * so build a map of those first.
11115 let defines = List.fold_left (
11117 function Xml.Element ("define", ["name", name], defn) ->
11118 StringMap.add name defn map
11120 failwithf "%s: expected <define name=name/>" rng_input
11121 ) StringMap.empty defines in
11122 let defines = StringMap.mapi parse_rng defines in
11124 (* Parse the <start> clause, passing the defines. *)
11125 parse_rng ~defines "<start>" gram
11127 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11130 let name_of_field = function
11131 | Element (name, _) | Attribute (name, _)
11132 | ZeroOrMore (Element (name, _))
11133 | OneOrMore (Element (name, _))
11134 | Optional (Element (name, _)) -> name
11135 | Optional (Attribute (name, _)) -> name
11136 | Text -> (* an unnamed field in an element *)
11139 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11141 (* At the moment this function only generates OCaml types. However we
11142 * should parameterize it later so it can generate types/structs in a
11143 * variety of languages.
11145 let generate_types xs =
11146 (* A simple type is one that can be printed out directly, eg.
11147 * "string option". A complex type is one which has a name and has
11148 * to be defined via another toplevel definition, eg. a struct.
11150 * generate_type generates code for either simple or complex types.
11151 * In the simple case, it returns the string ("string option"). In
11152 * the complex case, it returns the name ("mountpoint"). In the
11153 * complex case it has to print out the definition before returning,
11154 * so it should only be called when we are at the beginning of a
11155 * new line (BOL context).
11157 let rec generate_type = function
11158 | Text -> (* string *)
11160 | Choice values -> (* [`val1|`val2|...] *)
11161 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11162 | ZeroOrMore rng -> (* <rng> list *)
11163 let t, is_simple = generate_type rng in
11164 t ^ " list (* 0 or more *)", is_simple
11165 | OneOrMore rng -> (* <rng> list *)
11166 let t, is_simple = generate_type rng in
11167 t ^ " list (* 1 or more *)", is_simple
11168 (* virt-inspector hack: bool *)
11169 | Optional (Attribute (name, [Value "1"])) ->
11171 | Optional rng -> (* <rng> list *)
11172 let t, is_simple = generate_type rng in
11173 t ^ " option", is_simple
11174 (* type name = { fields ... } *)
11175 | Element (name, fields) when is_attrs_interleave fields ->
11176 generate_type_struct name (get_attrs_interleave fields)
11177 | Element (name, [field]) (* type name = field *)
11178 | Attribute (name, [field]) ->
11179 let t, is_simple = generate_type field in
11180 if is_simple then (t, true)
11182 pr "type %s = %s\n" name t;
11185 | Element (name, fields) -> (* type name = { fields ... } *)
11186 generate_type_struct name fields
11188 failwithf "generate_type failed at: %s" (string_of_rng rng)
11190 and is_attrs_interleave = function
11191 | [Interleave _] -> true
11192 | Attribute _ :: fields -> is_attrs_interleave fields
11193 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11196 and get_attrs_interleave = function
11197 | [Interleave fields] -> fields
11198 | ((Attribute _) as field) :: fields
11199 | ((Optional (Attribute _)) as field) :: fields ->
11200 field :: get_attrs_interleave fields
11201 | _ -> assert false
11203 and generate_types xs =
11204 List.iter (fun x -> ignore (generate_type x)) xs
11206 and generate_type_struct name fields =
11207 (* Calculate the types of the fields first. We have to do this
11208 * before printing anything so we are still in BOL context.
11210 let types = List.map fst (List.map generate_type fields) in
11212 (* Special case of a struct containing just a string and another
11213 * field. Turn it into an assoc list.
11216 | ["string"; other] ->
11217 let fname1, fname2 =
11219 | [f1; f2] -> name_of_field f1, name_of_field f2
11220 | _ -> assert false in
11221 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11225 pr "type %s = {\n" name;
11227 fun (field, ftype) ->
11228 let fname = name_of_field field in
11229 pr " %s_%s : %s;\n" name fname ftype
11230 ) (List.combine fields types);
11232 (* Return the name of this type, and
11233 * false because it's not a simple type.
11240 let generate_parsers xs =
11241 (* As for generate_type above, generate_parser makes a parser for
11242 * some type, and returns the name of the parser it has generated.
11243 * Because it (may) need to print something, it should always be
11244 * called in BOL context.
11246 let rec generate_parser = function
11247 | Text -> (* string *)
11248 "string_child_or_empty"
11249 | Choice values -> (* [`val1|`val2|...] *)
11250 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11252 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11253 | ZeroOrMore rng -> (* <rng> list *)
11254 let pa = generate_parser rng in
11255 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11256 | OneOrMore rng -> (* <rng> list *)
11257 let pa = generate_parser rng in
11258 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11259 (* virt-inspector hack: bool *)
11260 | Optional (Attribute (name, [Value "1"])) ->
11261 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11262 | Optional rng -> (* <rng> list *)
11263 let pa = generate_parser rng in
11264 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11265 (* type name = { fields ... } *)
11266 | Element (name, fields) when is_attrs_interleave fields ->
11267 generate_parser_struct name (get_attrs_interleave fields)
11268 | Element (name, [field]) -> (* type name = field *)
11269 let pa = generate_parser field in
11270 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11271 pr "let %s =\n" parser_name;
11273 pr "let parse_%s = %s\n" name parser_name;
11275 | Attribute (name, [field]) ->
11276 let pa = generate_parser field in
11277 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11278 pr "let %s =\n" parser_name;
11280 pr "let parse_%s = %s\n" name parser_name;
11282 | Element (name, fields) -> (* type name = { fields ... } *)
11283 generate_parser_struct name ([], fields)
11285 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11287 and is_attrs_interleave = function
11288 | [Interleave _] -> true
11289 | Attribute _ :: fields -> is_attrs_interleave fields
11290 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11293 and get_attrs_interleave = function
11294 | [Interleave fields] -> [], fields
11295 | ((Attribute _) as field) :: fields
11296 | ((Optional (Attribute _)) as field) :: fields ->
11297 let attrs, interleaves = get_attrs_interleave fields in
11298 (field :: attrs), interleaves
11299 | _ -> assert false
11301 and generate_parsers xs =
11302 List.iter (fun x -> ignore (generate_parser x)) xs
11304 and generate_parser_struct name (attrs, interleaves) =
11305 (* Generate parsers for the fields first. We have to do this
11306 * before printing anything so we are still in BOL context.
11308 let fields = attrs @ interleaves in
11309 let pas = List.map generate_parser fields in
11311 (* Generate an intermediate tuple from all the fields first.
11312 * If the type is just a string + another field, then we will
11313 * return this directly, otherwise it is turned into a record.
11315 * RELAX NG note: This code treats <interleave> and plain lists of
11316 * fields the same. In other words, it doesn't bother enforcing
11317 * any ordering of fields in the XML.
11319 pr "let parse_%s x =\n" name;
11320 pr " let t = (\n ";
11321 let comma = ref false in
11324 if !comma then pr ",\n ";
11327 | Optional (Attribute (fname, [field])), pa ->
11329 | Optional (Element (fname, [field])), pa ->
11330 pr "%s (optional_child %S x)" pa fname
11331 | Attribute (fname, [Text]), _ ->
11332 pr "attribute %S x" fname
11333 | (ZeroOrMore _ | OneOrMore _), pa ->
11338 let fname = name_of_field field in
11339 pr "%s (child %S x)" pa fname
11340 ) (List.combine fields pas);
11344 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11348 pr " (Obj.magic t : %s)\n" name
11352 | (Optional (Attribute (fname, [field])), pa) ->
11353 pr " %s_%s =\n" name fname;
11355 | (Optional (Element (fname, [field])), pa) ->
11356 pr " %s_%s =\n" name fname;
11357 pr " (let x = optional_child %S x in\n" fname;
11360 let fname = name_of_field field in
11361 pr " %s_%s =\n" name fname;
11362 pr " (let x = child %S x in\n" fname;
11364 ) (List.combine fields pas);
11368 sprintf "parse_%s" name
11371 generate_parsers xs
11373 (* Generate ocaml/guestfs_inspector.mli. *)
11374 let generate_ocaml_inspector_mli () =
11375 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11378 (** This is an OCaml language binding to the external [virt-inspector]
11381 For more information, please read the man page [virt-inspector(1)].
11386 generate_types grammar;
11387 pr "(** The nested information returned from the {!inspect} function. *)\n";
11391 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11392 (** To inspect a libvirt domain called [name], pass a singleton
11393 list: [inspect [name]]. When using libvirt only, you may
11394 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11396 To inspect a disk image or images, pass a list of the filenames
11397 of the disk images: [inspect filenames]
11399 This function inspects the given guest or disk images and
11400 returns a list of operating system(s) found and a large amount
11401 of information about them. In the vast majority of cases,
11402 a virtual machine only contains a single operating system.
11404 If the optional [~xml] parameter is given, then this function
11405 skips running the external virt-inspector program and just
11406 parses the given XML directly (which is expected to be XML
11407 produced from a previous run of virt-inspector). The list of
11408 names and connect URI are ignored in this case.
11410 This function can throw a wide variety of exceptions, for example
11411 if the external virt-inspector program cannot be found, or if
11412 it doesn't generate valid XML.
11416 (* Generate ocaml/guestfs_inspector.ml. *)
11417 let generate_ocaml_inspector_ml () =
11418 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11423 generate_types grammar;
11427 (* Misc functions which are used by the parser code below. *)
11428 let first_child = function
11429 | Xml.Element (_, _, c::_) -> c
11430 | Xml.Element (name, _, []) ->
11431 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11432 | Xml.PCData str ->
11433 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11435 let string_child_or_empty = function
11436 | Xml.Element (_, _, [Xml.PCData s]) -> s
11437 | Xml.Element (_, _, []) -> \"\"
11438 | Xml.Element (x, _, _) ->
11439 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11441 | Xml.PCData str ->
11442 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11444 let optional_child name xml =
11445 let children = Xml.children xml in
11447 Some (List.find (function
11448 | Xml.Element (n, _, _) when n = name -> true
11449 | _ -> false) children)
11453 let child name xml =
11454 match optional_child name xml with
11457 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11459 let attribute name xml =
11460 try Xml.attrib xml name
11461 with Xml.No_attribute _ ->
11462 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11466 generate_parsers grammar;
11470 (* Run external virt-inspector, then use parser to parse the XML. *)
11471 let inspect ?connect ?xml names =
11475 if names = [] then invalid_arg \"inspect: no names given\";
11476 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11477 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11479 let cmd = List.map Filename.quote cmd in
11480 let cmd = String.concat \" \" cmd in
11481 let chan = open_process_in cmd in
11482 let xml = Xml.parse_in chan in
11483 (match close_process_in chan with
11485 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11486 | WSIGNALED i | WSTOPPED i ->
11487 failwith (\"external virt-inspector command died or stopped on sig \" ^
11492 Xml.parse_string doc in
11493 parse_operatingsystems xml
11496 (* This is used to generate the src/MAX_PROC_NR file which
11497 * contains the maximum procedure number, a surrogate for the
11498 * ABI version number. See src/Makefile.am for the details.
11500 and generate_max_proc_nr () =
11501 let proc_nrs = List.map (
11502 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11503 ) daemon_functions in
11505 let max_proc_nr = List.fold_left max 0 proc_nrs in
11507 pr "%d\n" max_proc_nr
11509 let output_to filename k =
11510 let filename_new = filename ^ ".new" in
11511 chan := open_out filename_new;
11514 chan := Pervasives.stdout;
11516 (* Is the new file different from the current file? *)
11517 if Sys.file_exists filename && files_equal filename filename_new then
11518 unlink filename_new (* same, so skip it *)
11520 (* different, overwrite old one *)
11521 (try chmod filename 0o644 with Unix_error _ -> ());
11522 rename filename_new filename;
11523 chmod filename 0o444;
11524 printf "written %s\n%!" filename;
11527 let perror msg = function
11528 | Unix_error (err, _, _) ->
11529 eprintf "%s: %s\n" msg (error_message err)
11531 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11533 (* Main program. *)
11536 try openfile "HACKING" [O_RDWR] 0
11538 | Unix_error (ENOENT, _, _) ->
11540 You are probably running this from the wrong directory.
11541 Run it from the top source directory using the command
11546 perror "open: HACKING" exn;
11549 (* Acquire a lock so parallel builds won't try to run the generator
11550 * twice at the same time. Subsequent builds will wait for the first
11551 * one to finish. Note the lock is released implicitly when the
11554 (try lockf lock_fd F_LOCK 1
11556 perror "lock: HACKING" exn;
11559 check_functions ();
11561 output_to "src/guestfs_protocol.x" generate_xdr;
11562 output_to "src/guestfs-structs.h" generate_structs_h;
11563 output_to "src/guestfs-actions.h" generate_actions_h;
11564 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11565 output_to "src/guestfs-actions.c" generate_client_actions;
11566 output_to "src/guestfs-bindtests.c" generate_bindtests;
11567 output_to "src/guestfs-structs.pod" generate_structs_pod;
11568 output_to "src/guestfs-actions.pod" generate_actions_pod;
11569 output_to "src/guestfs-availability.pod" generate_availability_pod;
11570 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11571 output_to "src/libguestfs.syms" generate_linker_script;
11572 output_to "daemon/actions.h" generate_daemon_actions_h;
11573 output_to "daemon/stubs.c" generate_daemon_actions;
11574 output_to "daemon/names.c" generate_daemon_names;
11575 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11576 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11577 output_to "capitests/tests.c" generate_tests;
11578 output_to "fish/cmds.c" generate_fish_cmds;
11579 output_to "fish/completion.c" generate_fish_completion;
11580 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11581 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11582 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11583 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11584 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11585 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11586 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11587 output_to "perl/Guestfs.xs" generate_perl_xs;
11588 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11589 output_to "perl/bindtests.pl" generate_perl_bindtests;
11590 output_to "python/guestfs-py.c" generate_python_c;
11591 output_to "python/guestfs.py" generate_python_py;
11592 output_to "python/bindtests.py" generate_python_bindtests;
11593 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11594 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11595 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11599 let cols = cols_of_struct typ in
11600 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11601 output_to filename (generate_java_struct jtyp cols);
11604 output_to "java/Makefile.inc" generate_java_makefile_inc;
11605 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11606 output_to "java/Bindtests.java" generate_java_bindtests;
11607 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11608 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11609 output_to "csharp/Libguestfs.cs" generate_csharp;
11611 (* Always generate this file last, and unconditionally. It's used
11612 * by the Makefile to know when we must re-run the generator.
11614 let chan = open_out "src/stamp-generator" in
11615 fprintf chan "1\n";
11618 printf "generated %d lines of code\n" !lines