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 The mode actually set is affected by the umask.");
1397 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398 [], (* XXX Need stat command to test *)
1399 "change file owner and group",
1401 Change the file owner to C<owner> and group to C<group>.
1403 Only numeric uid and gid are supported. If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1407 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408 [InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/empty"]]);
1410 InitISOFS, Always, TestOutputTrue (
1411 [["exists"; "/directory"]])],
1412 "test if file or directory exists",
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1419 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420 [InitISOFS, Always, TestOutputTrue (
1421 [["is_file"; "/known-1"]]);
1422 InitISOFS, Always, TestOutputFalse (
1423 [["is_file"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name. Note that it returns false for
1428 other objects like directories.
1430 See also C<guestfs_stat>.");
1432 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433 [InitISOFS, Always, TestOutputFalse (
1434 [["is_dir"; "/known-3"]]);
1435 InitISOFS, Always, TestOutputTrue (
1436 [["is_dir"; "/directory"]])],
1437 "test if file exists",
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name. Note that it returns false for
1441 other objects like files.
1443 See also C<guestfs_stat>.");
1445 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputListOfDevices (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452 "create an LVM physical volume",
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1458 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459 [InitEmpty, Always, TestOutputList (
1460 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461 ["pvcreate"; "/dev/sda1"];
1462 ["pvcreate"; "/dev/sda2"];
1463 ["pvcreate"; "/dev/sda3"];
1464 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465 ["vgcreate"; "VG2"; "/dev/sda3"];
1466 ["vgs"]], ["VG1"; "VG2"])],
1467 "create an LVM volume group",
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1472 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473 [InitEmpty, Always, TestOutputList (
1474 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475 ["pvcreate"; "/dev/sda1"];
1476 ["pvcreate"; "/dev/sda2"];
1477 ["pvcreate"; "/dev/sda3"];
1478 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479 ["vgcreate"; "VG2"; "/dev/sda3"];
1480 ["lvcreate"; "LV1"; "VG1"; "50"];
1481 ["lvcreate"; "LV2"; "VG1"; "50"];
1482 ["lvcreate"; "LV3"; "VG2"; "50"];
1483 ["lvcreate"; "LV4"; "VG2"; "50"];
1484 ["lvcreate"; "LV5"; "VG2"; "50"];
1486 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488 "create an LVM logical volume",
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1493 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494 [InitEmpty, Always, TestOutput (
1495 [["part_disk"; "/dev/sda"; "mbr"];
1496 ["mkfs"; "ext2"; "/dev/sda1"];
1497 ["mount_options"; ""; "/dev/sda1"; "/"];
1498 ["write_file"; "/new"; "new file contents"; "0"];
1499 ["cat"; "/new"]], "new file contents")],
1500 "make a filesystem",
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume). The filesystem type is C<fstype>, for
1506 ("sfdisk", (RErr, [Device "device";
1507 Int "cyls"; Int "heads"; Int "sectors";
1508 StringList "lines"]), 43, [DangerWillRobinson],
1510 "create partitions on a block device",
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1515 C<device> should be a block device, for example C</dev/sda>.
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted. Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1525 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1526 information refer to the L<sfdisk(8)> manpage.
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1535 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536 [InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "new file contents"; "0"];
1538 ["cat"; "/new"]], "new file contents");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541 ["cat"; "/new"]], "\nnew file contents\n");
1542 InitBasicFS, Always, TestOutput (
1543 [["write_file"; "/new"; "\n\n"; "0"];
1544 ["cat"; "/new"]], "\n\n");
1545 InitBasicFS, Always, TestOutput (
1546 [["write_file"; "/new"; ""; "0"];
1547 ["cat"; "/new"]], "");
1548 InitBasicFS, Always, TestOutput (
1549 [["write_file"; "/new"; "\n\n\n"; "0"];
1550 ["cat"; "/new"]], "\n\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["write_file"; "/new"; "\n"; "0"];
1553 ["cat"; "/new"]], "\n")],
1556 This call creates a file called C<path>. The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version. In the meantime
1567 use C<guestfs_upload>.");
1569 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570 [InitEmpty, Always, TestOutputListOfDevices (
1571 [["part_disk"; "/dev/sda"; "mbr"];
1572 ["mkfs"; "ext2"; "/dev/sda1"];
1573 ["mount_options"; ""; "/dev/sda1"; "/"];
1574 ["mounts"]], ["/dev/sda1"]);
1575 InitEmpty, Always, TestOutputList (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 "unmount a filesystem",
1583 This unmounts the given filesystem. The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1587 ("mounts", (RStringList "devices", []), 46, [],
1588 [InitBasicFS, Always, TestOutputListOfDevices (
1589 [["mounts"]], ["/dev/sda1"])],
1590 "show mounted filesystems",
1592 This returns the list of currently mounted filesystems. It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1595 Some internal mounts are not shown.
1597 See also: C<guestfs_mountpoints>");
1599 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600 [InitBasicFS, Always, TestOutputList (
1603 (* check that umount_all can unmount nested mounts correctly: *)
1604 InitEmpty, Always, TestOutputList (
1605 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606 ["mkfs"; "ext2"; "/dev/sda1"];
1607 ["mkfs"; "ext2"; "/dev/sda2"];
1608 ["mkfs"; "ext2"; "/dev/sda3"];
1609 ["mount_options"; ""; "/dev/sda1"; "/"];
1611 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612 ["mkdir"; "/mp1/mp2"];
1613 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614 ["mkdir"; "/mp1/mp2/mp3"];
1617 "unmount all filesystems",
1619 This unmounts all mounted filesystems.
1621 Some internal mounts are not unmounted by this call.");
1623 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1625 "remove all LVM LVs, VGs and PVs",
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1630 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631 [InitISOFS, Always, TestOutput (
1632 [["file"; "/empty"]], "empty");
1633 InitISOFS, Always, TestOutput (
1634 [["file"; "/known-1"]], "ASCII text");
1635 InitISOFS, Always, TestLastFail (
1636 [["file"; "/notexists"]])],
1637 "determine file type",
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file. This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zbsL path>. Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1650 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651 [InitBasicFS, Always, TestOutput (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command"; "/test-command 1"]], "Result1");
1655 InitBasicFS, Always, TestOutput (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command"; "/test-command 2"]], "Result2\n");
1659 InitBasicFS, Always, TestOutput (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command"; "/test-command 3"]], "\nResult3");
1663 InitBasicFS, Always, TestOutput (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command"; "/test-command 4"]], "\nResult4\n");
1667 InitBasicFS, Always, TestOutput (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command"; "/test-command 5"]], "\nResult5\n\n");
1671 InitBasicFS, Always, TestOutput (
1672 [["upload"; "test-command"; "/test-command"];
1673 ["chmod"; "0o755"; "/test-command"];
1674 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675 InitBasicFS, Always, TestOutput (
1676 [["upload"; "test-command"; "/test-command"];
1677 ["chmod"; "0o755"; "/test-command"];
1678 ["command"; "/test-command 7"]], "");
1679 InitBasicFS, Always, TestOutput (
1680 [["upload"; "test-command"; "/test-command"];
1681 ["chmod"; "0o755"; "/test-command"];
1682 ["command"; "/test-command 8"]], "\n");
1683 InitBasicFS, Always, TestOutput (
1684 [["upload"; "test-command"; "/test-command"];
1685 ["chmod"; "0o755"; "/test-command"];
1686 ["command"; "/test-command 9"]], "\n\n");
1687 InitBasicFS, Always, TestOutput (
1688 [["upload"; "test-command"; "/test-command"];
1689 ["chmod"; "0o755"; "/test-command"];
1690 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691 InitBasicFS, Always, TestOutput (
1692 [["upload"; "test-command"; "/test-command"];
1693 ["chmod"; "0o755"; "/test-command"];
1694 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695 InitBasicFS, Always, TestLastFail (
1696 [["upload"; "test-command"; "/test-command"];
1697 ["chmod"; "0o755"; "/test-command"];
1698 ["command"; "/test-command"]])],
1699 "run a command from the guest filesystem",
1701 This call runs a command from the guest filesystem. The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters. The list must be
1709 non-empty (ie. must contain a program name). Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1713 The return value is anything printed to I<stdout> by
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message. The error message
1718 string is the content of I<stderr> from the command.
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>. If you require a program from
1722 another location, you should provide the full path in the
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places. It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1731 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732 [InitBasicFS, Always, TestOutputList (
1733 [["upload"; "test-command"; "/test-command"];
1734 ["chmod"; "0o755"; "/test-command"];
1735 ["command_lines"; "/test-command 1"]], ["Result1"]);
1736 InitBasicFS, Always, TestOutputList (
1737 [["upload"; "test-command"; "/test-command"];
1738 ["chmod"; "0o755"; "/test-command"];
1739 ["command_lines"; "/test-command 2"]], ["Result2"]);
1740 InitBasicFS, Always, TestOutputList (
1741 [["upload"; "test-command"; "/test-command"];
1742 ["chmod"; "0o755"; "/test-command"];
1743 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744 InitBasicFS, Always, TestOutputList (
1745 [["upload"; "test-command"; "/test-command"];
1746 ["chmod"; "0o755"; "/test-command"];
1747 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748 InitBasicFS, Always, TestOutputList (
1749 [["upload"; "test-command"; "/test-command"];
1750 ["chmod"; "0o755"; "/test-command"];
1751 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752 InitBasicFS, Always, TestOutputList (
1753 [["upload"; "test-command"; "/test-command"];
1754 ["chmod"; "0o755"; "/test-command"];
1755 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756 InitBasicFS, Always, TestOutputList (
1757 [["upload"; "test-command"; "/test-command"];
1758 ["chmod"; "0o755"; "/test-command"];
1759 ["command_lines"; "/test-command 7"]], []);
1760 InitBasicFS, Always, TestOutputList (
1761 [["upload"; "test-command"; "/test-command"];
1762 ["chmod"; "0o755"; "/test-command"];
1763 ["command_lines"; "/test-command 8"]], [""]);
1764 InitBasicFS, Always, TestOutputList (
1765 [["upload"; "test-command"; "/test-command"];
1766 ["chmod"; "0o755"; "/test-command"];
1767 ["command_lines"; "/test-command 9"]], ["";""]);
1768 InitBasicFS, Always, TestOutputList (
1769 [["upload"; "test-command"; "/test-command"];
1770 ["chmod"; "0o755"; "/test-command"];
1771 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772 InitBasicFS, Always, TestOutputList (
1773 [["upload"; "test-command"; "/test-command"];
1774 ["chmod"; "0o755"; "/test-command"];
1775 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776 "run a command, returning lines",
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1781 See also: C<guestfs_sh_lines>");
1783 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784 [InitISOFS, Always, TestOutputStruct (
1785 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786 "get file information",
1788 Returns file information for the given C<path>.
1790 This is the same as the C<stat(2)> system call.");
1792 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795 "get file information for a symbolic link",
1797 Returns file information for the given C<path>.
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1803 This is the same as the C<lstat(2)> system call.");
1805 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806 [InitISOFS, Always, TestOutputStruct (
1807 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808 "get file system statistics",
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1814 This is the same as the C<statvfs(2)> system call.");
1816 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1818 "get ext2/ext3/ext4 superblock details",
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1823 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1824 manpage for more details. The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1828 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829 [InitEmpty, Always, TestOutputTrue (
1830 [["blockdev_setro"; "/dev/sda"];
1831 ["blockdev_getro"; "/dev/sda"]])],
1832 "set block device to read-only",
1834 Sets the block device named C<device> to read-only.
1836 This uses the L<blockdev(8)> command.");
1838 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839 [InitEmpty, Always, TestOutputFalse (
1840 [["blockdev_setrw"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-write",
1844 Sets the block device named C<device> to read-write.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849 [InitEmpty, Always, TestOutputTrue (
1850 [["blockdev_setro"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "is block device set to read-only",
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getss"; "/dev/sda"]], 512)],
1862 "get sectorsize of block device",
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 This uses the L<blockdev(8)> command.");
1872 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873 [InitEmpty, Always, TestOutputInt (
1874 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875 "get blocksize of block device",
1877 This returns the block size of a device.
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1882 This uses the L<blockdev(8)> command.");
1884 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1886 "set blocksize of block device",
1888 This sets the block size of a device.
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1893 This uses the L<blockdev(8)> command.");
1895 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896 [InitEmpty, Always, TestOutputInt (
1897 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898 "get total size of device in 512-byte sectors",
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1907 This uses the L<blockdev(8)> command.");
1909 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910 [InitEmpty, Always, TestOutputInt (
1911 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912 "get total size of device in bytes",
1914 This returns the size of the device in bytes.
1916 See also C<guestfs_blockdev_getsz>.
1918 This uses the L<blockdev(8)> command.");
1920 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921 [InitEmpty, Always, TestRun
1922 [["blockdev_flushbufs"; "/dev/sda"]]],
1923 "flush device buffers",
1925 This tells the kernel to flush internal buffers associated
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_rereadpt"; "/dev/sda"]]],
1933 "reread partition table",
1935 Reread the partition table on C<device>.
1937 This uses the L<blockdev(8)> command.");
1939 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940 [InitBasicFS, Always, TestOutput (
1941 (* Pick a file from cwd which isn't likely to change. *)
1942 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943 ["checksum"; "md5"; "/COPYING.LIB"]],
1944 Digest.to_hex (Digest.file "COPYING.LIB"))],
1945 "upload a file from the local machine",
1947 Upload local file C<filename> to C<remotefilename> on the
1950 C<filename> can also be a named pipe.
1952 See also C<guestfs_download>.");
1954 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955 [InitBasicFS, Always, TestOutput (
1956 (* Pick a file from cwd which isn't likely to change. *)
1957 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959 ["upload"; "testdownload.tmp"; "/upload"];
1960 ["checksum"; "md5"; "/upload"]],
1961 Digest.to_hex (Digest.file "COPYING.LIB"))],
1962 "download a file to the local machine",
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1967 C<filename> can also be a named pipe.
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1971 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972 [InitISOFS, Always, TestOutput (
1973 [["checksum"; "crc"; "/known-3"]], "2891671662");
1974 InitISOFS, Always, TestLastFail (
1975 [["checksum"; "crc"; "/notexists"]]);
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988 "compute MD5, SHAx or CRC checksum of file",
1990 This call computes the MD5, SHAx or CRC checksum of the
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2005 Compute the MD5 hash (using the C<md5sum> program).
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2029 The checksum is returned as a printable string.");
2031 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2032 [InitBasicFS, Always, TestOutput (
2033 [["tar_in"; "../images/helloworld.tar"; "/"];
2034 ["cat"; "/hello"]], "hello\n")],
2035 "unpack tarfile to directory",
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2040 To upload a compressed tarball, use C<guestfs_tgz_in>
2041 or C<guestfs_txz_in>.");
2043 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2045 "pack directory into tarfile",
2047 This command packs the contents of C<directory> and downloads
2048 it to local file C<tarfile>.
2050 To download a compressed tarball, use C<guestfs_tgz_out>
2051 or C<guestfs_txz_out>.");
2053 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2054 [InitBasicFS, Always, TestOutput (
2055 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056 ["cat"; "/hello"]], "hello\n")],
2057 "unpack compressed tarball to directory",
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2064 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2066 "pack directory into compressed tarball",
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2073 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074 [InitBasicFS, Always, TestLastFail (
2076 ["mount_ro"; "/dev/sda1"; "/"];
2077 ["touch"; "/new"]]);
2078 InitBasicFS, Always, TestOutput (
2079 [["write_file"; "/new"; "data"; "0"];
2081 ["mount_ro"; "/dev/sda1"; "/"];
2082 ["cat"; "/new"]], "data")],
2083 "mount a guest disk, read-only",
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2088 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2090 "mount a guest disk with mount options",
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.");
2096 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2098 "mount a guest disk with mount options and vfstype",
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2104 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2106 "debugging and internals",
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2112 There is no comprehensive help for this command. You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2116 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117 [InitEmpty, Always, TestOutputList (
2118 [["part_disk"; "/dev/sda"; "mbr"];
2119 ["pvcreate"; "/dev/sda1"];
2120 ["vgcreate"; "VG"; "/dev/sda1"];
2121 ["lvcreate"; "LV1"; "VG"; "50"];
2122 ["lvcreate"; "LV2"; "VG"; "50"];
2123 ["lvremove"; "/dev/VG/LV1"];
2124 ["lvs"]], ["/dev/VG/LV2"]);
2125 InitEmpty, Always, TestOutputList (
2126 [["part_disk"; "/dev/sda"; "mbr"];
2127 ["pvcreate"; "/dev/sda1"];
2128 ["vgcreate"; "VG"; "/dev/sda1"];
2129 ["lvcreate"; "LV1"; "VG"; "50"];
2130 ["lvcreate"; "LV2"; "VG"; "50"];
2131 ["lvremove"; "/dev/VG"];
2133 InitEmpty, Always, TestOutputList (
2134 [["part_disk"; "/dev/sda"; "mbr"];
2135 ["pvcreate"; "/dev/sda1"];
2136 ["vgcreate"; "VG"; "/dev/sda1"];
2137 ["lvcreate"; "LV1"; "VG"; "50"];
2138 ["lvcreate"; "LV2"; "VG"; "50"];
2139 ["lvremove"; "/dev/VG"];
2141 "remove an LVM logical volume",
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2149 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150 [InitEmpty, Always, TestOutputList (
2151 [["part_disk"; "/dev/sda"; "mbr"];
2152 ["pvcreate"; "/dev/sda1"];
2153 ["vgcreate"; "VG"; "/dev/sda1"];
2154 ["lvcreate"; "LV1"; "VG"; "50"];
2155 ["lvcreate"; "LV2"; "VG"; "50"];
2158 InitEmpty, Always, TestOutputList (
2159 [["part_disk"; "/dev/sda"; "mbr"];
2160 ["pvcreate"; "/dev/sda1"];
2161 ["vgcreate"; "VG"; "/dev/sda1"];
2162 ["lvcreate"; "LV1"; "VG"; "50"];
2163 ["lvcreate"; "LV2"; "VG"; "50"];
2166 "remove an LVM volume group",
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2170 This also forcibly removes all logical volumes in the volume
2173 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174 [InitEmpty, Always, TestOutputListOfDevices (
2175 [["part_disk"; "/dev/sda"; "mbr"];
2176 ["pvcreate"; "/dev/sda1"];
2177 ["vgcreate"; "VG"; "/dev/sda1"];
2178 ["lvcreate"; "LV1"; "VG"; "50"];
2179 ["lvcreate"; "LV2"; "VG"; "50"];
2181 ["pvremove"; "/dev/sda1"];
2183 InitEmpty, Always, TestOutputListOfDevices (
2184 [["part_disk"; "/dev/sda"; "mbr"];
2185 ["pvcreate"; "/dev/sda1"];
2186 ["vgcreate"; "VG"; "/dev/sda1"];
2187 ["lvcreate"; "LV1"; "VG"; "50"];
2188 ["lvcreate"; "LV2"; "VG"; "50"];
2190 ["pvremove"; "/dev/sda1"];
2192 InitEmpty, Always, TestOutputListOfDevices (
2193 [["part_disk"; "/dev/sda"; "mbr"];
2194 ["pvcreate"; "/dev/sda1"];
2195 ["vgcreate"; "VG"; "/dev/sda1"];
2196 ["lvcreate"; "LV1"; "VG"; "50"];
2197 ["lvcreate"; "LV2"; "VG"; "50"];
2199 ["pvremove"; "/dev/sda1"];
2201 "remove an LVM physical volume",
2203 This wipes a physical volume C<device> so that LVM will no longer
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2210 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211 [InitBasicFS, Always, TestOutput (
2212 [["set_e2label"; "/dev/sda1"; "testlabel"];
2213 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214 "set the ext2/3/4 filesystem label",
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>. Filesystem labels are limited to
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2223 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2225 "get the ext2/3/4 filesystem label",
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2230 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231 (let uuid = uuidgen () in
2232 [InitBasicFS, Always, TestOutput (
2233 [["set_e2uuid"; "/dev/sda1"; uuid];
2234 ["get_e2uuid"; "/dev/sda1"]], uuid);
2235 InitBasicFS, Always, TestOutput (
2236 [["set_e2uuid"; "/dev/sda1"; "clear"];
2237 ["get_e2uuid"; "/dev/sda1"]], "");
2238 (* We can't predict what UUIDs will be, so just check the commands run. *)
2239 InitBasicFS, Always, TestRun (
2240 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241 InitBasicFS, Always, TestRun (
2242 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243 "set the ext2/3/4 filesystem UUID",
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>. The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2253 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2255 "get the ext2/3/4 filesystem UUID",
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2261 [InitBasicFS, Always, TestOutputInt (
2262 [["umount"; "/dev/sda1"];
2263 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264 InitBasicFS, Always, TestOutputInt (
2265 [["umount"; "/dev/sda1"];
2266 ["zero"; "/dev/sda1"];
2267 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268 "run the filesystem checker",
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2273 The returned integer is the status. See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2282 Multiple status codes can be summed together.
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2291 Checking or repairing NTFS volumes is not supported
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2298 ("zero", (RErr, [Device "device"]), 85, [],
2299 [InitBasicFS, Always, TestOutput (
2300 [["umount"; "/dev/sda1"];
2301 ["zero"; "/dev/sda1"];
2302 ["file"; "/dev/sda1"]], "data")],
2303 "write zeroes to the device",
2305 This command writes zeroes over the first few blocks of C<device>.
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device). It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2311 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2313 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314 (* Test disabled because grub-install incompatible with virtio-blk driver.
2315 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2317 [InitBasicFS, Disabled, TestOutputTrue (
2318 [["grub_install"; "/"; "/dev/sda1"];
2319 ["is_dir"; "/boot"]])],
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2325 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326 [InitBasicFS, Always, TestOutput (
2327 [["write_file"; "/old"; "file content"; "0"];
2328 ["cp"; "/old"; "/new"];
2329 ["cat"; "/new"]], "file content");
2330 InitBasicFS, Always, TestOutputTrue (
2331 [["write_file"; "/old"; "file content"; "0"];
2332 ["cp"; "/old"; "/new"];
2333 ["is_file"; "/old"]]);
2334 InitBasicFS, Always, TestOutput (
2335 [["write_file"; "/old"; "file content"; "0"];
2337 ["cp"; "/old"; "/dir/new"];
2338 ["cat"; "/dir/new"]], "file content")],
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2344 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345 [InitBasicFS, Always, TestOutput (
2346 [["mkdir"; "/olddir"];
2347 ["mkdir"; "/newdir"];
2348 ["write_file"; "/olddir/file"; "file content"; "0"];
2349 ["cp_a"; "/olddir"; "/newdir"];
2350 ["cat"; "/newdir/olddir/file"]], "file content")],
2351 "copy a file or directory recursively",
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2356 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357 [InitBasicFS, Always, TestOutput (
2358 [["write_file"; "/old"; "file content"; "0"];
2359 ["mv"; "/old"; "/new"];
2360 ["cat"; "/new"]], "file content");
2361 InitBasicFS, Always, TestOutputFalse (
2362 [["write_file"; "/old"; "file content"; "0"];
2363 ["mv"; "/old"; "/new"];
2364 ["is_file"; "/old"]])],
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2370 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371 [InitEmpty, Always, TestRun (
2372 [["drop_caches"; "3"]])],
2373 "drop kernel page cache, dentries and inodes",
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches. The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2380 Setting C<whattodrop> to 3 should drop everything.
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2385 ("dmesg", (RString "kmsgs", []), 91, [],
2386 [InitEmpty, Always, TestRun (
2388 "return kernel messages",
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel. This is sometimes useful for extended
2392 debugging of problems.
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2399 ("ping_daemon", (RErr, []), 92, [],
2400 [InitEmpty, Always, TestRun (
2401 [["ping_daemon"]])],
2402 "ping the guest daemon",
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess. Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2409 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410 [InitBasicFS, Always, TestOutputTrue (
2411 [["write_file"; "/file1"; "contents of a file"; "0"];
2412 ["cp"; "/file1"; "/file2"];
2413 ["equal"; "/file1"; "/file2"]]);
2414 InitBasicFS, Always, TestOutputFalse (
2415 [["write_file"; "/file1"; "contents of a file"; "0"];
2416 ["write_file"; "/file2"; "contents of another file"; "0"];
2417 ["equal"; "/file1"; "/file2"]]);
2418 InitBasicFS, Always, TestLastFail (
2419 [["equal"; "/file1"; "/file2"]])],
2420 "test if two files have equal contents",
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2425 The external L<cmp(1)> program is used for the comparison.");
2427 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428 [InitISOFS, Always, TestOutputList (
2429 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430 InitISOFS, Always, TestOutputList (
2431 [["strings"; "/empty"]], [])],
2432 "print the printable strings in a file",
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2437 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438 [InitISOFS, Always, TestOutputList (
2439 [["strings_e"; "b"; "/known-5"]], []);
2440 InitBasicFS, Disabled, TestOutputList (
2441 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443 "print the printable strings in a file",
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding.
2448 See the L<strings(1)> manpage for the full list of encodings.
2450 Commonly useful encodings are C<l> (lower case L) which will
2451 show strings inside Windows/x86 files.
2453 The returned strings are transcoded to UTF-8.");
2455 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2456 [InitISOFS, Always, TestOutput (
2457 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2458 (* Test for RHBZ#501888c2 regression which caused large hexdump
2459 * commands to segfault.
2461 InitISOFS, Always, TestRun (
2462 [["hexdump"; "/100krandom"]])],
2463 "dump a file in hexadecimal",
2465 This runs C<hexdump -C> on the given C<path>. The result is
2466 the human-readable, canonical hex dump of the file.");
2468 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2469 [InitNone, Always, TestOutput (
2470 [["part_disk"; "/dev/sda"; "mbr"];
2471 ["mkfs"; "ext3"; "/dev/sda1"];
2472 ["mount_options"; ""; "/dev/sda1"; "/"];
2473 ["write_file"; "/new"; "test file"; "0"];
2474 ["umount"; "/dev/sda1"];
2475 ["zerofree"; "/dev/sda1"];
2476 ["mount_options"; ""; "/dev/sda1"; "/"];
2477 ["cat"; "/new"]], "test file")],
2478 "zero unused inodes and disk blocks on ext2/3 filesystem",
2480 This runs the I<zerofree> program on C<device>. This program
2481 claims to zero unused inodes and disk blocks on an ext2/3
2482 filesystem, thus making it possible to compress the filesystem
2485 You should B<not> run this program if the filesystem is
2488 It is possible that using this program can damage the filesystem
2489 or data on the filesystem.");
2491 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2493 "resize an LVM physical volume",
2495 This resizes (expands or shrinks) an existing LVM physical
2496 volume to match the new size of the underlying device.");
2498 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2499 Int "cyls"; Int "heads"; Int "sectors";
2500 String "line"]), 99, [DangerWillRobinson],
2502 "modify a single partition on a block device",
2504 This runs L<sfdisk(8)> option to modify just the single
2505 partition C<n> (note: C<n> counts from 1).
2507 For other parameters, see C<guestfs_sfdisk>. You should usually
2508 pass C<0> for the cyls/heads/sectors parameters.
2510 See also: C<guestfs_part_add>");
2512 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2514 "display the partition table",
2516 This displays the partition table on C<device>, in the
2517 human-readable output of the L<sfdisk(8)> command. It is
2518 not intended to be parsed.
2520 See also: C<guestfs_part_list>");
2522 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2524 "display the kernel geometry",
2526 This displays the kernel's idea of the geometry of C<device>.
2528 The result is in human-readable format, and not designed to
2531 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2533 "display the disk geometry from the partition table",
2535 This displays the disk geometry of C<device> read from the
2536 partition table. Especially in the case where the underlying
2537 block device has been resized, this can be different from the
2538 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2540 The result is in human-readable format, and not designed to
2543 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2545 "activate or deactivate all volume groups",
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in all volume groups.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2551 then those devices disappear.
2553 This command is the same as running C<vgchange -a y|n>");
2555 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2557 "activate or deactivate some volume groups",
2559 This command activates or (if C<activate> is false) deactivates
2560 all logical volumes in the listed volume groups C<volgroups>.
2561 If activated, then they are made known to the
2562 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2563 then those devices disappear.
2565 This command is the same as running C<vgchange -a y|n volgroups...>
2567 Note that if C<volgroups> is an empty list then B<all> volume groups
2568 are activated or deactivated.");
2570 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2571 [InitNone, Always, TestOutput (
2572 [["part_disk"; "/dev/sda"; "mbr"];
2573 ["pvcreate"; "/dev/sda1"];
2574 ["vgcreate"; "VG"; "/dev/sda1"];
2575 ["lvcreate"; "LV"; "VG"; "10"];
2576 ["mkfs"; "ext2"; "/dev/VG/LV"];
2577 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2578 ["write_file"; "/new"; "test content"; "0"];
2580 ["lvresize"; "/dev/VG/LV"; "20"];
2581 ["e2fsck_f"; "/dev/VG/LV"];
2582 ["resize2fs"; "/dev/VG/LV"];
2583 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2584 ["cat"; "/new"]], "test content")],
2585 "resize an LVM logical volume",
2587 This resizes (expands or shrinks) an existing LVM logical
2588 volume to C<mbytes>. When reducing, data in the reduced part
2591 ("resize2fs", (RErr, [Device "device"]), 106, [],
2592 [], (* lvresize tests this *)
2593 "resize an ext2/ext3 filesystem",
2595 This resizes an ext2 or ext3 filesystem to match the size of
2596 the underlying device.
2598 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2599 on the C<device> before calling this command. For unknown reasons
2600 C<resize2fs> sometimes gives an error about this and sometimes not.
2601 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2602 calling this function.");
2604 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2605 [InitBasicFS, Always, TestOutputList (
2606 [["find"; "/"]], ["lost+found"]);
2607 InitBasicFS, Always, TestOutputList (
2611 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2612 InitBasicFS, Always, TestOutputList (
2613 [["mkdir_p"; "/a/b/c"];
2614 ["touch"; "/a/b/c/d"];
2615 ["find"; "/a/b/"]], ["c"; "c/d"])],
2616 "find all files and directories",
2618 This command lists out all files and directories, recursively,
2619 starting at C<directory>. It is essentially equivalent to
2620 running the shell command C<find directory -print> but some
2621 post-processing happens on the output, described below.
2623 This returns a list of strings I<without any prefix>. Thus
2624 if the directory structure was:
2630 then the returned list from C<guestfs_find> C</tmp> would be
2638 If C<directory> is not a directory, then this command returns
2641 The returned list is sorted.
2643 See also C<guestfs_find0>.");
2645 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2646 [], (* lvresize tests this *)
2647 "check an ext2/ext3 filesystem",
2649 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2650 filesystem checker on C<device>, noninteractively (C<-p>),
2651 even if the filesystem appears to be clean (C<-f>).
2653 This command is only needed because of C<guestfs_resize2fs>
2654 (q.v.). Normally you should use C<guestfs_fsck>.");
2656 ("sleep", (RErr, [Int "secs"]), 109, [],
2657 [InitNone, Always, TestRun (
2659 "sleep for some seconds",
2661 Sleep for C<secs> seconds.");
2663 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2664 [InitNone, Always, TestOutputInt (
2665 [["part_disk"; "/dev/sda"; "mbr"];
2666 ["mkfs"; "ntfs"; "/dev/sda1"];
2667 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2668 InitNone, Always, TestOutputInt (
2669 [["part_disk"; "/dev/sda"; "mbr"];
2670 ["mkfs"; "ext2"; "/dev/sda1"];
2671 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2672 "probe NTFS volume",
2674 This command runs the L<ntfs-3g.probe(8)> command which probes
2675 an NTFS C<device> for mountability. (Not all NTFS volumes can
2676 be mounted read-write, and some cannot be mounted at all).
2678 C<rw> is a boolean flag. Set it to true if you want to test
2679 if the volume can be mounted read-write. Set it to false if
2680 you want to test if the volume can be mounted read-only.
2682 The return value is an integer which C<0> if the operation
2683 would succeed, or some non-zero value documented in the
2684 L<ntfs-3g.probe(8)> manual page.");
2686 ("sh", (RString "output", [String "command"]), 111, [],
2687 [], (* XXX needs tests *)
2688 "run a command via the shell",
2690 This call runs a command from the guest filesystem via the
2693 This is like C<guestfs_command>, but passes the command to:
2695 /bin/sh -c \"command\"
2697 Depending on the guest's shell, this usually results in
2698 wildcards being expanded, shell expressions being interpolated
2701 All the provisos about C<guestfs_command> apply to this call.");
2703 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2704 [], (* XXX needs tests *)
2705 "run a command via the shell returning lines",
2707 This is the same as C<guestfs_sh>, but splits the result
2708 into a list of lines.
2710 See also: C<guestfs_command_lines>");
2712 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2713 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2714 * code in stubs.c, since all valid glob patterns must start with "/".
2715 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2717 [InitBasicFS, Always, TestOutputList (
2718 [["mkdir_p"; "/a/b/c"];
2719 ["touch"; "/a/b/c/d"];
2720 ["touch"; "/a/b/c/e"];
2721 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2722 InitBasicFS, Always, TestOutputList (
2723 [["mkdir_p"; "/a/b/c"];
2724 ["touch"; "/a/b/c/d"];
2725 ["touch"; "/a/b/c/e"];
2726 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2727 InitBasicFS, Always, TestOutputList (
2728 [["mkdir_p"; "/a/b/c"];
2729 ["touch"; "/a/b/c/d"];
2730 ["touch"; "/a/b/c/e"];
2731 ["glob_expand"; "/a/*/x/*"]], [])],
2732 "expand a wildcard path",
2734 This command searches for all the pathnames matching
2735 C<pattern> according to the wildcard expansion rules
2738 If no paths match, then this returns an empty list
2739 (note: not an error).
2741 It is just a wrapper around the C L<glob(3)> function
2742 with flags C<GLOB_MARK|GLOB_BRACE>.
2743 See that manual page for more details.");
2745 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2746 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2747 [["scrub_device"; "/dev/sdc"]])],
2748 "scrub (securely wipe) a device",
2750 This command writes patterns over C<device> to make data retrieval
2753 It is an interface to the L<scrub(1)> program. See that
2754 manual page for more details.");
2756 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2757 [InitBasicFS, Always, TestRun (
2758 [["write_file"; "/file"; "content"; "0"];
2759 ["scrub_file"; "/file"]])],
2760 "scrub (securely wipe) a file",
2762 This command writes patterns over a file to make data retrieval
2765 The file is I<removed> after scrubbing.
2767 It is an interface to the L<scrub(1)> program. See that
2768 manual page for more details.");
2770 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2771 [], (* XXX needs testing *)
2772 "scrub (securely wipe) free space",
2774 This command creates the directory C<dir> and then fills it
2775 with files until the filesystem is full, and scrubs the files
2776 as for C<guestfs_scrub_file>, and deletes them.
2777 The intention is to scrub any free space on the partition
2780 It is an interface to the L<scrub(1)> program. See that
2781 manual page for more details.");
2783 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2784 [InitBasicFS, Always, TestRun (
2786 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2787 "create a temporary directory",
2789 This command creates a temporary directory. The
2790 C<template> parameter should be a full pathname for the
2791 temporary directory name with the final six characters being
2794 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2795 the second one being suitable for Windows filesystems.
2797 The name of the temporary directory that was created
2800 The temporary directory is created with mode 0700
2801 and is owned by root.
2803 The caller is responsible for deleting the temporary
2804 directory and its contents after use.
2806 See also: L<mkdtemp(3)>");
2808 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2809 [InitISOFS, Always, TestOutputInt (
2810 [["wc_l"; "/10klines"]], 10000)],
2811 "count lines in a file",
2813 This command counts the lines in a file, using the
2814 C<wc -l> external command.");
2816 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2817 [InitISOFS, Always, TestOutputInt (
2818 [["wc_w"; "/10klines"]], 10000)],
2819 "count words in a file",
2821 This command counts the words in a file, using the
2822 C<wc -w> external command.");
2824 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2825 [InitISOFS, Always, TestOutputInt (
2826 [["wc_c"; "/100kallspaces"]], 102400)],
2827 "count characters in a file",
2829 This command counts the characters in a file, using the
2830 C<wc -c> external command.");
2832 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2833 [InitISOFS, Always, TestOutputList (
2834 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2835 "return first 10 lines of a file",
2837 This command returns up to the first 10 lines of a file as
2838 a list of strings.");
2840 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2841 [InitISOFS, Always, TestOutputList (
2842 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843 InitISOFS, Always, TestOutputList (
2844 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2845 InitISOFS, Always, TestOutputList (
2846 [["head_n"; "0"; "/10klines"]], [])],
2847 "return first N lines of a file",
2849 If the parameter C<nrlines> is a positive number, this returns the first
2850 C<nrlines> lines of the file C<path>.
2852 If the parameter C<nrlines> is a negative number, this returns lines
2853 from the file C<path>, excluding the last C<nrlines> lines.
2855 If the parameter C<nrlines> is zero, this returns an empty list.");
2857 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2858 [InitISOFS, Always, TestOutputList (
2859 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2860 "return last 10 lines of a file",
2862 This command returns up to the last 10 lines of a file as
2863 a list of strings.");
2865 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2866 [InitISOFS, Always, TestOutputList (
2867 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868 InitISOFS, Always, TestOutputList (
2869 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2870 InitISOFS, Always, TestOutputList (
2871 [["tail_n"; "0"; "/10klines"]], [])],
2872 "return last N lines of a file",
2874 If the parameter C<nrlines> is a positive number, this returns the last
2875 C<nrlines> lines of the file C<path>.
2877 If the parameter C<nrlines> is a negative number, this returns lines
2878 from the file C<path>, starting with the C<-nrlines>th line.
2880 If the parameter C<nrlines> is zero, this returns an empty list.");
2882 ("df", (RString "output", []), 125, [],
2883 [], (* XXX Tricky to test because it depends on the exact format
2884 * of the 'df' command and other imponderables.
2886 "report file system disk space usage",
2888 This command runs the C<df> command to report disk space used.
2890 This command is mostly useful for interactive sessions. It
2891 is I<not> intended that you try to parse the output string.
2892 Use C<statvfs> from programs.");
2894 ("df_h", (RString "output", []), 126, [],
2895 [], (* XXX Tricky to test because it depends on the exact format
2896 * of the 'df' command and other imponderables.
2898 "report file system disk space usage (human readable)",
2900 This command runs the C<df -h> command to report disk space used
2901 in human-readable format.
2903 This command is mostly useful for interactive sessions. It
2904 is I<not> intended that you try to parse the output string.
2905 Use C<statvfs> from programs.");
2907 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2908 [InitISOFS, Always, TestOutputInt (
2909 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2910 "estimate file space usage",
2912 This command runs the C<du -s> command to estimate file space
2915 C<path> can be a file or a directory. If C<path> is a directory
2916 then the estimate includes the contents of the directory and all
2917 subdirectories (recursively).
2919 The result is the estimated size in I<kilobytes>
2920 (ie. units of 1024 bytes).");
2922 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2923 [InitISOFS, Always, TestOutputList (
2924 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2925 "list files in an initrd",
2927 This command lists out files contained in an initrd.
2929 The files are listed without any initial C</> character. The
2930 files are listed in the order they appear (not necessarily
2931 alphabetical). Directory names are listed as separate items.
2933 Old Linux kernels (2.4 and earlier) used a compressed ext2
2934 filesystem as initrd. We I<only> support the newer initramfs
2935 format (compressed cpio files).");
2937 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2939 "mount a file using the loop device",
2941 This command lets you mount C<file> (a filesystem image
2942 in a file) on a mount point. It is entirely equivalent to
2943 the command C<mount -o loop file mountpoint>.");
2945 ("mkswap", (RErr, [Device "device"]), 130, [],
2946 [InitEmpty, Always, TestRun (
2947 [["part_disk"; "/dev/sda"; "mbr"];
2948 ["mkswap"; "/dev/sda1"]])],
2949 "create a swap partition",
2951 Create a swap partition on C<device>.");
2953 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2954 [InitEmpty, Always, TestRun (
2955 [["part_disk"; "/dev/sda"; "mbr"];
2956 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2957 "create a swap partition with a label",
2959 Create a swap partition on C<device> with label C<label>.
2961 Note that you cannot attach a swap label to a block device
2962 (eg. C</dev/sda>), just to a partition. This appears to be
2963 a limitation of the kernel or swap tools.");
2965 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2966 (let uuid = uuidgen () in
2967 [InitEmpty, Always, TestRun (
2968 [["part_disk"; "/dev/sda"; "mbr"];
2969 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2970 "create a swap partition with an explicit UUID",
2972 Create a swap partition on C<device> with UUID C<uuid>.");
2974 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2975 [InitBasicFS, Always, TestOutputStruct (
2976 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2977 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2978 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2979 InitBasicFS, Always, TestOutputStruct (
2980 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2981 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2982 "make block, character or FIFO devices",
2984 This call creates block or character special devices, or
2985 named pipes (FIFOs).
2987 The C<mode> parameter should be the mode, using the standard
2988 constants. C<devmajor> and C<devminor> are the
2989 device major and minor numbers, only used when creating block
2990 and character special devices.
2992 The mode actually set is affected by the umask.");
2994 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2995 [InitBasicFS, Always, TestOutputStruct (
2996 [["mkfifo"; "0o777"; "/node"];
2997 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2998 "make FIFO (named pipe)",
3000 This call creates a FIFO (named pipe) called C<path> with
3001 mode C<mode>. It is just a convenient wrapper around
3004 The mode actually set is affected by the umask.");
3006 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3007 [InitBasicFS, Always, TestOutputStruct (
3008 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3009 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3010 "make block device node",
3012 This call creates a block device node called C<path> with
3013 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3014 It is just a convenient wrapper around C<guestfs_mknod>.
3016 The mode actually set is affected by the umask.");
3018 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3019 [InitBasicFS, Always, TestOutputStruct (
3020 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3021 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3022 "make char device node",
3024 This call creates a char device node called C<path> with
3025 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3026 It is just a convenient wrapper around C<guestfs_mknod>.
3028 The mode actually set is affected by the umask.");
3030 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3031 [InitEmpty, Always, TestOutputInt (
3032 [["umask"; "0o22"]], 0o22)],
3033 "set file mode creation mask (umask)",
3035 This function sets the mask used for creating new files and
3036 device nodes to C<mask & 0777>.
3038 Typical umask values would be C<022> which creates new files
3039 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3040 C<002> which creates new files with permissions like
3041 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3043 The default umask is C<022>. This is important because it
3044 means that directories and device nodes will be created with
3045 C<0644> or C<0755> mode even if you specify C<0777>.
3047 See also C<guestfs_get_umask>,
3048 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3050 This call returns the previous umask.");
3052 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3054 "read directories entries",
3056 This returns the list of directory entries in directory C<dir>.
3058 All entries in the directory are returned, including C<.> and
3059 C<..>. The entries are I<not> sorted, but returned in the same
3060 order as the underlying filesystem.
3062 Also this call returns basic file type information about each
3063 file. The C<ftyp> field will contain one of the following characters:
3101 The L<readdir(3)> returned a C<d_type> field with an
3106 This function is primarily intended for use by programs. To
3107 get a simple list of names, use C<guestfs_ls>. To get a printable
3108 directory for human consumption, use C<guestfs_ll>.");
3110 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3112 "create partitions on a block device",
3114 This is a simplified interface to the C<guestfs_sfdisk>
3115 command, where partition sizes are specified in megabytes
3116 only (rounded to the nearest cylinder) and you don't need
3117 to specify the cyls, heads and sectors parameters which
3118 were rarely if ever used anyway.
3120 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3121 and C<guestfs_part_disk>");
3123 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3125 "determine file type inside a compressed file",
3127 This command runs C<file> after first decompressing C<path>
3130 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3132 Since 1.0.63, use C<guestfs_file> instead which can now
3133 process compressed files.");
3135 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3137 "list extended attributes of a file or directory",
3139 This call lists the extended attributes of the file or directory
3142 At the system call level, this is a combination of the
3143 L<listxattr(2)> and L<getxattr(2)> calls.
3145 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3147 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3149 "list extended attributes of a file or directory",
3151 This is the same as C<guestfs_getxattrs>, but if C<path>
3152 is a symbolic link, then it returns the extended attributes
3153 of the link itself.");
3155 ("setxattr", (RErr, [String "xattr";
3156 String "val"; Int "vallen"; (* will be BufferIn *)
3157 Pathname "path"]), 143, [Optional "linuxxattrs"],
3159 "set extended attribute of a file or directory",
3161 This call sets the extended attribute named C<xattr>
3162 of the file C<path> to the value C<val> (of length C<vallen>).
3163 The value is arbitrary 8 bit data.
3165 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3167 ("lsetxattr", (RErr, [String "xattr";
3168 String "val"; Int "vallen"; (* will be BufferIn *)
3169 Pathname "path"]), 144, [Optional "linuxxattrs"],
3171 "set extended attribute of a file or directory",
3173 This is the same as C<guestfs_setxattr>, but if C<path>
3174 is a symbolic link, then it sets an extended attribute
3175 of the link itself.");
3177 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3179 "remove extended attribute of a file or directory",
3181 This call removes the extended attribute named C<xattr>
3182 of the file C<path>.
3184 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3186 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3188 "remove extended attribute of a file or directory",
3190 This is the same as C<guestfs_removexattr>, but if C<path>
3191 is a symbolic link, then it removes an extended attribute
3192 of the link itself.");
3194 ("mountpoints", (RHashtable "mps", []), 147, [],
3198 This call is similar to C<guestfs_mounts>. That call returns
3199 a list of devices. This one returns a hash table (map) of
3200 device name to directory where the device is mounted.");
3202 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3203 (* This is a special case: while you would expect a parameter
3204 * of type "Pathname", that doesn't work, because it implies
3205 * NEED_ROOT in the generated calling code in stubs.c, and
3206 * this function cannot use NEED_ROOT.
3209 "create a mountpoint",
3211 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3212 specialized calls that can be used to create extra mountpoints
3213 before mounting the first filesystem.
3215 These calls are I<only> necessary in some very limited circumstances,
3216 mainly the case where you want to mount a mix of unrelated and/or
3217 read-only filesystems together.
3219 For example, live CDs often contain a \"Russian doll\" nest of
3220 filesystems, an ISO outer layer, with a squashfs image inside, with
3221 an ext2/3 image inside that. You can unpack this as follows
3224 add-ro Fedora-11-i686-Live.iso
3227 mkmountpoint /squash
3230 mount-loop /cd/LiveOS/squashfs.img /squash
3231 mount-loop /squash/LiveOS/ext3fs.img /ext3
3233 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3235 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3237 "remove a mountpoint",
3239 This calls removes a mountpoint that was previously created
3240 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3241 for full details.");
3243 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3244 [InitISOFS, Always, TestOutputBuffer (
3245 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3248 This calls returns the contents of the file C<path> as a
3251 Unlike C<guestfs_cat>, this function can correctly
3252 handle files that contain embedded ASCII NUL characters.
3253 However unlike C<guestfs_download>, this function is limited
3254 in the total size of file that can be handled.");
3256 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3257 [InitISOFS, Always, TestOutputList (
3258 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3259 InitISOFS, Always, TestOutputList (
3260 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3261 "return lines matching a pattern",
3263 This calls the external C<grep> program and returns the
3266 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3267 [InitISOFS, Always, TestOutputList (
3268 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3269 "return lines matching a pattern",
3271 This calls the external C<egrep> program and returns the
3274 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3275 [InitISOFS, Always, TestOutputList (
3276 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3277 "return lines matching a pattern",
3279 This calls the external C<fgrep> program and returns the
3282 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3283 [InitISOFS, Always, TestOutputList (
3284 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3285 "return lines matching a pattern",
3287 This calls the external C<grep -i> program and returns the
3290 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3291 [InitISOFS, Always, TestOutputList (
3292 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3293 "return lines matching a pattern",
3295 This calls the external C<egrep -i> program and returns the
3298 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3299 [InitISOFS, Always, TestOutputList (
3300 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3301 "return lines matching a pattern",
3303 This calls the external C<fgrep -i> program and returns the
3306 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3307 [InitISOFS, Always, TestOutputList (
3308 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3309 "return lines matching a pattern",
3311 This calls the external C<zgrep> program and returns the
3314 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3315 [InitISOFS, Always, TestOutputList (
3316 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3317 "return lines matching a pattern",
3319 This calls the external C<zegrep> program and returns the
3322 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3323 [InitISOFS, Always, TestOutputList (
3324 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3325 "return lines matching a pattern",
3327 This calls the external C<zfgrep> program and returns the
3330 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3331 [InitISOFS, Always, TestOutputList (
3332 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3333 "return lines matching a pattern",
3335 This calls the external C<zgrep -i> program and returns the
3338 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3339 [InitISOFS, Always, TestOutputList (
3340 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3341 "return lines matching a pattern",
3343 This calls the external C<zegrep -i> program and returns the
3346 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3347 [InitISOFS, Always, TestOutputList (
3348 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3349 "return lines matching a pattern",
3351 This calls the external C<zfgrep -i> program and returns the
3354 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3355 [InitISOFS, Always, TestOutput (
3356 [["realpath"; "/../directory"]], "/directory")],
3357 "canonicalized absolute pathname",
3359 Return the canonicalized absolute pathname of C<path>. The
3360 returned path has no C<.>, C<..> or symbolic link path elements.");
3362 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3363 [InitBasicFS, Always, TestOutputStruct (
3366 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3367 "create a hard link",
3369 This command creates a hard link using the C<ln> command.");
3371 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3372 [InitBasicFS, Always, TestOutputStruct (
3375 ["ln_f"; "/a"; "/b"];
3376 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3377 "create a hard link",
3379 This command creates a hard link using the C<ln -f> command.
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3382 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3383 [InitBasicFS, Always, TestOutputStruct (
3385 ["ln_s"; "a"; "/b"];
3386 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3387 "create a symbolic link",
3389 This command creates a symbolic link using the C<ln -s> command.");
3391 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3392 [InitBasicFS, Always, TestOutput (
3393 [["mkdir_p"; "/a/b"];
3394 ["touch"; "/a/b/c"];
3395 ["ln_sf"; "../d"; "/a/b/c"];
3396 ["readlink"; "/a/b/c"]], "../d")],
3397 "create a symbolic link",
3399 This command creates a symbolic link using the C<ln -sf> command,
3400 The C<-f> option removes the link (C<linkname>) if it exists already.");
3402 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3403 [] (* XXX tested above *),
3404 "read the target of a symbolic link",
3406 This command reads the target of a symbolic link.");
3408 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3409 [InitBasicFS, Always, TestOutputStruct (
3410 [["fallocate"; "/a"; "1000000"];
3411 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3412 "preallocate a file in the guest filesystem",
3414 This command preallocates a file (containing zero bytes) named
3415 C<path> of size C<len> bytes. If the file exists already, it
3418 Do not confuse this with the guestfish-specific
3419 C<alloc> command which allocates a file in the host and
3420 attaches it as a device.");
3422 ("swapon_device", (RErr, [Device "device"]), 170, [],
3423 [InitPartition, Always, TestRun (
3424 [["mkswap"; "/dev/sda1"];
3425 ["swapon_device"; "/dev/sda1"];
3426 ["swapoff_device"; "/dev/sda1"]])],
3427 "enable swap on device",
3429 This command enables the libguestfs appliance to use the
3430 swap device or partition named C<device>. The increased
3431 memory is made available for all commands, for example
3432 those run using C<guestfs_command> or C<guestfs_sh>.
3434 Note that you should not swap to existing guest swap
3435 partitions unless you know what you are doing. They may
3436 contain hibernation information, or other information that
3437 the guest doesn't want you to trash. You also risk leaking
3438 information about the host to the guest this way. Instead,
3439 attach a new host device to the guest and swap on that.");
3441 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3442 [], (* XXX tested by swapon_device *)
3443 "disable swap on device",
3445 This command disables the libguestfs appliance swap
3446 device or partition named C<device>.
3447 See C<guestfs_swapon_device>.");
3449 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3450 [InitBasicFS, Always, TestRun (
3451 [["fallocate"; "/swap"; "8388608"];
3452 ["mkswap_file"; "/swap"];
3453 ["swapon_file"; "/swap"];
3454 ["swapoff_file"; "/swap"]])],
3455 "enable swap on file",
3457 This command enables swap to a file.
3458 See C<guestfs_swapon_device> for other notes.");
3460 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3461 [], (* XXX tested by swapon_file *)
3462 "disable swap on file",
3464 This command disables the libguestfs appliance swap on file.");
3466 ("swapon_label", (RErr, [String "label"]), 174, [],
3467 [InitEmpty, Always, TestRun (
3468 [["part_disk"; "/dev/sdb"; "mbr"];
3469 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3470 ["swapon_label"; "swapit"];
3471 ["swapoff_label"; "swapit"];
3472 ["zero"; "/dev/sdb"];
3473 ["blockdev_rereadpt"; "/dev/sdb"]])],
3474 "enable swap on labeled swap partition",
3476 This command enables swap to a labeled swap partition.
3477 See C<guestfs_swapon_device> for other notes.");
3479 ("swapoff_label", (RErr, [String "label"]), 175, [],
3480 [], (* XXX tested by swapon_label *)
3481 "disable swap on labeled swap partition",
3483 This command disables the libguestfs appliance swap on
3484 labeled swap partition.");
3486 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3487 (let uuid = uuidgen () in
3488 [InitEmpty, Always, TestRun (
3489 [["mkswap_U"; uuid; "/dev/sdb"];
3490 ["swapon_uuid"; uuid];
3491 ["swapoff_uuid"; uuid]])]),
3492 "enable swap on swap partition by UUID",
3494 This command enables swap to a swap partition with the given UUID.
3495 See C<guestfs_swapon_device> for other notes.");
3497 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3498 [], (* XXX tested by swapon_uuid *)
3499 "disable swap on swap partition by UUID",
3501 This command disables the libguestfs appliance swap partition
3502 with the given UUID.");
3504 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3505 [InitBasicFS, Always, TestRun (
3506 [["fallocate"; "/swap"; "8388608"];
3507 ["mkswap_file"; "/swap"]])],
3508 "create a swap file",
3512 This command just writes a swap file signature to an existing
3513 file. To create the file itself, use something like C<guestfs_fallocate>.");
3515 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3516 [InitISOFS, Always, TestRun (
3517 [["inotify_init"; "0"]])],
3518 "create an inotify handle",
3520 This command creates a new inotify handle.
3521 The inotify subsystem can be used to notify events which happen to
3522 objects in the guest filesystem.
3524 C<maxevents> is the maximum number of events which will be
3525 queued up between calls to C<guestfs_inotify_read> or
3526 C<guestfs_inotify_files>.
3527 If this is passed as C<0>, then the kernel (or previously set)
3528 default is used. For Linux 2.6.29 the default was 16384 events.
3529 Beyond this limit, the kernel throws away events, but records
3530 the fact that it threw them away by setting a flag
3531 C<IN_Q_OVERFLOW> in the returned structure list (see
3532 C<guestfs_inotify_read>).
3534 Before any events are generated, you have to add some
3535 watches to the internal watch list. See:
3536 C<guestfs_inotify_add_watch>,
3537 C<guestfs_inotify_rm_watch> and
3538 C<guestfs_inotify_watch_all>.
3540 Queued up events should be read periodically by calling
3541 C<guestfs_inotify_read>
3542 (or C<guestfs_inotify_files> which is just a helpful
3543 wrapper around C<guestfs_inotify_read>). If you don't
3544 read the events out often enough then you risk the internal
3547 The handle should be closed after use by calling
3548 C<guestfs_inotify_close>. This also removes any
3549 watches automatically.
3551 See also L<inotify(7)> for an overview of the inotify interface
3552 as exposed by the Linux kernel, which is roughly what we expose
3553 via libguestfs. Note that there is one global inotify handle
3554 per libguestfs instance.");
3556 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3557 [InitBasicFS, Always, TestOutputList (
3558 [["inotify_init"; "0"];
3559 ["inotify_add_watch"; "/"; "1073741823"];
3562 ["inotify_files"]], ["a"; "b"])],
3563 "add an inotify watch",
3565 Watch C<path> for the events listed in C<mask>.
3567 Note that if C<path> is a directory then events within that
3568 directory are watched, but this does I<not> happen recursively
3569 (in subdirectories).
3571 Note for non-C or non-Linux callers: the inotify events are
3572 defined by the Linux kernel ABI and are listed in
3573 C</usr/include/sys/inotify.h>.");
3575 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3577 "remove an inotify watch",
3579 Remove a previously defined inotify watch.
3580 See C<guestfs_inotify_add_watch>.");
3582 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3584 "return list of inotify events",
3586 Return the complete queue of events that have happened
3587 since the previous read call.
3589 If no events have happened, this returns an empty list.
3591 I<Note>: In order to make sure that all events have been
3592 read, you must call this function repeatedly until it
3593 returns an empty list. The reason is that the call will
3594 read events up to the maximum appliance-to-host message
3595 size and leave remaining events in the queue.");
3597 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3599 "return list of watched files that had events",
3601 This function is a helpful wrapper around C<guestfs_inotify_read>
3602 which just returns a list of pathnames of objects that were
3603 touched. The returned pathnames are sorted and deduplicated.");
3605 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3607 "close the inotify handle",
3609 This closes the inotify handle which was previously
3610 opened by inotify_init. It removes all watches, throws
3611 away any pending events, and deallocates all resources.");
3613 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3615 "set SELinux security context",
3617 This sets the SELinux security context of the daemon
3618 to the string C<context>.
3620 See the documentation about SELINUX in L<guestfs(3)>.");
3622 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3624 "get SELinux security context",
3626 This gets the SELinux security context of the daemon.
3628 See the documentation about SELINUX in L<guestfs(3)>,
3629 and C<guestfs_setcon>");
3631 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3632 [InitEmpty, Always, TestOutput (
3633 [["part_disk"; "/dev/sda"; "mbr"];
3634 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3635 ["mount_options"; ""; "/dev/sda1"; "/"];
3636 ["write_file"; "/new"; "new file contents"; "0"];
3637 ["cat"; "/new"]], "new file contents")],
3638 "make a filesystem with block size",
3640 This call is similar to C<guestfs_mkfs>, but it allows you to
3641 control the block size of the resulting filesystem. Supported
3642 block sizes depend on the filesystem type, but typically they
3643 are C<1024>, C<2048> or C<4096> only.");
3645 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3646 [InitEmpty, Always, TestOutput (
3647 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3648 ["mke2journal"; "4096"; "/dev/sda1"];
3649 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3650 ["mount_options"; ""; "/dev/sda2"; "/"];
3651 ["write_file"; "/new"; "new file contents"; "0"];
3652 ["cat"; "/new"]], "new file contents")],
3653 "make ext2/3/4 external journal",
3655 This creates an ext2 external journal on C<device>. It is equivalent
3658 mke2fs -O journal_dev -b blocksize device");
3660 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3661 [InitEmpty, Always, TestOutput (
3662 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3663 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3664 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3665 ["mount_options"; ""; "/dev/sda2"; "/"];
3666 ["write_file"; "/new"; "new file contents"; "0"];
3667 ["cat"; "/new"]], "new file contents")],
3668 "make ext2/3/4 external journal with label",
3670 This creates an ext2 external journal on C<device> with label C<label>.");
3672 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3673 (let uuid = uuidgen () in
3674 [InitEmpty, Always, TestOutput (
3675 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3676 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3677 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3678 ["mount_options"; ""; "/dev/sda2"; "/"];
3679 ["write_file"; "/new"; "new file contents"; "0"];
3680 ["cat"; "/new"]], "new file contents")]),
3681 "make ext2/3/4 external journal with UUID",
3683 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3685 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3687 "make ext2/3/4 filesystem with external journal",
3689 This creates an ext2/3/4 filesystem on C<device> with
3690 an external journal on C<journal>. It is equivalent
3693 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3695 See also C<guestfs_mke2journal>.");
3697 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3699 "make ext2/3/4 filesystem with external journal",
3701 This creates an ext2/3/4 filesystem on C<device> with
3702 an external journal on the journal labeled C<label>.
3704 See also C<guestfs_mke2journal_L>.");
3706 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3708 "make ext2/3/4 filesystem with external journal",
3710 This creates an ext2/3/4 filesystem on C<device> with
3711 an external journal on the journal with UUID C<uuid>.
3713 See also C<guestfs_mke2journal_U>.");
3715 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3716 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3717 "load a kernel module",
3719 This loads a kernel module in the appliance.
3721 The kernel module must have been whitelisted when libguestfs
3722 was built (see C<appliance/kmod.whitelist.in> in the source).");
3724 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3725 [InitNone, Always, TestOutput (
3726 [["echo_daemon"; "This is a test"]], "This is a test"
3728 "echo arguments back to the client",
3730 This command concatenate the list of C<words> passed with single spaces between
3731 them and returns the resulting string.
3733 You can use this command to test the connection through to the daemon.
3735 See also C<guestfs_ping_daemon>.");
3737 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3738 [], (* There is a regression test for this. *)
3739 "find all files and directories, returning NUL-separated list",
3741 This command lists out all files and directories, recursively,
3742 starting at C<directory>, placing the resulting list in the
3743 external file called C<files>.
3745 This command works the same way as C<guestfs_find> with the
3746 following exceptions:
3752 The resulting list is written to an external file.
3756 Items (filenames) in the result are separated
3757 by C<\\0> characters. See L<find(1)> option I<-print0>.
3761 This command is not limited in the number of names that it
3766 The result list is not sorted.
3770 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3771 [InitISOFS, Always, TestOutput (
3772 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3773 InitISOFS, Always, TestOutput (
3774 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3775 InitISOFS, Always, TestOutput (
3776 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3777 InitISOFS, Always, TestLastFail (
3778 [["case_sensitive_path"; "/Known-1/"]]);
3779 InitBasicFS, Always, TestOutput (
3781 ["mkdir"; "/a/bbb"];
3782 ["touch"; "/a/bbb/c"];
3783 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3784 InitBasicFS, Always, TestOutput (
3786 ["mkdir"; "/a/bbb"];
3787 ["touch"; "/a/bbb/c"];
3788 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3789 InitBasicFS, Always, TestLastFail (
3791 ["mkdir"; "/a/bbb"];
3792 ["touch"; "/a/bbb/c"];
3793 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3794 "return true path on case-insensitive filesystem",
3796 This can be used to resolve case insensitive paths on
3797 a filesystem which is case sensitive. The use case is
3798 to resolve paths which you have read from Windows configuration
3799 files or the Windows Registry, to the true path.
3801 The command handles a peculiarity of the Linux ntfs-3g
3802 filesystem driver (and probably others), which is that although
3803 the underlying filesystem is case-insensitive, the driver
3804 exports the filesystem to Linux as case-sensitive.
3806 One consequence of this is that special directories such
3807 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3808 (or other things) depending on the precise details of how
3809 they were created. In Windows itself this would not be
3812 Bug or feature? You decide:
3813 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3815 This function resolves the true case of each element in the
3816 path and returns the case-sensitive path.
3818 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3819 might return C<\"/WINDOWS/system32\"> (the exact return value
3820 would depend on details of how the directories were originally
3821 created under Windows).
3824 This function does not handle drive names, backslashes etc.
3826 See also C<guestfs_realpath>.");
3828 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3829 [InitBasicFS, Always, TestOutput (
3830 [["vfs_type"; "/dev/sda1"]], "ext2")],
3831 "get the Linux VFS type corresponding to a mounted device",
3833 This command gets the block device type corresponding to
3834 a mounted device called C<device>.
3836 Usually the result is the name of the Linux VFS module that
3837 is used to mount this device (probably determined automatically
3838 if you used the C<guestfs_mount> call).");
3840 ("truncate", (RErr, [Pathname "path"]), 199, [],
3841 [InitBasicFS, Always, TestOutputStruct (
3842 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3843 ["truncate"; "/test"];
3844 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3845 "truncate a file to zero size",
3847 This command truncates C<path> to a zero-length file. The
3848 file must exist already.");
3850 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3851 [InitBasicFS, Always, TestOutputStruct (
3852 [["touch"; "/test"];
3853 ["truncate_size"; "/test"; "1000"];
3854 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3855 "truncate a file to a particular size",
3857 This command truncates C<path> to size C<size> bytes. The file
3858 must exist already. If the file is smaller than C<size> then
3859 the file is extended to the required size with null bytes.");
3861 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3862 [InitBasicFS, Always, TestOutputStruct (
3863 [["touch"; "/test"];
3864 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3865 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3866 "set timestamp of a file with nanosecond precision",
3868 This command sets the timestamps of a file with nanosecond
3871 C<atsecs, atnsecs> are the last access time (atime) in secs and
3872 nanoseconds from the epoch.
3874 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3875 secs and nanoseconds from the epoch.
3877 If the C<*nsecs> field contains the special value C<-1> then
3878 the corresponding timestamp is set to the current time. (The
3879 C<*secs> field is ignored in this case).
3881 If the C<*nsecs> field contains the special value C<-2> then
3882 the corresponding timestamp is left unchanged. (The
3883 C<*secs> field is ignored in this case).");
3885 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3886 [InitBasicFS, Always, TestOutputStruct (
3887 [["mkdir_mode"; "/test"; "0o111"];
3888 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3889 "create a directory with a particular mode",
3891 This command creates a directory, setting the initial permissions
3892 of the directory to C<mode>.
3894 For common Linux filesystems, the actual mode which is set will
3895 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3896 interpret the mode in other ways.
3898 See also C<guestfs_mkdir>, C<guestfs_umask>");
3900 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3902 "change file owner and group",
3904 Change the file owner to C<owner> and group to C<group>.
3905 This is like C<guestfs_chown> but if C<path> is a symlink then
3906 the link itself is changed, not the target.
3908 Only numeric uid and gid are supported. If you want to use
3909 names, you will need to locate and parse the password file
3910 yourself (Augeas support makes this relatively easy).");
3912 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3914 "lstat on multiple files",
3916 This call allows you to perform the C<guestfs_lstat> operation
3917 on multiple files, where all files are in the directory C<path>.
3918 C<names> is the list of files from this directory.
3920 On return you get a list of stat structs, with a one-to-one
3921 correspondence to the C<names> list. If any name did not exist
3922 or could not be lstat'd, then the C<ino> field of that structure
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lxattrlist> for a similarly efficient call
3928 for getting extended attributes. Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail. The caller must split up such requests
3931 into smaller groups of names.");
3933 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3935 "lgetxattr on multiple files",
3937 This call allows you to get the extended attributes
3938 of multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3941 On return you get a flat list of xattr structs which must be
3942 interpreted sequentially. The first xattr struct always has a zero-length
3943 C<attrname>. C<attrval> in this struct is zero-length
3944 to indicate there was an error doing C<lgetxattr> for this
3945 file, I<or> is a C string which is a decimal number
3946 (the number of following attributes for this file, which could
3947 be C<\"0\">). Then after the first xattr struct are the
3948 zero or more attributes for the first named file.
3949 This repeats for the second and subsequent files.
3951 This call is intended for programs that want to efficiently
3952 list a directory contents without making many round-trips.
3953 See also C<guestfs_lstatlist> for a similarly efficient call
3954 for getting standard stats. Very long directory listings
3955 might cause the protocol message size to be exceeded, causing
3956 this call to fail. The caller must split up such requests
3957 into smaller groups of names.");
3959 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3961 "readlink on multiple files",
3963 This call allows you to do a C<readlink> operation
3964 on multiple files, where all files are in the directory C<path>.
3965 C<names> is the list of files from this directory.
3967 On return you get a list of strings, with a one-to-one
3968 correspondence to the C<names> list. Each string is the
3969 value of the symbol link.
3971 If the C<readlink(2)> operation fails on any name, then
3972 the corresponding result string is the empty string C<\"\">.
3973 However the whole operation is completed even if there
3974 were C<readlink(2)> errors, and so you can call this
3975 function with names where you don't know if they are
3976 symbolic links already (albeit slightly less efficient).
3978 This call is intended for programs that want to efficiently
3979 list a directory contents without making many round-trips.
3980 Very long directory listings might cause the protocol
3981 message size to be exceeded, causing
3982 this call to fail. The caller must split up such requests
3983 into smaller groups of names.");
3985 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3986 [InitISOFS, Always, TestOutputBuffer (
3987 [["pread"; "/known-4"; "1"; "3"]], "\n");
3988 InitISOFS, Always, TestOutputBuffer (
3989 [["pread"; "/empty"; "0"; "100"]], "")],
3990 "read part of a file",
3992 This command lets you read part of a file. It reads C<count>
3993 bytes of the file, starting at C<offset>, from file C<path>.
3995 This may read fewer bytes than requested. For further details
3996 see the L<pread(2)> system call.");
3998 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3999 [InitEmpty, Always, TestRun (
4000 [["part_init"; "/dev/sda"; "gpt"]])],
4001 "create an empty partition table",
4003 This creates an empty partition table on C<device> of one of the
4004 partition types listed below. Usually C<parttype> should be
4005 either C<msdos> or C<gpt> (for large disks).
4007 Initially there are no partitions. Following this, you should
4008 call C<guestfs_part_add> for each partition required.
4010 Possible values for C<parttype> are:
4014 =item B<efi> | B<gpt>
4016 Intel EFI / GPT partition table.
4018 This is recommended for >= 2 TB partitions that will be accessed
4019 from Linux and Intel-based Mac OS X. It also has limited backwards
4020 compatibility with the C<mbr> format.
4022 =item B<mbr> | B<msdos>
4024 The standard PC \"Master Boot Record\" (MBR) format used
4025 by MS-DOS and Windows. This partition type will B<only> work
4026 for device sizes up to 2 TB. For large disks we recommend
4031 Other partition table types that may work but are not
4040 =item B<amiga> | B<rdb>
4042 Amiga \"Rigid Disk Block\" format.
4050 DASD, used on IBM mainframes.
4058 Old Mac partition format. Modern Macs use C<gpt>.
4062 NEC PC-98 format, common in Japan apparently.
4070 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4071 [InitEmpty, Always, TestRun (
4072 [["part_init"; "/dev/sda"; "mbr"];
4073 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4074 InitEmpty, Always, TestRun (
4075 [["part_init"; "/dev/sda"; "gpt"];
4076 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4077 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4078 InitEmpty, Always, TestRun (
4079 [["part_init"; "/dev/sda"; "mbr"];
4080 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4081 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4082 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4083 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4084 "add a partition to the device",
4086 This command adds a partition to C<device>. If there is no partition
4087 table on the device, call C<guestfs_part_init> first.
4089 The C<prlogex> parameter is the type of partition. Normally you
4090 should pass C<p> or C<primary> here, but MBR partition tables also
4091 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4094 C<startsect> and C<endsect> are the start and end of the partition
4095 in I<sectors>. C<endsect> may be negative, which means it counts
4096 backwards from the end of the disk (C<-1> is the last sector).
4098 Creating a partition which covers the whole disk is not so easy.
4099 Use C<guestfs_part_disk> to do that.");
4101 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4102 [InitEmpty, Always, TestRun (
4103 [["part_disk"; "/dev/sda"; "mbr"]]);
4104 InitEmpty, Always, TestRun (
4105 [["part_disk"; "/dev/sda"; "gpt"]])],
4106 "partition whole disk with a single primary partition",
4108 This command is simply a combination of C<guestfs_part_init>
4109 followed by C<guestfs_part_add> to create a single primary partition
4110 covering the whole disk.
4112 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4113 but other possible values are described in C<guestfs_part_init>.");
4115 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4116 [InitEmpty, Always, TestRun (
4117 [["part_disk"; "/dev/sda"; "mbr"];
4118 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4119 "make a partition bootable",
4121 This sets the bootable flag on partition numbered C<partnum> on
4122 device C<device>. Note that partitions are numbered from 1.
4124 The bootable flag is used by some operating systems (notably
4125 Windows) to determine which partition to boot from. It is by
4126 no means universally recognized.");
4128 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4129 [InitEmpty, Always, TestRun (
4130 [["part_disk"; "/dev/sda"; "gpt"];
4131 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4132 "set partition name",
4134 This sets the partition name on partition numbered C<partnum> on
4135 device C<device>. Note that partitions are numbered from 1.
4137 The partition name can only be set on certain types of partition
4138 table. This works on C<gpt> but not on C<mbr> partitions.");
4140 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4141 [], (* XXX Add a regression test for this. *)
4142 "list partitions on a device",
4144 This command parses the partition table on C<device> and
4145 returns the list of partitions found.
4147 The fields in the returned structure are:
4153 Partition number, counting from 1.
4157 Start of the partition I<in bytes>. To get sectors you have to
4158 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4162 End of the partition in bytes.
4166 Size of the partition in bytes.
4170 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4171 [InitEmpty, Always, TestOutput (
4172 [["part_disk"; "/dev/sda"; "gpt"];
4173 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4174 "get the partition table type",
4176 This command examines the partition table on C<device> and
4177 returns the partition table type (format) being used.
4179 Common return values include: C<msdos> (a DOS/Windows style MBR
4180 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4181 values are possible, although unusual. See C<guestfs_part_init>
4184 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4185 [InitBasicFS, Always, TestOutputBuffer (
4186 [["fill"; "0x63"; "10"; "/test"];
4187 ["read_file"; "/test"]], "cccccccccc")],
4188 "fill a file with octets",
4190 This command creates a new file called C<path>. The initial
4191 content of the file is C<len> octets of C<c>, where C<c>
4192 must be a number in the range C<[0..255]>.
4194 To fill a file with zero bytes (sparsely), it is
4195 much more efficient to use C<guestfs_truncate_size>.");
4197 ("available", (RErr, [StringList "groups"]), 216, [],
4198 [InitNone, Always, TestRun [["available"; ""]]],
4199 "test availability of some parts of the API",
4201 This command is used to check the availability of some
4202 groups of functionality in the appliance, which not all builds of
4203 the libguestfs appliance will be able to provide.
4205 The libguestfs groups, and the functions that those
4206 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4208 The argument C<groups> is a list of group names, eg:
4209 C<[\"inotify\", \"augeas\"]> would check for the availability of
4210 the Linux inotify functions and Augeas (configuration file
4213 The command returns no error if I<all> requested groups are available.
4215 It fails with an error if one or more of the requested
4216 groups is unavailable in the appliance.
4218 If an unknown group name is included in the
4219 list of groups then an error is always returned.
4227 You must call C<guestfs_launch> before calling this function.
4229 The reason is because we don't know what groups are
4230 supported by the appliance/daemon until it is running and can
4235 If a group of functions is available, this does not necessarily
4236 mean that they will work. You still have to check for errors
4237 when calling individual API functions even if they are
4242 It is usually the job of distro packagers to build
4243 complete functionality into the libguestfs appliance.
4244 Upstream libguestfs, if built from source with all
4245 requirements satisfied, will support everything.
4249 This call was added in version C<1.0.80>. In previous
4250 versions of libguestfs all you could do would be to speculatively
4251 execute a command to find out if the daemon implemented it.
4252 See also C<guestfs_version>.
4256 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4257 [InitBasicFS, Always, TestOutputBuffer (
4258 [["write_file"; "/src"; "hello, world"; "0"];
4259 ["dd"; "/src"; "/dest"];
4260 ["read_file"; "/dest"]], "hello, world")],
4261 "copy from source to destination using dd",
4263 This command copies from one source device or file C<src>
4264 to another destination device or file C<dest>. Normally you
4265 would use this to copy to or from a device or partition, for
4266 example to duplicate a filesystem.
4268 If the destination is a device, it must be as large or larger
4269 than the source file or device, otherwise the copy will fail.
4270 This command cannot do partial copies (see C<guestfs_copy_size>).");
4272 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4273 [InitBasicFS, Always, TestOutputInt (
4274 [["write_file"; "/file"; "hello, world"; "0"];
4275 ["filesize"; "/file"]], 12)],
4276 "return the size of the file in bytes",
4278 This command returns the size of C<file> in bytes.
4280 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4281 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4282 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4284 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4285 [InitBasicFSonLVM, Always, TestOutputList (
4286 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4287 ["lvs"]], ["/dev/VG/LV2"])],
4288 "rename an LVM logical volume",
4290 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4292 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4293 [InitBasicFSonLVM, Always, TestOutputList (
4295 ["vg_activate"; "false"; "VG"];
4296 ["vgrename"; "VG"; "VG2"];
4297 ["vg_activate"; "true"; "VG2"];
4298 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4299 ["vgs"]], ["VG2"])],
4300 "rename an LVM volume group",
4302 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4304 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4305 [InitISOFS, Always, TestOutputBuffer (
4306 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4307 "list the contents of a single file in an initrd",
4309 This command unpacks the file C<filename> from the initrd file
4310 called C<initrdpath>. The filename must be given I<without> the
4311 initial C</> character.
4313 For example, in guestfish you could use the following command
4314 to examine the boot script (usually called C</init>)
4315 contained in a Linux initrd or initramfs image:
4317 initrd-cat /boot/initrd-<version>.img init
4319 See also C<guestfs_initrd_list>.");
4321 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4323 "get the UUID of a physical volume",
4325 This command returns the UUID of the LVM PV C<device>.");
4327 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4329 "get the UUID of a volume group",
4331 This command returns the UUID of the LVM VG named C<vgname>.");
4333 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4335 "get the UUID of a logical volume",
4337 This command returns the UUID of the LVM LV C<device>.");
4339 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4341 "get the PV UUIDs containing the volume group",
4343 Given a VG called C<vgname>, this returns the UUIDs of all
4344 the physical volumes that this volume group resides on.
4346 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4347 calls to associate physical volumes and volume groups.
4349 See also C<guestfs_vglvuuids>.");
4351 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4353 "get the LV UUIDs of all LVs in the volume group",
4355 Given a VG called C<vgname>, this returns the UUIDs of all
4356 the logical volumes created in this volume group.
4358 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4359 calls to associate logical volumes and volume groups.
4361 See also C<guestfs_vgpvuuids>.");
4363 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4364 [InitBasicFS, Always, TestOutputBuffer (
4365 [["write_file"; "/src"; "hello, world"; "0"];
4366 ["copy_size"; "/src"; "/dest"; "5"];
4367 ["read_file"; "/dest"]], "hello")],
4368 "copy size bytes from source to destination using dd",
4370 This command copies exactly C<size> bytes from one source device
4371 or file C<src> to another destination device or file C<dest>.
4373 Note this will fail if the source is too short or if the destination
4374 is not large enough.");
4376 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4377 [InitBasicFSonLVM, Always, TestRun (
4378 [["zero_device"; "/dev/VG/LV"]])],
4379 "write zeroes to an entire device",
4381 This command writes zeroes over the entire C<device>. Compare
4382 with C<guestfs_zero> which just zeroes the first few blocks of
4385 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4386 [InitBasicFS, Always, TestOutput (
4387 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4388 ["cat"; "/hello"]], "hello\n")],
4389 "unpack compressed tarball to directory",
4391 This command uploads and unpacks local file C<tarball> (an
4392 I<xz compressed> tar file) into C<directory>.");
4394 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4396 "pack directory into compressed tarball",
4398 This command packs the contents of C<directory> and downloads
4399 it to local file C<tarball> (as an xz compressed tar archive).");
4401 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4403 "resize an NTFS filesystem",
4405 This command resizes an NTFS filesystem, expanding or
4406 shrinking it to the size of the underlying device.
4407 See also L<ntfsresize(8)>.");
4409 ("vgscan", (RErr, []), 232, [],
4410 [InitEmpty, Always, TestRun (
4412 "rescan for LVM physical volumes, volume groups and logical volumes",
4414 This rescans all block devices and rebuilds the list of LVM
4415 physical volumes, volume groups and logical volumes.");
4417 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4418 [InitEmpty, Always, TestRun (
4419 [["part_init"; "/dev/sda"; "mbr"];
4420 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4421 ["part_del"; "/dev/sda"; "1"]])],
4422 "delete a partition",
4424 This command deletes the partition numbered C<partnum> on C<device>.
4426 Note that in the case of MBR partitioning, deleting an
4427 extended partition also deletes any logical partitions
4430 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4431 [InitEmpty, Always, TestOutputTrue (
4432 [["part_init"; "/dev/sda"; "mbr"];
4433 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4434 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4435 ["part_get_bootable"; "/dev/sda"; "1"]])],
4436 "return true if a partition is bootable",
4438 This command returns true if the partition C<partnum> on
4439 C<device> has the bootable flag set.
4441 See also C<guestfs_part_set_bootable>.");
4443 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4444 [InitEmpty, Always, TestOutputInt (
4445 [["part_init"; "/dev/sda"; "mbr"];
4446 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4447 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4448 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4449 "get the MBR type byte (ID byte) from a partition",
4451 Returns the MBR type byte (also known as the ID byte) from
4452 the numbered partition C<partnum>.
4454 Note that only MBR (old DOS-style) partitions have type bytes.
4455 You will get undefined results for other partition table
4456 types (see C<guestfs_part_get_parttype>).");
4458 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4459 [], (* tested by part_get_mbr_id *)
4460 "set the MBR type byte (ID byte) of a partition",
4462 Sets the MBR type byte (also known as the ID byte) of
4463 the numbered partition C<partnum> to C<idbyte>. Note
4464 that the type bytes quoted in most documentation are
4465 in fact hexadecimal numbers, but usually documented
4466 without any leading \"0x\" which might be confusing.
4468 Note that only MBR (old DOS-style) partitions have type bytes.
4469 You will get undefined results for other partition table
4470 types (see C<guestfs_part_get_parttype>).");
4472 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4473 [InitISOFS, Always, TestOutput (
4474 [["checksum_device"; "md5"; "/dev/sdd"]],
4475 (Digest.to_hex (Digest.file "images/test.iso")))],
4476 "compute MD5, SHAx or CRC checksum of the contents of a device",
4478 This call computes the MD5, SHAx or CRC checksum of the
4479 contents of the device named C<device>. For the types of
4480 checksums supported see the C<guestfs_checksum> command.");
4482 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4483 [InitNone, Always, TestRun (
4484 [["part_disk"; "/dev/sda"; "mbr"];
4485 ["pvcreate"; "/dev/sda1"];
4486 ["vgcreate"; "VG"; "/dev/sda1"];
4487 ["lvcreate"; "LV"; "VG"; "10"];
4488 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4489 "expand an LV to fill free space",
4491 This expands an existing logical volume C<lv> so that it fills
4492 C<pc>% of the remaining free space in the volume group. Commonly
4493 you would call this with pc = 100 which expands the logical volume
4494 as much as possible, using all remaining free space in the volume
4497 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4498 [], (* XXX Augeas code needs tests. *)
4499 "clear Augeas path",
4501 Set the value associated with C<path> to C<NULL>. This
4502 is the same as the L<augtool(1)> C<clear> command.");
4504 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4505 [InitEmpty, Always, TestOutputInt (
4506 [["get_umask"]], 0o22)],
4507 "get the current umask",
4509 Return the current umask. By default the umask is C<022>
4510 unless it has been set by calling C<guestfs_umask>.");
4512 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4514 "upload a file to the appliance (internal use only)",
4516 The C<guestfs_debug_upload> command uploads a file to
4517 the libguestfs appliance.
4519 There is no comprehensive help for this command. You have
4520 to look at the file C<daemon/debug.c> in the libguestfs source
4521 to find out what it is for.");
4523 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4524 [InitBasicFS, Always, TestOutput (
4525 [["base64_in"; "../images/hello.b64"; "/hello"];
4526 ["cat"; "/hello"]], "hello\n")],
4527 "upload base64-encoded data to file",
4529 This command uploads base64-encoded data from C<base64file>
4532 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4534 "download file and encode as base64",
4536 This command downloads the contents of C<filename>, writing
4537 it out to local file C<base64file> encoded as base64.");
4541 let all_functions = non_daemon_functions @ daemon_functions
4543 (* In some places we want the functions to be displayed sorted
4544 * alphabetically, so this is useful:
4546 let all_functions_sorted =
4547 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4548 compare n1 n2) all_functions
4550 (* Field types for structures. *)
4552 | FChar (* C 'char' (really, a 7 bit byte). *)
4553 | FString (* nul-terminated ASCII string, NOT NULL. *)
4554 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4559 | FBytes (* Any int measure that counts bytes. *)
4560 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4561 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4563 (* Because we generate extra parsing code for LVM command line tools,
4564 * we have to pull out the LVM columns separately here.
4574 "pv_attr", FString (* XXX *);
4575 "pv_pe_count", FInt64;
4576 "pv_pe_alloc_count", FInt64;
4579 "pv_mda_count", FInt64;
4580 "pv_mda_free", FBytes;
4581 (* Not in Fedora 10:
4582 "pv_mda_size", FBytes;
4589 "vg_attr", FString (* XXX *);
4592 "vg_sysid", FString;
4593 "vg_extent_size", FBytes;
4594 "vg_extent_count", FInt64;
4595 "vg_free_count", FInt64;
4600 "snap_count", FInt64;
4603 "vg_mda_count", FInt64;
4604 "vg_mda_free", FBytes;
4605 (* Not in Fedora 10:
4606 "vg_mda_size", FBytes;
4612 "lv_attr", FString (* XXX *);
4615 "lv_kernel_major", FInt64;
4616 "lv_kernel_minor", FInt64;
4618 "seg_count", FInt64;
4620 "snap_percent", FOptPercent;
4621 "copy_percent", FOptPercent;
4624 "mirror_log", FString;
4628 (* Names and fields in all structures (in RStruct and RStructList)
4632 (* The old RIntBool return type, only ever used for aug_defnode. Do
4633 * not use this struct in any new code.
4636 "i", FInt32; (* for historical compatibility *)
4637 "b", FInt32; (* for historical compatibility *)
4640 (* LVM PVs, VGs, LVs. *)
4641 "lvm_pv", lvm_pv_cols;
4642 "lvm_vg", lvm_vg_cols;
4643 "lvm_lv", lvm_lv_cols;
4645 (* Column names and types from stat structures.
4646 * NB. Can't use things like 'st_atime' because glibc header files
4647 * define some of these as macros. Ugh.
4678 (* Column names in dirent structure. *)
4681 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4686 (* Version numbers. *)
4694 (* Extended attribute. *)
4696 "attrname", FString;
4700 (* Inotify events. *)
4704 "in_cookie", FUInt32;
4708 (* Partition table entry. *)
4711 "part_start", FBytes;
4713 "part_size", FBytes;
4715 ] (* end of structs *)
4717 (* Ugh, Java has to be different ..
4718 * These names are also used by the Haskell bindings.
4720 let java_structs = [
4721 "int_bool", "IntBool";
4726 "statvfs", "StatVFS";
4728 "version", "Version";
4730 "inotify_event", "INotifyEvent";
4731 "partition", "Partition";
4734 (* What structs are actually returned. *)
4735 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4737 (* Returns a list of RStruct/RStructList structs that are returned
4738 * by any function. Each element of returned list is a pair:
4740 * (structname, RStructOnly)
4741 * == there exists function which returns RStruct (_, structname)
4742 * (structname, RStructListOnly)
4743 * == there exists function which returns RStructList (_, structname)
4744 * (structname, RStructAndList)
4745 * == there are functions returning both RStruct (_, structname)
4746 * and RStructList (_, structname)
4748 let rstructs_used_by functions =
4749 (* ||| is a "logical OR" for rstructs_used_t *)
4753 | _, RStructAndList -> RStructAndList
4754 | RStructOnly, RStructListOnly
4755 | RStructListOnly, RStructOnly -> RStructAndList
4756 | RStructOnly, RStructOnly -> RStructOnly
4757 | RStructListOnly, RStructListOnly -> RStructListOnly
4760 let h = Hashtbl.create 13 in
4762 (* if elem->oldv exists, update entry using ||| operator,
4763 * else just add elem->newv to the hash
4765 let update elem newv =
4766 try let oldv = Hashtbl.find h elem in
4767 Hashtbl.replace h elem (newv ||| oldv)
4768 with Not_found -> Hashtbl.add h elem newv
4772 fun (_, style, _, _, _, _, _) ->
4773 match fst style with
4774 | RStruct (_, structname) -> update structname RStructOnly
4775 | RStructList (_, structname) -> update structname RStructListOnly
4779 (* return key->values as a list of (key,value) *)
4780 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4782 (* Used for testing language bindings. *)
4784 | CallString of string
4785 | CallOptString of string option
4786 | CallStringList of string list
4788 | CallInt64 of int64
4791 (* Used to memoize the result of pod2text. *)
4792 let pod2text_memo_filename = "src/.pod2text.data"
4793 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4795 let chan = open_in pod2text_memo_filename in
4796 let v = input_value chan in
4800 _ -> Hashtbl.create 13
4801 let pod2text_memo_updated () =
4802 let chan = open_out pod2text_memo_filename in
4803 output_value chan pod2text_memo;
4806 (* Useful functions.
4807 * Note we don't want to use any external OCaml libraries which
4808 * makes this a bit harder than it should be.
4810 module StringMap = Map.Make (String)
4812 let failwithf fs = ksprintf failwith fs
4814 let unique = let i = ref 0 in fun () -> incr i; !i
4816 let replace_char s c1 c2 =
4817 let s2 = String.copy s in
4818 let r = ref false in
4819 for i = 0 to String.length s2 - 1 do
4820 if String.unsafe_get s2 i = c1 then (
4821 String.unsafe_set s2 i c2;
4825 if not !r then s else s2
4829 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4831 let triml ?(test = isspace) str =
4833 let n = ref (String.length str) in
4834 while !n > 0 && test str.[!i]; do
4839 else String.sub str !i !n
4841 let trimr ?(test = isspace) str =
4842 let n = ref (String.length str) in
4843 while !n > 0 && test str.[!n-1]; do
4846 if !n = String.length str then str
4847 else String.sub str 0 !n
4849 let trim ?(test = isspace) str =
4850 trimr ~test (triml ~test str)
4852 let rec find s sub =
4853 let len = String.length s in
4854 let sublen = String.length sub in
4856 if i <= len-sublen then (
4858 if j < sublen then (
4859 if s.[i+j] = sub.[j] then loop2 (j+1)
4865 if r = -1 then loop (i+1) else r
4871 let rec replace_str s s1 s2 =
4872 let len = String.length s in
4873 let sublen = String.length s1 in
4874 let i = find s s1 in
4877 let s' = String.sub s 0 i in
4878 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4879 s' ^ s2 ^ replace_str s'' s1 s2
4882 let rec string_split sep str =
4883 let len = String.length str in
4884 let seplen = String.length sep in
4885 let i = find str sep in
4886 if i = -1 then [str]
4888 let s' = String.sub str 0 i in
4889 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4890 s' :: string_split sep s''
4893 let files_equal n1 n2 =
4894 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4895 match Sys.command cmd with
4898 | i -> failwithf "%s: failed with error code %d" cmd i
4900 let rec filter_map f = function
4904 | Some y -> y :: filter_map f xs
4905 | None -> filter_map f xs
4907 let rec find_map f = function
4908 | [] -> raise Not_found
4912 | None -> find_map f xs
4915 let rec loop i = function
4917 | x :: xs -> f i x; loop (i+1) xs
4922 let rec loop i = function
4924 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4928 let count_chars c str =
4929 let count = ref 0 in
4930 for i = 0 to String.length str - 1 do
4931 if c = String.unsafe_get str i then incr count
4935 let name_of_argt = function
4936 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4937 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4938 | FileIn n | FileOut n -> n
4940 let java_name_of_struct typ =
4941 try List.assoc typ java_structs
4944 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4946 let cols_of_struct typ =
4947 try List.assoc typ structs
4949 failwithf "cols_of_struct: unknown struct %s" typ
4951 let seq_of_test = function
4952 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4953 | TestOutputListOfDevices (s, _)
4954 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4955 | TestOutputTrue s | TestOutputFalse s
4956 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4957 | TestOutputStruct (s, _)
4958 | TestLastFail s -> s
4960 (* Handling for function flags. *)
4961 let protocol_limit_warning =
4962 "Because of the message protocol, there is a transfer limit
4963 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4965 let danger_will_robinson =
4966 "B<This command is dangerous. Without careful use you
4967 can easily destroy all your data>."
4969 let deprecation_notice flags =
4972 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4974 sprintf "This function is deprecated.
4975 In new code, use the C<%s> call instead.
4977 Deprecated functions will not be removed from the API, but the
4978 fact that they are deprecated indicates that there are problems
4979 with correct use of these functions." alt in
4984 (* Create list of optional groups. *)
4986 let h = Hashtbl.create 13 in
4988 fun (name, _, _, flags, _, _, _) ->
4992 let names = try Hashtbl.find h group with Not_found -> [] in
4993 Hashtbl.replace h group (name :: names)
4997 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5000 fun group -> group, List.sort compare (Hashtbl.find h group)
5002 List.sort (fun x y -> compare (fst x) (fst y)) groups
5004 (* Check function names etc. for consistency. *)
5005 let check_functions () =
5006 let contains_uppercase str =
5007 let len = String.length str in
5009 if i >= len then false
5012 if c >= 'A' && c <= 'Z' then true
5019 (* Check function names. *)
5021 fun (name, _, _, _, _, _, _) ->
5022 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5023 failwithf "function name %s does not need 'guestfs' prefix" name;
5025 failwithf "function name is empty";
5026 if name.[0] < 'a' || name.[0] > 'z' then
5027 failwithf "function name %s must start with lowercase a-z" name;
5028 if String.contains name '-' then
5029 failwithf "function name %s should not contain '-', use '_' instead."
5033 (* Check function parameter/return names. *)
5035 fun (name, style, _, _, _, _, _) ->
5036 let check_arg_ret_name n =
5037 if contains_uppercase n then
5038 failwithf "%s param/ret %s should not contain uppercase chars"
5040 if String.contains n '-' || String.contains n '_' then
5041 failwithf "%s param/ret %s should not contain '-' or '_'"
5044 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;
5045 if n = "int" || n = "char" || n = "short" || n = "long" then
5046 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5047 if n = "i" || n = "n" then
5048 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5049 if n = "argv" || n = "args" then
5050 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5052 (* List Haskell, OCaml and C keywords here.
5053 * http://www.haskell.org/haskellwiki/Keywords
5054 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5055 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5056 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5057 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5058 * Omitting _-containing words, since they're handled above.
5059 * Omitting the OCaml reserved word, "val", is ok,
5060 * and saves us from renaming several parameters.
5063 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5064 "char"; "class"; "const"; "constraint"; "continue"; "data";
5065 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5066 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5067 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5068 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5069 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5071 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5072 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5073 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5074 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5075 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5076 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5077 "volatile"; "when"; "where"; "while";
5079 if List.mem n reserved then
5080 failwithf "%s has param/ret using reserved word %s" name n;
5083 (match fst style with
5085 | RInt n | RInt64 n | RBool n
5086 | RConstString n | RConstOptString n | RString n
5087 | RStringList n | RStruct (n, _) | RStructList (n, _)
5088 | RHashtable n | RBufferOut n ->
5089 check_arg_ret_name n
5091 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5094 (* Check short descriptions. *)
5096 fun (name, _, _, _, _, shortdesc, _) ->
5097 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5098 failwithf "short description of %s should begin with lowercase." name;
5099 let c = shortdesc.[String.length shortdesc-1] in
5100 if c = '\n' || c = '.' then
5101 failwithf "short description of %s should not end with . or \\n." name
5104 (* Check long descriptions. *)
5106 fun (name, _, _, _, _, _, longdesc) ->
5107 if longdesc.[String.length longdesc-1] = '\n' then
5108 failwithf "long description of %s should not end with \\n." name
5111 (* Check proc_nrs. *)
5113 fun (name, _, proc_nr, _, _, _, _) ->
5114 if proc_nr <= 0 then
5115 failwithf "daemon function %s should have proc_nr > 0" name
5119 fun (name, _, proc_nr, _, _, _, _) ->
5120 if proc_nr <> -1 then
5121 failwithf "non-daemon function %s should have proc_nr -1" name
5122 ) non_daemon_functions;
5125 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5128 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5129 let rec loop = function
5132 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5134 | (name1,nr1) :: (name2,nr2) :: _ ->
5135 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5143 (* Ignore functions that have no tests. We generate a
5144 * warning when the user does 'make check' instead.
5146 | name, _, _, _, [], _, _ -> ()
5147 | name, _, _, _, tests, _, _ ->
5151 match seq_of_test test with
5153 failwithf "%s has a test containing an empty sequence" name
5154 | cmds -> List.map List.hd cmds
5156 let funcs = List.flatten funcs in
5158 let tested = List.mem name funcs in
5161 failwithf "function %s has tests but does not test itself" name
5164 (* 'pr' prints to the current output file. *)
5165 let chan = ref Pervasives.stdout
5170 let i = count_chars '\n' str in
5171 lines := !lines + i;
5172 output_string !chan str
5175 let copyright_years =
5176 let this_year = 1900 + (localtime (time ())).tm_year in
5177 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5179 (* Generate a header block in a number of standard styles. *)
5180 type comment_style =
5181 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5182 type license = GPLv2plus | LGPLv2plus
5184 let generate_header ?(extra_inputs = []) comment license =
5185 let inputs = "src/generator.ml" :: extra_inputs in
5186 let c = match comment with
5187 | CStyle -> pr "/* "; " *"
5188 | CPlusPlusStyle -> pr "// "; "//"
5189 | HashStyle -> pr "# "; "#"
5190 | OCamlStyle -> pr "(* "; " *"
5191 | HaskellStyle -> pr "{- "; " " in
5192 pr "libguestfs generated file\n";
5193 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5194 List.iter (pr "%s %s\n" c) inputs;
5195 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5197 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5201 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5202 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5203 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5204 pr "%s (at your option) any later version.\n" c;
5206 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5207 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5208 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5209 pr "%s GNU General Public License for more details.\n" c;
5211 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5212 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5213 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5216 pr "%s This library is free software; you can redistribute it and/or\n" c;
5217 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5218 pr "%s License as published by the Free Software Foundation; either\n" c;
5219 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5221 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5222 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5223 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5224 pr "%s Lesser General Public License for more details.\n" c;
5226 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5227 pr "%s License along with this library; if not, write to the Free Software\n" c;
5228 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5231 | CStyle -> pr " */\n"
5234 | OCamlStyle -> pr " *)\n"
5235 | HaskellStyle -> pr "-}\n"
5239 (* Start of main code generation functions below this line. *)
5241 (* Generate the pod documentation for the C API. *)
5242 let rec generate_actions_pod () =
5244 fun (shortname, style, _, flags, _, _, longdesc) ->
5245 if not (List.mem NotInDocs flags) then (
5246 let name = "guestfs_" ^ shortname in
5247 pr "=head2 %s\n\n" name;
5249 generate_prototype ~extern:false ~handle:"g" name style;
5251 pr "%s\n\n" longdesc;
5252 (match fst style with
5254 pr "This function returns 0 on success or -1 on error.\n\n"
5256 pr "On error this function returns -1.\n\n"
5258 pr "On error this function returns -1.\n\n"
5260 pr "This function returns a C truth value on success or -1 on error.\n\n"
5262 pr "This function returns a string, or NULL on error.
5263 The string is owned by the guest handle and must I<not> be freed.\n\n"
5264 | RConstOptString _ ->
5265 pr "This function returns a string which may be NULL.
5266 There is way to return an error from this function.
5267 The string is owned by the guest handle and must I<not> be freed.\n\n"
5269 pr "This function returns a string, or NULL on error.
5270 I<The caller must free the returned string after use>.\n\n"
5272 pr "This function returns a NULL-terminated array of strings
5273 (like L<environ(3)>), or NULL if there was an error.
5274 I<The caller must free the strings and the array after use>.\n\n"
5275 | RStruct (_, typ) ->
5276 pr "This function returns a C<struct guestfs_%s *>,
5277 or NULL if there was an error.
5278 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5279 | RStructList (_, typ) ->
5280 pr "This function returns a C<struct guestfs_%s_list *>
5281 (see E<lt>guestfs-structs.hE<gt>),
5282 or NULL if there was an error.
5283 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5285 pr "This function returns a NULL-terminated array of
5286 strings, or NULL if there was an error.
5287 The array of strings will always have length C<2n+1>, where
5288 C<n> keys and values alternate, followed by the trailing NULL entry.
5289 I<The caller must free the strings and the array after use>.\n\n"
5291 pr "This function returns a buffer, or NULL on error.
5292 The size of the returned buffer is written to C<*size_r>.
5293 I<The caller must free the returned buffer after use>.\n\n"
5295 if List.mem ProtocolLimitWarning flags then
5296 pr "%s\n\n" protocol_limit_warning;
5297 if List.mem DangerWillRobinson flags then
5298 pr "%s\n\n" danger_will_robinson;
5299 match deprecation_notice flags with
5301 | Some txt -> pr "%s\n\n" txt
5303 ) all_functions_sorted
5305 and generate_structs_pod () =
5306 (* Structs documentation. *)
5309 pr "=head2 guestfs_%s\n" typ;
5311 pr " struct guestfs_%s {\n" typ;
5314 | name, FChar -> pr " char %s;\n" name
5315 | name, FUInt32 -> pr " uint32_t %s;\n" name
5316 | name, FInt32 -> pr " int32_t %s;\n" name
5317 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5318 | name, FInt64 -> pr " int64_t %s;\n" name
5319 | name, FString -> pr " char *%s;\n" name
5321 pr " /* The next two fields describe a byte array. */\n";
5322 pr " uint32_t %s_len;\n" name;
5323 pr " char *%s;\n" name
5325 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5326 pr " char %s[32];\n" name
5327 | name, FOptPercent ->
5328 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5329 pr " float %s;\n" name
5333 pr " struct guestfs_%s_list {\n" typ;
5334 pr " uint32_t len; /* Number of elements in list. */\n";
5335 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5338 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5339 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5344 and generate_availability_pod () =
5345 (* Availability documentation. *)
5349 fun (group, functions) ->
5350 pr "=item B<%s>\n" group;
5352 pr "The following functions:\n";
5353 List.iter (pr "L</guestfs_%s>\n") functions;
5359 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5360 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5362 * We have to use an underscore instead of a dash because otherwise
5363 * rpcgen generates incorrect code.
5365 * This header is NOT exported to clients, but see also generate_structs_h.
5367 and generate_xdr () =
5368 generate_header CStyle LGPLv2plus;
5370 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5371 pr "typedef string str<>;\n";
5374 (* Internal structures. *)
5378 pr "struct guestfs_int_%s {\n" typ;
5380 | name, FChar -> pr " char %s;\n" name
5381 | name, FString -> pr " string %s<>;\n" name
5382 | name, FBuffer -> pr " opaque %s<>;\n" name
5383 | name, FUUID -> pr " opaque %s[32];\n" name
5384 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5385 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5386 | name, FOptPercent -> pr " float %s;\n" name
5390 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5395 fun (shortname, style, _, _, _, _, _) ->
5396 let name = "guestfs_" ^ shortname in
5398 (match snd style with
5401 pr "struct %s_args {\n" name;
5404 | Pathname n | Device n | Dev_or_Path n | String n ->
5405 pr " string %s<>;\n" n
5406 | OptString n -> pr " str *%s;\n" n
5407 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5408 | Bool n -> pr " bool %s;\n" n
5409 | Int n -> pr " int %s;\n" n
5410 | Int64 n -> pr " hyper %s;\n" n
5411 | FileIn _ | FileOut _ -> ()
5415 (match fst style with
5418 pr "struct %s_ret {\n" name;
5422 pr "struct %s_ret {\n" name;
5423 pr " hyper %s;\n" n;
5426 pr "struct %s_ret {\n" name;
5429 | RConstString _ | RConstOptString _ ->
5430 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5432 pr "struct %s_ret {\n" name;
5433 pr " string %s<>;\n" n;
5436 pr "struct %s_ret {\n" name;
5437 pr " str %s<>;\n" n;
5439 | RStruct (n, typ) ->
5440 pr "struct %s_ret {\n" name;
5441 pr " guestfs_int_%s %s;\n" typ n;
5443 | RStructList (n, typ) ->
5444 pr "struct %s_ret {\n" name;
5445 pr " guestfs_int_%s_list %s;\n" typ n;
5448 pr "struct %s_ret {\n" name;
5449 pr " str %s<>;\n" n;
5452 pr "struct %s_ret {\n" name;
5453 pr " opaque %s<>;\n" n;
5458 (* Table of procedure numbers. *)
5459 pr "enum guestfs_procedure {\n";
5461 fun (shortname, _, proc_nr, _, _, _, _) ->
5462 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5464 pr " GUESTFS_PROC_NR_PROCS\n";
5468 (* Having to choose a maximum message size is annoying for several
5469 * reasons (it limits what we can do in the API), but it (a) makes
5470 * the protocol a lot simpler, and (b) provides a bound on the size
5471 * of the daemon which operates in limited memory space.
5473 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5476 (* Message header, etc. *)
5478 /* The communication protocol is now documented in the guestfs(3)
5482 const GUESTFS_PROGRAM = 0x2000F5F5;
5483 const GUESTFS_PROTOCOL_VERSION = 1;
5485 /* These constants must be larger than any possible message length. */
5486 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5487 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5489 enum guestfs_message_direction {
5490 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5491 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5494 enum guestfs_message_status {
5495 GUESTFS_STATUS_OK = 0,
5496 GUESTFS_STATUS_ERROR = 1
5499 const GUESTFS_ERROR_LEN = 256;
5501 struct guestfs_message_error {
5502 string error_message<GUESTFS_ERROR_LEN>;
5505 struct guestfs_message_header {
5506 unsigned prog; /* GUESTFS_PROGRAM */
5507 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5508 guestfs_procedure proc; /* GUESTFS_PROC_x */
5509 guestfs_message_direction direction;
5510 unsigned serial; /* message serial number */
5511 guestfs_message_status status;
5514 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5516 struct guestfs_chunk {
5517 int cancel; /* if non-zero, transfer is cancelled */
5518 /* data size is 0 bytes if the transfer has finished successfully */
5519 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5523 (* Generate the guestfs-structs.h file. *)
5524 and generate_structs_h () =
5525 generate_header CStyle LGPLv2plus;
5527 (* This is a public exported header file containing various
5528 * structures. The structures are carefully written to have
5529 * exactly the same in-memory format as the XDR structures that
5530 * we use on the wire to the daemon. The reason for creating
5531 * copies of these structures here is just so we don't have to
5532 * export the whole of guestfs_protocol.h (which includes much
5533 * unrelated and XDR-dependent stuff that we don't want to be
5534 * public, or required by clients).
5536 * To reiterate, we will pass these structures to and from the
5537 * client with a simple assignment or memcpy, so the format
5538 * must be identical to what rpcgen / the RFC defines.
5541 (* Public structures. *)
5544 pr "struct guestfs_%s {\n" typ;
5547 | name, FChar -> pr " char %s;\n" name
5548 | name, FString -> pr " char *%s;\n" name
5550 pr " uint32_t %s_len;\n" name;
5551 pr " char *%s;\n" name
5552 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5553 | name, FUInt32 -> pr " uint32_t %s;\n" name
5554 | name, FInt32 -> pr " int32_t %s;\n" name
5555 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5556 | name, FInt64 -> pr " int64_t %s;\n" name
5557 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5561 pr "struct guestfs_%s_list {\n" typ;
5562 pr " uint32_t len;\n";
5563 pr " struct guestfs_%s *val;\n" typ;
5566 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5567 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5571 (* Generate the guestfs-actions.h file. *)
5572 and generate_actions_h () =
5573 generate_header CStyle LGPLv2plus;
5575 fun (shortname, style, _, _, _, _, _) ->
5576 let name = "guestfs_" ^ shortname in
5577 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5581 (* Generate the guestfs-internal-actions.h file. *)
5582 and generate_internal_actions_h () =
5583 generate_header CStyle LGPLv2plus;
5585 fun (shortname, style, _, _, _, _, _) ->
5586 let name = "guestfs__" ^ shortname in
5587 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5589 ) non_daemon_functions
5591 (* Generate the client-side dispatch stubs. *)
5592 and generate_client_actions () =
5593 generate_header CStyle LGPLv2plus;
5600 #include <inttypes.h>
5602 #include \"guestfs.h\"
5603 #include \"guestfs-internal.h\"
5604 #include \"guestfs-internal-actions.h\"
5605 #include \"guestfs_protocol.h\"
5607 #define error guestfs_error
5608 //#define perrorf guestfs_perrorf
5609 #define safe_malloc guestfs_safe_malloc
5610 #define safe_realloc guestfs_safe_realloc
5611 //#define safe_strdup guestfs_safe_strdup
5612 #define safe_memdup guestfs_safe_memdup
5614 /* Check the return message from a call for validity. */
5616 check_reply_header (guestfs_h *g,
5617 const struct guestfs_message_header *hdr,
5618 unsigned int proc_nr, unsigned int serial)
5620 if (hdr->prog != GUESTFS_PROGRAM) {
5621 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5624 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5625 error (g, \"wrong protocol version (%%d/%%d)\",
5626 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5629 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5630 error (g, \"unexpected message direction (%%d/%%d)\",
5631 hdr->direction, GUESTFS_DIRECTION_REPLY);
5634 if (hdr->proc != proc_nr) {
5635 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5638 if (hdr->serial != serial) {
5639 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5646 /* Check we are in the right state to run a high-level action. */
5648 check_state (guestfs_h *g, const char *caller)
5650 if (!guestfs__is_ready (g)) {
5651 if (guestfs__is_config (g) || guestfs__is_launching (g))
5652 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5655 error (g, \"%%s called from the wrong state, %%d != READY\",
5656 caller, guestfs__get_state (g));
5664 (* Generate code to generate guestfish call traces. *)
5665 let trace_call shortname style =
5666 pr " if (guestfs__get_trace (g)) {\n";
5669 List.exists (function
5670 | StringList _ | DeviceList _ -> true
5671 | _ -> false) (snd style) in
5677 pr " printf (\"%s\");\n" shortname;
5680 | String n (* strings *)
5686 (* guestfish doesn't support string escaping, so neither do we *)
5687 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5688 | OptString n -> (* string option *)
5689 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5690 pr " else printf (\" null\");\n"
5692 | DeviceList n -> (* string list *)
5693 pr " putchar (' ');\n";
5694 pr " putchar ('\"');\n";
5695 pr " for (i = 0; %s[i]; ++i) {\n" n;
5696 pr " if (i > 0) putchar (' ');\n";
5697 pr " fputs (%s[i], stdout);\n" n;
5699 pr " putchar ('\"');\n";
5700 | Bool n -> (* boolean *)
5701 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5702 | Int n -> (* int *)
5703 pr " printf (\" %%d\", %s);\n" n
5705 pr " printf (\" %%\" PRIi64, %s);\n" n
5707 pr " putchar ('\\n');\n";
5712 (* For non-daemon functions, generate a wrapper around each function. *)
5714 fun (shortname, style, _, _, _, _, _) ->
5715 let name = "guestfs_" ^ shortname in
5717 generate_prototype ~extern:false ~semicolon:false ~newline:true
5718 ~handle:"g" name style;
5720 trace_call shortname style;
5721 pr " return guestfs__%s " shortname;
5722 generate_c_call_args ~handle:"g" style;
5726 ) non_daemon_functions;
5728 (* Client-side stubs for each function. *)
5730 fun (shortname, style, _, _, _, _, _) ->
5731 let name = "guestfs_" ^ shortname in
5733 (* Generate the action stub. *)
5734 generate_prototype ~extern:false ~semicolon:false ~newline:true
5735 ~handle:"g" name style;
5738 match fst style with
5739 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5740 | RConstString _ | RConstOptString _ ->
5741 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5742 | RString _ | RStringList _
5743 | RStruct _ | RStructList _
5744 | RHashtable _ | RBufferOut _ ->
5749 (match snd style with
5751 | _ -> pr " struct %s_args args;\n" name
5754 pr " guestfs_message_header hdr;\n";
5755 pr " guestfs_message_error err;\n";
5757 match fst style with
5759 | RConstString _ | RConstOptString _ ->
5760 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5762 | RBool _ | RString _ | RStringList _
5763 | RStruct _ | RStructList _
5764 | RHashtable _ | RBufferOut _ ->
5765 pr " struct %s_ret ret;\n" name;
5768 pr " int serial;\n";
5771 trace_call shortname style;
5772 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5773 shortname error_code;
5774 pr " guestfs___set_busy (g);\n";
5777 (* Send the main header and arguments. *)
5778 (match snd style with
5780 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5781 (String.uppercase shortname)
5785 | Pathname n | Device n | Dev_or_Path n | String n ->
5786 pr " args.%s = (char *) %s;\n" n n
5788 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5789 | StringList n | DeviceList n ->
5790 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5791 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5793 pr " args.%s = %s;\n" n n
5795 pr " args.%s = %s;\n" n n
5797 pr " args.%s = %s;\n" n n
5798 | FileIn _ | FileOut _ -> ()
5800 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5801 (String.uppercase shortname);
5802 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5805 pr " if (serial == -1) {\n";
5806 pr " guestfs___end_busy (g);\n";
5807 pr " return %s;\n" error_code;
5811 (* Send any additional files (FileIn) requested. *)
5812 let need_read_reply_label = ref false in
5816 pr " r = guestfs___send_file (g, %s);\n" n;
5817 pr " if (r == -1) {\n";
5818 pr " guestfs___end_busy (g);\n";
5819 pr " return %s;\n" error_code;
5821 pr " if (r == -2) /* daemon cancelled */\n";
5822 pr " goto read_reply;\n";
5823 need_read_reply_label := true;
5828 (* Wait for the reply from the remote end. *)
5829 if !need_read_reply_label then pr " read_reply:\n";
5830 pr " memset (&hdr, 0, sizeof hdr);\n";
5831 pr " memset (&err, 0, sizeof err);\n";
5832 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5834 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5838 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5841 pr " if (r == -1) {\n";
5842 pr " guestfs___end_busy (g);\n";
5843 pr " return %s;\n" error_code;
5847 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5848 (String.uppercase shortname);
5849 pr " guestfs___end_busy (g);\n";
5850 pr " return %s;\n" error_code;
5854 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5855 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5856 pr " free (err.error_message);\n";
5857 pr " guestfs___end_busy (g);\n";
5858 pr " return %s;\n" error_code;
5862 (* Expecting to receive further files (FileOut)? *)
5866 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5867 pr " guestfs___end_busy (g);\n";
5868 pr " return %s;\n" error_code;
5874 pr " guestfs___end_busy (g);\n";
5876 (match fst style with
5877 | RErr -> pr " return 0;\n"
5878 | RInt n | RInt64 n | RBool n ->
5879 pr " return ret.%s;\n" n
5880 | RConstString _ | RConstOptString _ ->
5881 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5883 pr " return ret.%s; /* caller will free */\n" n
5884 | RStringList n | RHashtable n ->
5885 pr " /* caller will free this, but we need to add a NULL entry */\n";
5886 pr " ret.%s.%s_val =\n" n n;
5887 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5888 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5890 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5891 pr " return ret.%s.%s_val;\n" n n
5893 pr " /* caller will free this */\n";
5894 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5895 | RStructList (n, _) ->
5896 pr " /* caller will free this */\n";
5897 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5899 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5900 pr " * _val might be NULL here. To make the API saner for\n";
5901 pr " * callers, we turn this case into a unique pointer (using\n";
5902 pr " * malloc(1)).\n";
5904 pr " if (ret.%s.%s_len > 0) {\n" n n;
5905 pr " *size_r = ret.%s.%s_len;\n" n n;
5906 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5908 pr " free (ret.%s.%s_val);\n" n n;
5909 pr " char *p = safe_malloc (g, 1);\n";
5910 pr " *size_r = ret.%s.%s_len;\n" n n;
5918 (* Functions to free structures. *)
5919 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5920 pr " * structure format is identical to the XDR format. See note in\n";
5921 pr " * generator.ml.\n";
5928 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5930 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5936 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5938 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5945 (* Generate daemon/actions.h. *)
5946 and generate_daemon_actions_h () =
5947 generate_header CStyle GPLv2plus;
5949 pr "#include \"../src/guestfs_protocol.h\"\n";
5953 fun (name, style, _, _, _, _, _) ->
5955 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5959 (* Generate the linker script which controls the visibility of
5960 * symbols in the public ABI and ensures no other symbols get
5961 * exported accidentally.
5963 and generate_linker_script () =
5964 generate_header HashStyle GPLv2plus;
5969 "guestfs_get_error_handler";
5970 "guestfs_get_out_of_memory_handler";
5971 "guestfs_last_error";
5972 "guestfs_set_error_handler";
5973 "guestfs_set_launch_done_callback";
5974 "guestfs_set_log_message_callback";
5975 "guestfs_set_out_of_memory_handler";
5976 "guestfs_set_subprocess_quit_callback";
5978 (* Unofficial parts of the API: the bindings code use these
5979 * functions, so it is useful to export them.
5981 "guestfs_safe_calloc";
5982 "guestfs_safe_malloc";
5985 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5989 List.map (fun (typ, _) ->
5990 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5993 let globals = List.sort compare (globals @ functions @ structs) in
5997 List.iter (pr " %s;\n") globals;
6004 (* Generate the server-side stubs. *)
6005 and generate_daemon_actions () =
6006 generate_header CStyle GPLv2plus;
6008 pr "#include <config.h>\n";
6010 pr "#include <stdio.h>\n";
6011 pr "#include <stdlib.h>\n";
6012 pr "#include <string.h>\n";
6013 pr "#include <inttypes.h>\n";
6014 pr "#include <rpc/types.h>\n";
6015 pr "#include <rpc/xdr.h>\n";
6017 pr "#include \"daemon.h\"\n";
6018 pr "#include \"c-ctype.h\"\n";
6019 pr "#include \"../src/guestfs_protocol.h\"\n";
6020 pr "#include \"actions.h\"\n";
6024 fun (name, style, _, _, _, _, _) ->
6025 (* Generate server-side stubs. *)
6026 pr "static void %s_stub (XDR *xdr_in)\n" name;
6029 match fst style with
6030 | RErr | RInt _ -> pr " int r;\n"; "-1"
6031 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6032 | RBool _ -> pr " int r;\n"; "-1"
6033 | RConstString _ | RConstOptString _ ->
6034 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6035 | RString _ -> pr " char *r;\n"; "NULL"
6036 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6037 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6038 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6040 pr " size_t size = 1;\n";
6044 (match snd style with
6047 pr " struct guestfs_%s_args args;\n" name;
6050 | Device n | Dev_or_Path n
6053 | OptString n -> pr " char *%s;\n" n
6054 | StringList n | DeviceList n -> pr " char **%s;\n" n
6055 | Bool n -> pr " int %s;\n" n
6056 | Int n -> pr " int %s;\n" n
6057 | Int64 n -> pr " int64_t %s;\n" n
6058 | FileIn _ | FileOut _ -> ()
6064 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6066 (match snd style with
6069 pr " memset (&args, 0, sizeof args);\n";
6071 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6073 pr " cancel_receive ();\n";
6074 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6078 pr " char *%s = args.%s;\n" n n
6080 let pr_list_handling_code n =
6081 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6082 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6083 pr " if (%s == NULL) {\n" n;
6085 pr " cancel_receive ();\n";
6086 pr " reply_with_perror (\"realloc\");\n";
6089 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6090 pr " args.%s.%s_val = %s;\n" n n n;
6096 pr " ABS_PATH (%s, %s, goto done);\n"
6097 n (if is_filein then "cancel_receive ()" else "");
6100 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6101 n (if is_filein then "cancel_receive ()" else "");
6104 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6105 n (if is_filein then "cancel_receive ()" else "");
6106 | String n -> pr_args n
6107 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6109 pr_list_handling_code n;
6111 pr_list_handling_code n;
6112 pr " /* Ensure that each is a device,\n";
6113 pr " * and perform device name translation. */\n";
6114 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6115 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6116 (if is_filein then "cancel_receive ()" else "");
6118 | Bool n -> pr " %s = args.%s;\n" n n
6119 | Int n -> pr " %s = args.%s;\n" n n
6120 | Int64 n -> pr " %s = args.%s;\n" n n
6121 | FileIn _ | FileOut _ -> ()
6127 (* this is used at least for do_equal *)
6128 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6129 (* Emit NEED_ROOT just once, even when there are two or
6130 more Pathname args *)
6131 pr " NEED_ROOT (%s, goto done);\n"
6132 (if is_filein then "cancel_receive ()" else "");
6135 (* Don't want to call the impl with any FileIn or FileOut
6136 * parameters, since these go "outside" the RPC protocol.
6139 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6141 pr " r = do_%s " name;
6142 generate_c_call_args (fst style, args');
6145 (match fst style with
6146 | RErr | RInt _ | RInt64 _ | RBool _
6147 | RConstString _ | RConstOptString _
6148 | RString _ | RStringList _ | RHashtable _
6149 | RStruct (_, _) | RStructList (_, _) ->
6150 pr " if (r == %s)\n" error_code;
6151 pr " /* do_%s has already called reply_with_error */\n" name;
6155 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6156 pr " * an ordinary zero-length buffer), so be careful ...\n";
6158 pr " if (size == 1 && r == %s)\n" error_code;
6159 pr " /* do_%s has already called reply_with_error */\n" name;
6164 (* If there are any FileOut parameters, then the impl must
6165 * send its own reply.
6168 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6170 pr " /* do_%s has already sent a reply */\n" name
6172 match fst style with
6173 | RErr -> pr " reply (NULL, NULL);\n"
6174 | RInt n | RInt64 n | RBool n ->
6175 pr " struct guestfs_%s_ret ret;\n" name;
6176 pr " ret.%s = r;\n" n;
6177 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6179 | RConstString _ | RConstOptString _ ->
6180 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6182 pr " struct guestfs_%s_ret ret;\n" name;
6183 pr " ret.%s = r;\n" n;
6184 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6187 | RStringList n | RHashtable n ->
6188 pr " struct guestfs_%s_ret ret;\n" name;
6189 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6190 pr " ret.%s.%s_val = r;\n" n n;
6191 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6193 pr " free_strings (r);\n"
6195 pr " struct guestfs_%s_ret ret;\n" name;
6196 pr " ret.%s = *r;\n" n;
6197 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6199 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6201 | RStructList (n, _) ->
6202 pr " struct guestfs_%s_ret ret;\n" name;
6203 pr " ret.%s = *r;\n" n;
6204 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6206 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6209 pr " struct guestfs_%s_ret ret;\n" name;
6210 pr " ret.%s.%s_val = r;\n" n n;
6211 pr " ret.%s.%s_len = size;\n" n n;
6212 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6217 (* Free the args. *)
6219 (match snd style with
6222 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6229 (* Dispatch function. *)
6230 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6232 pr " switch (proc_nr) {\n";
6235 fun (name, style, _, _, _, _, _) ->
6236 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6237 pr " %s_stub (xdr_in);\n" name;
6242 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";
6247 (* LVM columns and tokenization functions. *)
6248 (* XXX This generates crap code. We should rethink how we
6254 pr "static const char *lvm_%s_cols = \"%s\";\n"
6255 typ (String.concat "," (List.map fst cols));
6258 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6260 pr " char *tok, *p, *next;\n";
6264 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6267 pr " if (!str) {\n";
6268 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6271 pr " if (!*str || c_isspace (*str)) {\n";
6272 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6277 fun (name, coltype) ->
6278 pr " if (!tok) {\n";
6279 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6282 pr " p = strchrnul (tok, ',');\n";
6283 pr " if (*p) next = p+1; else next = NULL;\n";
6284 pr " *p = '\\0';\n";
6287 pr " r->%s = strdup (tok);\n" name;
6288 pr " if (r->%s == NULL) {\n" name;
6289 pr " perror (\"strdup\");\n";
6293 pr " for (i = j = 0; i < 32; ++j) {\n";
6294 pr " if (tok[j] == '\\0') {\n";
6295 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6297 pr " } else if (tok[j] != '-')\n";
6298 pr " r->%s[i++] = tok[j];\n" name;
6301 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6302 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6306 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6307 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6311 pr " if (tok[0] == '\\0')\n";
6312 pr " r->%s = -1;\n" name;
6313 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6314 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6317 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6318 assert false (* can never be an LVM column *)
6320 pr " tok = next;\n";
6323 pr " if (tok != NULL) {\n";
6324 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6331 pr "guestfs_int_lvm_%s_list *\n" typ;
6332 pr "parse_command_line_%ss (void)\n" typ;
6334 pr " char *out, *err;\n";
6335 pr " char *p, *pend;\n";
6337 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6338 pr " void *newp;\n";
6340 pr " ret = malloc (sizeof *ret);\n";
6341 pr " if (!ret) {\n";
6342 pr " reply_with_perror (\"malloc\");\n";
6343 pr " return NULL;\n";
6346 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6347 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6349 pr " r = command (&out, &err,\n";
6350 pr " \"lvm\", \"%ss\",\n" typ;
6351 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6352 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6353 pr " if (r == -1) {\n";
6354 pr " reply_with_error (\"%%s\", err);\n";
6355 pr " free (out);\n";
6356 pr " free (err);\n";
6357 pr " free (ret);\n";
6358 pr " return NULL;\n";
6361 pr " free (err);\n";
6363 pr " /* Tokenize each line of the output. */\n";
6366 pr " while (p) {\n";
6367 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6368 pr " if (pend) {\n";
6369 pr " *pend = '\\0';\n";
6373 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6376 pr " if (!*p) { /* Empty line? Skip it. */\n";
6381 pr " /* Allocate some space to store this next entry. */\n";
6382 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6383 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6384 pr " if (newp == NULL) {\n";
6385 pr " reply_with_perror (\"realloc\");\n";
6386 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6387 pr " free (ret);\n";
6388 pr " free (out);\n";
6389 pr " return NULL;\n";
6391 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6393 pr " /* Tokenize the next entry. */\n";
6394 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6395 pr " if (r == -1) {\n";
6396 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6397 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6398 pr " free (ret);\n";
6399 pr " free (out);\n";
6400 pr " return NULL;\n";
6407 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6409 pr " free (out);\n";
6410 pr " return ret;\n";
6413 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6415 (* Generate a list of function names, for debugging in the daemon.. *)
6416 and generate_daemon_names () =
6417 generate_header CStyle GPLv2plus;
6419 pr "#include <config.h>\n";
6421 pr "#include \"daemon.h\"\n";
6424 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6425 pr "const char *function_names[] = {\n";
6427 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6431 (* Generate the optional groups for the daemon to implement
6432 * guestfs_available.
6434 and generate_daemon_optgroups_c () =
6435 generate_header CStyle GPLv2plus;
6437 pr "#include <config.h>\n";
6439 pr "#include \"daemon.h\"\n";
6440 pr "#include \"optgroups.h\"\n";
6443 pr "struct optgroup optgroups[] = {\n";
6446 pr " { \"%s\", optgroup_%s_available },\n" group group
6448 pr " { NULL, NULL }\n";
6451 and generate_daemon_optgroups_h () =
6452 generate_header CStyle GPLv2plus;
6456 pr "extern int optgroup_%s_available (void);\n" group
6459 (* Generate the tests. *)
6460 and generate_tests () =
6461 generate_header CStyle GPLv2plus;
6468 #include <sys/types.h>
6471 #include \"guestfs.h\"
6472 #include \"guestfs-internal.h\"
6474 static guestfs_h *g;
6475 static int suppress_error = 0;
6477 static void print_error (guestfs_h *g, void *data, const char *msg)
6479 if (!suppress_error)
6480 fprintf (stderr, \"%%s\\n\", msg);
6483 /* FIXME: nearly identical code appears in fish.c */
6484 static void print_strings (char *const *argv)
6488 for (argc = 0; argv[argc] != NULL; ++argc)
6489 printf (\"\\t%%s\\n\", argv[argc]);
6493 static void print_table (char const *const *argv)
6497 for (i = 0; argv[i] != NULL; i += 2)
6498 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6504 (* Generate a list of commands which are not tested anywhere. *)
6505 pr "static void no_test_warnings (void)\n";
6508 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6510 fun (_, _, _, _, tests, _, _) ->
6511 let tests = filter_map (
6513 | (_, (Always|If _|Unless _), test) -> Some test
6514 | (_, Disabled, _) -> None
6516 let seq = List.concat (List.map seq_of_test tests) in
6517 let cmds_tested = List.map List.hd seq in
6518 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6522 fun (name, _, _, _, _, _, _) ->
6523 if not (Hashtbl.mem hash name) then
6524 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6530 (* Generate the actual tests. Note that we generate the tests
6531 * in reverse order, deliberately, so that (in general) the
6532 * newest tests run first. This makes it quicker and easier to
6537 fun (name, _, _, flags, tests, _, _) ->
6538 mapi (generate_one_test name flags) tests
6539 ) (List.rev all_functions) in
6540 let test_names = List.concat test_names in
6541 let nr_tests = List.length test_names in
6544 int main (int argc, char *argv[])
6547 unsigned long int n_failed = 0;
6548 const char *filename;
6550 int nr_tests, test_num = 0;
6552 setbuf (stdout, NULL);
6554 no_test_warnings ();
6556 g = guestfs_create ();
6558 printf (\"guestfs_create FAILED\\n\");
6559 exit (EXIT_FAILURE);
6562 guestfs_set_error_handler (g, print_error, NULL);
6564 guestfs_set_path (g, \"../appliance\");
6566 filename = \"test1.img\";
6567 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6570 exit (EXIT_FAILURE);
6572 if (lseek (fd, %d, SEEK_SET) == -1) {
6576 exit (EXIT_FAILURE);
6578 if (write (fd, &c, 1) == -1) {
6582 exit (EXIT_FAILURE);
6584 if (close (fd) == -1) {
6587 exit (EXIT_FAILURE);
6589 if (guestfs_add_drive (g, filename) == -1) {
6590 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6591 exit (EXIT_FAILURE);
6594 filename = \"test2.img\";
6595 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6598 exit (EXIT_FAILURE);
6600 if (lseek (fd, %d, SEEK_SET) == -1) {
6604 exit (EXIT_FAILURE);
6606 if (write (fd, &c, 1) == -1) {
6610 exit (EXIT_FAILURE);
6612 if (close (fd) == -1) {
6615 exit (EXIT_FAILURE);
6617 if (guestfs_add_drive (g, filename) == -1) {
6618 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6619 exit (EXIT_FAILURE);
6622 filename = \"test3.img\";
6623 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6626 exit (EXIT_FAILURE);
6628 if (lseek (fd, %d, SEEK_SET) == -1) {
6632 exit (EXIT_FAILURE);
6634 if (write (fd, &c, 1) == -1) {
6638 exit (EXIT_FAILURE);
6640 if (close (fd) == -1) {
6643 exit (EXIT_FAILURE);
6645 if (guestfs_add_drive (g, filename) == -1) {
6646 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6647 exit (EXIT_FAILURE);
6650 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6651 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6652 exit (EXIT_FAILURE);
6655 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6658 if (guestfs_launch (g) == -1) {
6659 printf (\"guestfs_launch FAILED\\n\");
6660 exit (EXIT_FAILURE);
6663 /* Cancel previous alarm. */
6668 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6672 pr " test_num++;\n";
6673 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6674 pr " if (%s () == -1) {\n" test_name;
6675 pr " printf (\"%s FAILED\\n\");\n" test_name;
6676 pr " n_failed++;\n";
6681 pr " guestfs_close (g);\n";
6682 pr " unlink (\"test1.img\");\n";
6683 pr " unlink (\"test2.img\");\n";
6684 pr " unlink (\"test3.img\");\n";
6687 pr " if (n_failed > 0) {\n";
6688 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6689 pr " exit (EXIT_FAILURE);\n";
6693 pr " exit (EXIT_SUCCESS);\n";
6696 and generate_one_test name flags i (init, prereq, test) =
6697 let test_name = sprintf "test_%s_%d" name i in
6700 static int %s_skip (void)
6704 str = getenv (\"TEST_ONLY\");
6706 return strstr (str, \"%s\") == NULL;
6707 str = getenv (\"SKIP_%s\");
6708 if (str && STREQ (str, \"1\")) return 1;
6709 str = getenv (\"SKIP_TEST_%s\");
6710 if (str && STREQ (str, \"1\")) return 1;
6714 " test_name name (String.uppercase test_name) (String.uppercase name);
6717 | Disabled | Always -> ()
6718 | If code | Unless code ->
6719 pr "static int %s_prereq (void)\n" test_name;
6727 static int %s (void)
6730 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6734 " test_name test_name test_name;
6736 (* Optional functions should only be tested if the relevant
6737 * support is available in the daemon.
6743 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6745 pr " suppress_error = 1;\n";
6746 pr " r = guestfs_available (g, (char **) groups);\n";
6747 pr " suppress_error = 0;\n";
6748 pr " if (r == -1) {\n";
6749 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6758 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6760 pr " if (! %s_prereq ()) {\n" test_name;
6761 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6765 generate_one_test_body name i test_name init test;
6767 pr " if (%s_prereq ()) {\n" test_name;
6768 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6772 generate_one_test_body name i test_name init test;
6774 generate_one_test_body name i test_name init test
6782 and generate_one_test_body name i test_name init test =
6784 | InitNone (* XXX at some point, InitNone and InitEmpty became
6785 * folded together as the same thing. Really we should
6786 * make InitNone do nothing at all, but the tests may
6787 * need to be checked to make sure this is OK.
6790 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6791 List.iter (generate_test_command_call test_name)
6792 [["blockdev_setrw"; "/dev/sda"];
6796 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6797 List.iter (generate_test_command_call test_name)
6798 [["blockdev_setrw"; "/dev/sda"];
6801 ["part_disk"; "/dev/sda"; "mbr"]]
6803 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6804 List.iter (generate_test_command_call test_name)
6805 [["blockdev_setrw"; "/dev/sda"];
6808 ["part_disk"; "/dev/sda"; "mbr"];
6809 ["mkfs"; "ext2"; "/dev/sda1"];
6810 ["mount_options"; ""; "/dev/sda1"; "/"]]
6811 | InitBasicFSonLVM ->
6812 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6814 List.iter (generate_test_command_call test_name)
6815 [["blockdev_setrw"; "/dev/sda"];
6818 ["part_disk"; "/dev/sda"; "mbr"];
6819 ["pvcreate"; "/dev/sda1"];
6820 ["vgcreate"; "VG"; "/dev/sda1"];
6821 ["lvcreate"; "LV"; "VG"; "8"];
6822 ["mkfs"; "ext2"; "/dev/VG/LV"];
6823 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6825 pr " /* InitISOFS for %s */\n" test_name;
6826 List.iter (generate_test_command_call test_name)
6827 [["blockdev_setrw"; "/dev/sda"];
6830 ["mount_ro"; "/dev/sdd"; "/"]]
6833 let get_seq_last = function
6835 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6838 let seq = List.rev seq in
6839 List.rev (List.tl seq), List.hd seq
6844 pr " /* TestRun for %s (%d) */\n" name i;
6845 List.iter (generate_test_command_call test_name) seq
6846 | TestOutput (seq, expected) ->
6847 pr " /* TestOutput for %s (%d) */\n" name i;
6848 pr " const char *expected = \"%s\";\n" (c_quote expected);
6849 let seq, last = get_seq_last seq in
6851 pr " if (STRNEQ (r, expected)) {\n";
6852 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6856 List.iter (generate_test_command_call test_name) seq;
6857 generate_test_command_call ~test test_name last
6858 | TestOutputList (seq, expected) ->
6859 pr " /* TestOutputList for %s (%d) */\n" name i;
6860 let seq, last = get_seq_last seq in
6864 pr " if (!r[%d]) {\n" i;
6865 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6866 pr " print_strings (r);\n";
6870 pr " const char *expected = \"%s\";\n" (c_quote str);
6871 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6872 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6877 pr " if (r[%d] != NULL) {\n" (List.length expected);
6878 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6880 pr " print_strings (r);\n";
6884 List.iter (generate_test_command_call test_name) seq;
6885 generate_test_command_call ~test test_name last
6886 | TestOutputListOfDevices (seq, expected) ->
6887 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6888 let seq, last = get_seq_last seq in
6892 pr " if (!r[%d]) {\n" i;
6893 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6894 pr " print_strings (r);\n";
6898 pr " const char *expected = \"%s\";\n" (c_quote str);
6899 pr " r[%d][5] = 's';\n" i;
6900 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6901 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6906 pr " if (r[%d] != NULL) {\n" (List.length expected);
6907 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6909 pr " print_strings (r);\n";
6913 List.iter (generate_test_command_call test_name) seq;
6914 generate_test_command_call ~test test_name last
6915 | TestOutputInt (seq, expected) ->
6916 pr " /* TestOutputInt for %s (%d) */\n" name i;
6917 let seq, last = get_seq_last seq in
6919 pr " if (r != %d) {\n" expected;
6920 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6926 List.iter (generate_test_command_call test_name) seq;
6927 generate_test_command_call ~test test_name last
6928 | TestOutputIntOp (seq, op, expected) ->
6929 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6930 let seq, last = get_seq_last seq in
6932 pr " if (! (r %s %d)) {\n" op expected;
6933 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6934 test_name op expected;
6939 List.iter (generate_test_command_call test_name) seq;
6940 generate_test_command_call ~test test_name last
6941 | TestOutputTrue seq ->
6942 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6943 let seq, last = get_seq_last seq in
6946 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6951 List.iter (generate_test_command_call test_name) seq;
6952 generate_test_command_call ~test test_name last
6953 | TestOutputFalse seq ->
6954 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6955 let seq, last = get_seq_last seq in
6958 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6963 List.iter (generate_test_command_call test_name) seq;
6964 generate_test_command_call ~test test_name last
6965 | TestOutputLength (seq, expected) ->
6966 pr " /* TestOutputLength for %s (%d) */\n" name i;
6967 let seq, last = get_seq_last seq in
6970 pr " for (j = 0; j < %d; ++j)\n" expected;
6971 pr " if (r[j] == NULL) {\n";
6972 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6974 pr " print_strings (r);\n";
6977 pr " if (r[j] != NULL) {\n";
6978 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6980 pr " print_strings (r);\n";
6984 List.iter (generate_test_command_call test_name) seq;
6985 generate_test_command_call ~test test_name last
6986 | TestOutputBuffer (seq, expected) ->
6987 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6988 pr " const char *expected = \"%s\";\n" (c_quote expected);
6989 let seq, last = get_seq_last seq in
6990 let len = String.length expected in
6992 pr " if (size != %d) {\n" len;
6993 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6996 pr " if (STRNEQLEN (r, expected, size)) {\n";
6997 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7001 List.iter (generate_test_command_call test_name) seq;
7002 generate_test_command_call ~test test_name last
7003 | TestOutputStruct (seq, checks) ->
7004 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7005 let seq, last = get_seq_last seq in
7009 | CompareWithInt (field, expected) ->
7010 pr " if (r->%s != %d) {\n" field expected;
7011 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7012 test_name field expected;
7013 pr " (int) r->%s);\n" field;
7016 | CompareWithIntOp (field, op, expected) ->
7017 pr " if (!(r->%s %s %d)) {\n" field op expected;
7018 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7019 test_name field op expected;
7020 pr " (int) r->%s);\n" field;
7023 | CompareWithString (field, expected) ->
7024 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7025 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7026 test_name field expected;
7027 pr " r->%s);\n" field;
7030 | CompareFieldsIntEq (field1, field2) ->
7031 pr " if (r->%s != r->%s) {\n" field1 field2;
7032 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7033 test_name field1 field2;
7034 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7037 | CompareFieldsStrEq (field1, field2) ->
7038 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7039 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7040 test_name field1 field2;
7041 pr " r->%s, r->%s);\n" field1 field2;
7046 List.iter (generate_test_command_call test_name) seq;
7047 generate_test_command_call ~test test_name last
7048 | TestLastFail seq ->
7049 pr " /* TestLastFail for %s (%d) */\n" name i;
7050 let seq, last = get_seq_last seq in
7051 List.iter (generate_test_command_call test_name) seq;
7052 generate_test_command_call test_name ~expect_error:true last
7054 (* Generate the code to run a command, leaving the result in 'r'.
7055 * If you expect to get an error then you should set expect_error:true.
7057 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7059 | [] -> assert false
7061 (* Look up the command to find out what args/ret it has. *)
7064 let _, style, _, _, _, _, _ =
7065 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7068 failwithf "%s: in test, command %s was not found" test_name name in
7070 if List.length (snd style) <> List.length args then
7071 failwithf "%s: in test, wrong number of args given to %s"
7078 | OptString n, "NULL" -> ()
7081 | Dev_or_Path n, arg
7083 | OptString n, arg ->
7084 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7088 | FileIn _, _ | FileOut _, _ -> ()
7089 | StringList n, "" | DeviceList n, "" ->
7090 pr " const char *const %s[1] = { NULL };\n" n
7091 | StringList n, arg | DeviceList n, arg ->
7092 let strs = string_split " " arg in
7095 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7097 pr " const char *const %s[] = {\n" n;
7099 fun i _ -> pr " %s_%d,\n" n i
7103 ) (List.combine (snd style) args);
7106 match fst style with
7107 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7108 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7109 | RConstString _ | RConstOptString _ ->
7110 pr " const char *r;\n"; "NULL"
7111 | RString _ -> pr " char *r;\n"; "NULL"
7112 | RStringList _ | RHashtable _ ->
7116 | RStruct (_, typ) ->
7117 pr " struct guestfs_%s *r;\n" typ; "NULL"
7118 | RStructList (_, typ) ->
7119 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7122 pr " size_t size;\n";
7125 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7126 pr " r = guestfs_%s (g" name;
7128 (* Generate the parameters. *)
7131 | OptString _, "NULL" -> pr ", NULL"
7133 | Device n, _ | Dev_or_Path n, _
7137 | FileIn _, arg | FileOut _, arg ->
7138 pr ", \"%s\"" (c_quote arg)
7139 | StringList n, _ | DeviceList n, _ ->
7140 pr ", (char **) %s" n
7143 try int_of_string arg
7144 with Failure "int_of_string" ->
7145 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7149 try Int64.of_string arg
7150 with Failure "int_of_string" ->
7151 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7154 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7155 ) (List.combine (snd style) args);
7157 (match fst style with
7158 | RBufferOut _ -> pr ", &size"
7164 if not expect_error then
7165 pr " if (r == %s)\n" error_code
7167 pr " if (r != %s)\n" error_code;
7170 (* Insert the test code. *)
7176 (match fst style with
7177 | RErr | RInt _ | RInt64 _ | RBool _
7178 | RConstString _ | RConstOptString _ -> ()
7179 | RString _ | RBufferOut _ -> pr " free (r);\n"
7180 | RStringList _ | RHashtable _ ->
7181 pr " for (i = 0; r[i] != NULL; ++i)\n";
7182 pr " free (r[i]);\n";
7184 | RStruct (_, typ) ->
7185 pr " guestfs_free_%s (r);\n" typ
7186 | RStructList (_, typ) ->
7187 pr " guestfs_free_%s_list (r);\n" typ
7193 let str = replace_str str "\r" "\\r" in
7194 let str = replace_str str "\n" "\\n" in
7195 let str = replace_str str "\t" "\\t" in
7196 let str = replace_str str "\000" "\\0" in
7199 (* Generate a lot of different functions for guestfish. *)
7200 and generate_fish_cmds () =
7201 generate_header CStyle GPLv2plus;
7205 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7207 let all_functions_sorted =
7209 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7210 ) all_functions_sorted in
7212 pr "#include <config.h>\n";
7214 pr "#include <stdio.h>\n";
7215 pr "#include <stdlib.h>\n";
7216 pr "#include <string.h>\n";
7217 pr "#include <inttypes.h>\n";
7219 pr "#include <guestfs.h>\n";
7220 pr "#include \"c-ctype.h\"\n";
7221 pr "#include \"full-write.h\"\n";
7222 pr "#include \"xstrtol.h\"\n";
7223 pr "#include \"fish.h\"\n";
7226 (* list_commands function, which implements guestfish -h *)
7227 pr "void list_commands (void)\n";
7229 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7230 pr " list_builtin_commands ();\n";
7232 fun (name, _, _, flags, _, shortdesc, _) ->
7233 let name = replace_char name '_' '-' in
7234 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7236 ) all_functions_sorted;
7237 pr " printf (\" %%s\\n\",";
7238 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7242 (* display_command function, which implements guestfish -h cmd *)
7243 pr "void display_command (const char *cmd)\n";
7246 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7247 let name2 = replace_char name '_' '-' in
7249 try find_map (function FishAlias n -> Some n | _ -> None) flags
7250 with Not_found -> name in
7251 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7253 match snd style with
7257 name2 (String.concat " " (List.map name_of_argt args)) in
7260 if List.mem ProtocolLimitWarning flags then
7261 ("\n\n" ^ protocol_limit_warning)
7264 (* For DangerWillRobinson commands, we should probably have
7265 * guestfish prompt before allowing you to use them (especially
7266 * in interactive mode). XXX
7270 if List.mem DangerWillRobinson flags then
7271 ("\n\n" ^ danger_will_robinson)
7276 match deprecation_notice flags with
7278 | Some txt -> "\n\n" ^ txt in
7280 let describe_alias =
7281 if name <> alias then
7282 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7286 pr "STRCASEEQ (cmd, \"%s\")" name;
7287 if name <> name2 then
7288 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7289 if name <> alias then
7290 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7292 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7294 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7295 "=head1 DESCRIPTION\n\n" ^
7296 longdesc ^ warnings ^ describe_alias);
7299 pr " display_builtin_command (cmd);\n";
7303 let emit_print_list_function typ =
7304 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7307 pr " unsigned int i;\n";
7309 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7310 pr " printf (\"[%%d] = {\\n\", i);\n";
7311 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7312 pr " printf (\"}\\n\");\n";
7318 (* print_* functions *)
7322 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7324 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7327 pr " unsigned int i;\n";
7333 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7335 pr " printf (\"%%s%s: \", indent);\n" name;
7336 pr " for (i = 0; i < 32; ++i)\n";
7337 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7338 pr " printf (\"\\n\");\n"
7340 pr " printf (\"%%s%s: \", indent);\n" name;
7341 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7342 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7343 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7345 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7346 pr " printf (\"\\n\");\n"
7347 | name, (FUInt64|FBytes) ->
7348 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7351 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7354 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7357 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7360 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7362 | name, FOptPercent ->
7363 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7364 typ name name typ name;
7365 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7371 (* Emit a print_TYPE_list function definition only if that function is used. *)
7374 | typ, (RStructListOnly | RStructAndList) ->
7375 (* generate the function for typ *)
7376 emit_print_list_function typ
7377 | typ, _ -> () (* empty *)
7378 ) (rstructs_used_by all_functions);
7380 (* Emit a print_TYPE function definition only if that function is used. *)
7383 | typ, (RStructOnly | RStructAndList) ->
7384 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7386 pr " print_%s_indent (%s, \"\");\n" typ typ;
7389 | typ, _ -> () (* empty *)
7390 ) (rstructs_used_by all_functions);
7392 (* run_<action> actions *)
7394 fun (name, style, _, flags, _, _, _) ->
7395 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7397 (match fst style with
7400 | RBool _ -> pr " int r;\n"
7401 | RInt64 _ -> pr " int64_t r;\n"
7402 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7403 | RString _ -> pr " char *r;\n"
7404 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7405 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7406 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7409 pr " size_t size;\n";
7415 | OptString n -> pr " const char *%s;\n" n
7419 | FileOut n -> pr " char *%s;\n" n
7420 | StringList n | DeviceList n -> pr " char **%s;\n" n
7421 | Bool n -> pr " int %s;\n" n
7422 | Int n -> pr " int %s;\n" n
7423 | Int64 n -> pr " int64_t %s;\n" n
7426 (* Check and convert parameters. *)
7427 let argc_expected = List.length (snd style) in
7428 pr " if (argc != %d) {\n" argc_expected;
7429 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7431 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7435 let parse_integer fn fntyp rtyp range name i =
7437 pr " strtol_error xerr;\n";
7438 pr " %s r;\n" fntyp;
7440 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7441 pr " if (xerr != LONGINT_OK) {\n";
7442 pr " fprintf (stderr,\n";
7443 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7444 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7449 | Some (min, max, comment) ->
7450 pr " /* %s */\n" comment;
7451 pr " if (r < %s || r > %s) {\n" min max;
7452 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7456 pr " /* The check above should ensure this assignment does not overflow. */\n";
7458 pr " %s = r;\n" name;
7467 pr " %s = argv[%d];\n" name i
7469 | Dev_or_Path name ->
7470 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7471 pr " if (%s == NULL) return -1;\n" name
7473 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7476 pr " %s = file_in (argv[%d]);\n" name i;
7477 pr " if (%s == NULL) return -1;\n" name
7479 pr " %s = file_out (argv[%d]);\n" name i;
7480 pr " if (%s == NULL) return -1;\n" name
7481 | StringList name | DeviceList name ->
7482 pr " %s = parse_string_list (argv[%d]);\n" name i;
7483 pr " if (%s == NULL) return -1;\n" name;
7485 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7488 let min = "(-(2LL<<30))"
7489 and max = "((2LL<<30)-1)"
7491 "The Int type in the generator is a signed 31 bit int." in
7492 Some (min, max, comment) in
7493 parse_integer "xstrtoll" "long long" "int" range name i
7495 parse_integer "xstrtoll" "long long" "int64_t" None name i
7498 (* Call C API function. *)
7500 try find_map (function FishAction n -> Some n | _ -> None) flags
7501 with Not_found -> sprintf "guestfs_%s" name in
7503 generate_c_call_args ~handle:"g" style;
7508 | Device name | String name
7509 | OptString name | Bool name
7510 | Int name | Int64 name -> ()
7511 | Pathname name | Dev_or_Path name | FileOut name ->
7512 pr " free (%s);\n" name
7514 pr " free_file_in (%s);\n" name
7515 | StringList name | DeviceList name ->
7516 pr " free_strings (%s);\n" name
7519 (* Any output flags? *)
7521 let flags = filter_map (
7522 function FishOutput flag -> Some flag | _ -> None
7528 failwithf "%s: more than one FishOutput flag is not allowed" name in
7530 (* Check return value for errors and display command results. *)
7531 (match fst style with
7532 | RErr -> pr " return r;\n"
7534 pr " if (r == -1) return -1;\n";
7535 (match fish_output with
7537 pr " printf (\"%%d\\n\", r);\n";
7538 | Some FishOutputOctal ->
7539 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7540 | Some FishOutputHexadecimal ->
7541 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7544 pr " if (r == -1) return -1;\n";
7545 (match fish_output with
7547 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7548 | Some FishOutputOctal ->
7549 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7550 | Some FishOutputHexadecimal ->
7551 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7554 pr " if (r == -1) return -1;\n";
7555 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7558 pr " if (r == NULL) return -1;\n";
7559 pr " printf (\"%%s\\n\", r);\n";
7561 | RConstOptString _ ->
7562 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7565 pr " if (r == NULL) return -1;\n";
7566 pr " printf (\"%%s\\n\", r);\n";
7570 pr " if (r == NULL) return -1;\n";
7571 pr " print_strings (r);\n";
7572 pr " free_strings (r);\n";
7574 | RStruct (_, typ) ->
7575 pr " if (r == NULL) return -1;\n";
7576 pr " print_%s (r);\n" typ;
7577 pr " guestfs_free_%s (r);\n" typ;
7579 | RStructList (_, typ) ->
7580 pr " if (r == NULL) return -1;\n";
7581 pr " print_%s_list (r);\n" typ;
7582 pr " guestfs_free_%s_list (r);\n" typ;
7585 pr " if (r == NULL) return -1;\n";
7586 pr " print_table (r);\n";
7587 pr " free_strings (r);\n";
7590 pr " if (r == NULL) return -1;\n";
7591 pr " if (full_write (1, r, size) != size) {\n";
7592 pr " perror (\"write\");\n";
7603 (* run_action function *)
7604 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7607 fun (name, _, _, flags, _, _, _) ->
7608 let name2 = replace_char name '_' '-' in
7610 try find_map (function FishAlias n -> Some n | _ -> None) flags
7611 with Not_found -> name in
7613 pr "STRCASEEQ (cmd, \"%s\")" name;
7614 if name <> name2 then
7615 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7616 if name <> alias then
7617 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7619 pr " return run_%s (cmd, argc, argv);\n" name;
7623 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7624 pr " if (command_num == 1)\n";
7625 pr " extended_help_message ();\n";
7632 (* Readline completion for guestfish. *)
7633 and generate_fish_completion () =
7634 generate_header CStyle GPLv2plus;
7638 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7648 #ifdef HAVE_LIBREADLINE
7649 #include <readline/readline.h>
7654 #ifdef HAVE_LIBREADLINE
7656 static const char *const commands[] = {
7657 BUILTIN_COMMANDS_FOR_COMPLETION,
7660 (* Get the commands, including the aliases. They don't need to be
7661 * sorted - the generator() function just does a dumb linear search.
7665 fun (name, _, _, flags, _, _, _) ->
7666 let name2 = replace_char name '_' '-' in
7668 try find_map (function FishAlias n -> Some n | _ -> None) flags
7669 with Not_found -> name in
7671 if name <> alias then [name2; alias] else [name2]
7673 let commands = List.flatten commands in
7675 List.iter (pr " \"%s\",\n") commands;
7681 generator (const char *text, int state)
7683 static int index, len;
7688 len = strlen (text);
7691 rl_attempted_completion_over = 1;
7693 while ((name = commands[index]) != NULL) {
7695 if (STRCASEEQLEN (name, text, len))
7696 return strdup (name);
7702 #endif /* HAVE_LIBREADLINE */
7704 #ifdef HAVE_RL_COMPLETION_MATCHES
7705 #define RL_COMPLETION_MATCHES rl_completion_matches
7707 #ifdef HAVE_COMPLETION_MATCHES
7708 #define RL_COMPLETION_MATCHES completion_matches
7710 #endif /* else just fail if we don't have either symbol */
7713 do_completion (const char *text, int start, int end)
7715 char **matches = NULL;
7717 #ifdef HAVE_LIBREADLINE
7718 rl_completion_append_character = ' ';
7721 matches = RL_COMPLETION_MATCHES (text, generator);
7722 else if (complete_dest_paths)
7723 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7730 (* Generate the POD documentation for guestfish. *)
7731 and generate_fish_actions_pod () =
7732 let all_functions_sorted =
7734 fun (_, _, _, flags, _, _, _) ->
7735 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7736 ) all_functions_sorted in
7738 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7741 fun (name, style, _, flags, _, _, longdesc) ->
7743 Str.global_substitute rex (
7746 try Str.matched_group 1 s
7748 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7749 "C<" ^ replace_char sub '_' '-' ^ ">"
7751 let name = replace_char name '_' '-' in
7753 try find_map (function FishAlias n -> Some n | _ -> None) flags
7754 with Not_found -> name in
7756 pr "=head2 %s" name;
7757 if name <> alias then
7764 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7765 | OptString n -> pr " %s" n
7766 | StringList n | DeviceList n -> pr " '%s ...'" n
7767 | Bool _ -> pr " true|false"
7768 | Int n -> pr " %s" n
7769 | Int64 n -> pr " %s" n
7770 | FileIn n | FileOut n -> pr " (%s|-)" n
7774 pr "%s\n\n" longdesc;
7776 if List.exists (function FileIn _ | FileOut _ -> true
7777 | _ -> false) (snd style) then
7778 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7780 if List.mem ProtocolLimitWarning flags then
7781 pr "%s\n\n" protocol_limit_warning;
7783 if List.mem DangerWillRobinson flags then
7784 pr "%s\n\n" danger_will_robinson;
7786 match deprecation_notice flags with
7788 | Some txt -> pr "%s\n\n" txt
7789 ) all_functions_sorted
7791 (* Generate a C function prototype. *)
7792 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7793 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7795 ?handle name style =
7796 if extern then pr "extern ";
7797 if static then pr "static ";
7798 (match fst style with
7800 | RInt _ -> pr "int "
7801 | RInt64 _ -> pr "int64_t "
7802 | RBool _ -> pr "int "
7803 | RConstString _ | RConstOptString _ -> pr "const char *"
7804 | RString _ | RBufferOut _ -> pr "char *"
7805 | RStringList _ | RHashtable _ -> pr "char **"
7806 | RStruct (_, typ) ->
7807 if not in_daemon then pr "struct guestfs_%s *" typ
7808 else pr "guestfs_int_%s *" typ
7809 | RStructList (_, typ) ->
7810 if not in_daemon then pr "struct guestfs_%s_list *" typ
7811 else pr "guestfs_int_%s_list *" typ
7813 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7814 pr "%s%s (" prefix name;
7815 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7818 let comma = ref false in
7821 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7825 if single_line then pr ", " else pr ",\n\t\t"
7832 | Device n | Dev_or_Path n
7836 pr "const char *%s" n
7837 | StringList n | DeviceList n ->
7839 pr "char *const *%s" n
7840 | Bool n -> next (); pr "int %s" n
7841 | Int n -> next (); pr "int %s" n
7842 | Int64 n -> next (); pr "int64_t %s" n
7845 if not in_daemon then (next (); pr "const char *%s" n)
7847 if is_RBufferOut then (next (); pr "size_t *size_r");
7850 if semicolon then pr ";";
7851 if newline then pr "\n"
7853 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7854 and generate_c_call_args ?handle ?(decl = false) style =
7856 let comma = ref false in
7858 if !comma then pr ", ";
7863 | Some handle -> pr "%s" handle; comma := true
7868 pr "%s" (name_of_argt arg)
7870 (* For RBufferOut calls, add implicit &size parameter. *)
7872 match fst style with
7880 (* Generate the OCaml bindings interface. *)
7881 and generate_ocaml_mli () =
7882 generate_header OCamlStyle LGPLv2plus;
7885 (** For API documentation you should refer to the C API
7886 in the guestfs(3) manual page. The OCaml API uses almost
7887 exactly the same calls. *)
7890 (** A [guestfs_h] handle. *)
7892 exception Error of string
7893 (** This exception is raised when there is an error. *)
7895 exception Handle_closed of string
7896 (** This exception is raised if you use a {!Guestfs.t} handle
7897 after calling {!close} on it. The string is the name of
7900 val create : unit -> t
7901 (** Create a {!Guestfs.t} handle. *)
7903 val close : t -> unit
7904 (** Close the {!Guestfs.t} handle and free up all resources used
7907 Handles are closed by the garbage collector when they become
7908 unreferenced, but callers can call this in order to provide
7909 predictable cleanup. *)
7912 generate_ocaml_structure_decls ();
7916 fun (name, style, _, _, _, shortdesc, _) ->
7917 generate_ocaml_prototype name style;
7918 pr "(** %s *)\n" shortdesc;
7920 ) all_functions_sorted
7922 (* Generate the OCaml bindings implementation. *)
7923 and generate_ocaml_ml () =
7924 generate_header OCamlStyle LGPLv2plus;
7929 exception Error of string
7930 exception Handle_closed of string
7932 external create : unit -> t = \"ocaml_guestfs_create\"
7933 external close : t -> unit = \"ocaml_guestfs_close\"
7935 (* Give the exceptions names, so they can be raised from the C code. *)
7937 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7938 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7942 generate_ocaml_structure_decls ();
7946 fun (name, style, _, _, _, shortdesc, _) ->
7947 generate_ocaml_prototype ~is_external:true name style;
7948 ) all_functions_sorted
7950 (* Generate the OCaml bindings C implementation. *)
7951 and generate_ocaml_c () =
7952 generate_header CStyle LGPLv2plus;
7959 #include <caml/config.h>
7960 #include <caml/alloc.h>
7961 #include <caml/callback.h>
7962 #include <caml/fail.h>
7963 #include <caml/memory.h>
7964 #include <caml/mlvalues.h>
7965 #include <caml/signals.h>
7967 #include <guestfs.h>
7969 #include \"guestfs_c.h\"
7971 /* Copy a hashtable of string pairs into an assoc-list. We return
7972 * the list in reverse order, but hashtables aren't supposed to be
7975 static CAMLprim value
7976 copy_table (char * const * argv)
7979 CAMLlocal5 (rv, pairv, kv, vv, cons);
7983 for (i = 0; argv[i] != NULL; i += 2) {
7984 kv = caml_copy_string (argv[i]);
7985 vv = caml_copy_string (argv[i+1]);
7986 pairv = caml_alloc (2, 0);
7987 Store_field (pairv, 0, kv);
7988 Store_field (pairv, 1, vv);
7989 cons = caml_alloc (2, 0);
7990 Store_field (cons, 1, rv);
7992 Store_field (cons, 0, pairv);
8000 (* Struct copy functions. *)
8002 let emit_ocaml_copy_list_function typ =
8003 pr "static CAMLprim value\n";
8004 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8006 pr " CAMLparam0 ();\n";
8007 pr " CAMLlocal2 (rv, v);\n";
8008 pr " unsigned int i;\n";
8010 pr " if (%ss->len == 0)\n" typ;
8011 pr " CAMLreturn (Atom (0));\n";
8013 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8014 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8015 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8016 pr " caml_modify (&Field (rv, i), v);\n";
8018 pr " CAMLreturn (rv);\n";
8026 let has_optpercent_col =
8027 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8029 pr "static CAMLprim value\n";
8030 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8032 pr " CAMLparam0 ();\n";
8033 if has_optpercent_col then
8034 pr " CAMLlocal3 (rv, v, v2);\n"
8036 pr " CAMLlocal2 (rv, v);\n";
8038 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8043 pr " v = caml_copy_string (%s->%s);\n" typ name
8045 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8046 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8049 pr " v = caml_alloc_string (32);\n";
8050 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8051 | name, (FBytes|FInt64|FUInt64) ->
8052 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8053 | name, (FInt32|FUInt32) ->
8054 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8055 | name, FOptPercent ->
8056 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8057 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8058 pr " v = caml_alloc (1, 0);\n";
8059 pr " Store_field (v, 0, v2);\n";
8060 pr " } else /* None */\n";
8061 pr " v = Val_int (0);\n";
8063 pr " v = Val_int (%s->%s);\n" typ name
8065 pr " Store_field (rv, %d, v);\n" i
8067 pr " CAMLreturn (rv);\n";
8072 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8075 | typ, (RStructListOnly | RStructAndList) ->
8076 (* generate the function for typ *)
8077 emit_ocaml_copy_list_function typ
8078 | typ, _ -> () (* empty *)
8079 ) (rstructs_used_by all_functions);
8083 fun (name, style, _, _, _, _, _) ->
8084 pr "/* Automatically generated wrapper for function\n";
8086 generate_ocaml_prototype name style;
8091 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8093 let needs_extra_vs =
8094 match fst style with RConstOptString _ -> true | _ -> false in
8096 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8097 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8098 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8101 pr "CAMLprim value\n";
8102 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8103 List.iter (pr ", value %s") (List.tl params);
8108 | [p1; p2; p3; p4; p5] ->
8109 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8110 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8111 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8112 pr " CAMLxparam%d (%s);\n"
8113 (List.length rest) (String.concat ", " rest)
8115 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8117 if not needs_extra_vs then
8118 pr " CAMLlocal1 (rv);\n"
8120 pr " CAMLlocal3 (rv, v, v2);\n";
8123 pr " guestfs_h *g = Guestfs_val (gv);\n";
8124 pr " if (g == NULL)\n";
8125 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8131 | Device n | Dev_or_Path n
8135 pr " const char *%s = String_val (%sv);\n" n n
8137 pr " const char *%s =\n" n;
8138 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8140 | StringList n | DeviceList n ->
8141 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8143 pr " int %s = Bool_val (%sv);\n" n n
8145 pr " int %s = Int_val (%sv);\n" n n
8147 pr " int64_t %s = Int64_val (%sv);\n" n n
8150 match fst style with
8151 | RErr -> pr " int r;\n"; "-1"
8152 | RInt _ -> pr " int r;\n"; "-1"
8153 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8154 | RBool _ -> pr " int r;\n"; "-1"
8155 | RConstString _ | RConstOptString _ ->
8156 pr " const char *r;\n"; "NULL"
8157 | RString _ -> pr " char *r;\n"; "NULL"
8162 | RStruct (_, typ) ->
8163 pr " struct guestfs_%s *r;\n" typ; "NULL"
8164 | RStructList (_, typ) ->
8165 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8172 pr " size_t size;\n";
8176 pr " caml_enter_blocking_section ();\n";
8177 pr " r = guestfs_%s " name;
8178 generate_c_call_args ~handle:"g" style;
8180 pr " caml_leave_blocking_section ();\n";
8184 | StringList n | DeviceList n ->
8185 pr " ocaml_guestfs_free_strings (%s);\n" n;
8186 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8187 | Bool _ | Int _ | Int64 _
8188 | FileIn _ | FileOut _ -> ()
8191 pr " if (r == %s)\n" error_code;
8192 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8195 (match fst style with
8196 | RErr -> pr " rv = Val_unit;\n"
8197 | RInt _ -> pr " rv = Val_int (r);\n"
8199 pr " rv = caml_copy_int64 (r);\n"
8200 | RBool _ -> pr " rv = Val_bool (r);\n"
8202 pr " rv = caml_copy_string (r);\n"
8203 | RConstOptString _ ->
8204 pr " if (r) { /* Some string */\n";
8205 pr " v = caml_alloc (1, 0);\n";
8206 pr " v2 = caml_copy_string (r);\n";
8207 pr " Store_field (v, 0, v2);\n";
8208 pr " } else /* None */\n";
8209 pr " v = Val_int (0);\n";
8211 pr " rv = caml_copy_string (r);\n";
8214 pr " rv = caml_copy_string_array ((const char **) r);\n";
8215 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8217 | RStruct (_, typ) ->
8218 pr " rv = copy_%s (r);\n" typ;
8219 pr " guestfs_free_%s (r);\n" typ;
8220 | RStructList (_, typ) ->
8221 pr " rv = copy_%s_list (r);\n" typ;
8222 pr " guestfs_free_%s_list (r);\n" typ;
8224 pr " rv = copy_table (r);\n";
8225 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8228 pr " rv = caml_alloc_string (size);\n";
8229 pr " memcpy (String_val (rv), r, size);\n";
8232 pr " CAMLreturn (rv);\n";
8236 if List.length params > 5 then (
8237 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8238 pr "CAMLprim value ";
8239 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8240 pr "CAMLprim value\n";
8241 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8243 pr " return ocaml_guestfs_%s (argv[0]" name;
8244 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8249 ) all_functions_sorted
8251 and generate_ocaml_structure_decls () =
8254 pr "type %s = {\n" typ;
8257 | name, FString -> pr " %s : string;\n" name
8258 | name, FBuffer -> pr " %s : string;\n" name
8259 | name, FUUID -> pr " %s : string;\n" name
8260 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8261 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8262 | name, FChar -> pr " %s : char;\n" name
8263 | name, FOptPercent -> pr " %s : float option;\n" name
8269 and generate_ocaml_prototype ?(is_external = false) name style =
8270 if is_external then pr "external " else pr "val ";
8271 pr "%s : t -> " name;
8274 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8275 | OptString _ -> pr "string option -> "
8276 | StringList _ | DeviceList _ -> pr "string array -> "
8277 | Bool _ -> pr "bool -> "
8278 | Int _ -> pr "int -> "
8279 | Int64 _ -> pr "int64 -> "
8281 (match fst style with
8282 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8283 | RInt _ -> pr "int"
8284 | RInt64 _ -> pr "int64"
8285 | RBool _ -> pr "bool"
8286 | RConstString _ -> pr "string"
8287 | RConstOptString _ -> pr "string option"
8288 | RString _ | RBufferOut _ -> pr "string"
8289 | RStringList _ -> pr "string array"
8290 | RStruct (_, typ) -> pr "%s" typ
8291 | RStructList (_, typ) -> pr "%s array" typ
8292 | RHashtable _ -> pr "(string * string) list"
8294 if is_external then (
8296 if List.length (snd style) + 1 > 5 then
8297 pr "\"ocaml_guestfs_%s_byte\" " name;
8298 pr "\"ocaml_guestfs_%s\"" name
8302 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8303 and generate_perl_xs () =
8304 generate_header CStyle LGPLv2plus;
8307 #include \"EXTERN.h\"
8311 #include <guestfs.h>
8314 #define PRId64 \"lld\"
8318 my_newSVll(long long val) {
8319 #ifdef USE_64_BIT_ALL
8320 return newSViv(val);
8324 len = snprintf(buf, 100, \"%%\" PRId64, val);
8325 return newSVpv(buf, len);
8330 #define PRIu64 \"llu\"
8334 my_newSVull(unsigned long long val) {
8335 #ifdef USE_64_BIT_ALL
8336 return newSVuv(val);
8340 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8341 return newSVpv(buf, len);
8345 /* http://www.perlmonks.org/?node_id=680842 */
8347 XS_unpack_charPtrPtr (SV *arg) {
8352 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8353 croak (\"array reference expected\");
8355 av = (AV *)SvRV (arg);
8356 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8358 croak (\"malloc failed\");
8360 for (i = 0; i <= av_len (av); i++) {
8361 SV **elem = av_fetch (av, i, 0);
8363 if (!elem || !*elem)
8364 croak (\"missing element in list\");
8366 ret[i] = SvPV_nolen (*elem);
8374 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8381 RETVAL = guestfs_create ();
8383 croak (\"could not create guestfs handle\");
8384 guestfs_set_error_handler (RETVAL, NULL, NULL);
8397 fun (name, style, _, _, _, _, _) ->
8398 (match fst style with
8399 | RErr -> pr "void\n"
8400 | RInt _ -> pr "SV *\n"
8401 | RInt64 _ -> pr "SV *\n"
8402 | RBool _ -> pr "SV *\n"
8403 | RConstString _ -> pr "SV *\n"
8404 | RConstOptString _ -> pr "SV *\n"
8405 | RString _ -> pr "SV *\n"
8406 | RBufferOut _ -> pr "SV *\n"
8408 | RStruct _ | RStructList _
8410 pr "void\n" (* all lists returned implictly on the stack *)
8412 (* Call and arguments. *)
8414 generate_c_call_args ~handle:"g" ~decl:true style;
8416 pr " guestfs_h *g;\n";
8420 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8423 (* http://www.perlmonks.org/?node_id=554277
8424 * Note that the implicit handle argument means we have
8425 * to add 1 to the ST(x) operator.
8427 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8428 | StringList n | DeviceList n -> pr " char **%s;\n" n
8429 | Bool n -> pr " int %s;\n" n
8430 | Int n -> pr " int %s;\n" n
8431 | Int64 n -> pr " int64_t %s;\n" n
8434 let do_cleanups () =
8437 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8438 | Bool _ | Int _ | Int64 _
8439 | FileIn _ | FileOut _ -> ()
8440 | StringList n | DeviceList n -> pr " free (%s);\n" n
8445 (match fst style with
8450 pr " r = guestfs_%s " name;
8451 generate_c_call_args ~handle:"g" style;
8454 pr " if (r == -1)\n";
8455 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8461 pr " %s = guestfs_%s " n name;
8462 generate_c_call_args ~handle:"g" style;
8465 pr " if (%s == -1)\n" n;
8466 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8467 pr " RETVAL = newSViv (%s);\n" n;
8472 pr " int64_t %s;\n" n;
8474 pr " %s = guestfs_%s " n name;
8475 generate_c_call_args ~handle:"g" style;
8478 pr " if (%s == -1)\n" n;
8479 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8480 pr " RETVAL = my_newSVll (%s);\n" n;
8485 pr " const char *%s;\n" n;
8487 pr " %s = guestfs_%s " n name;
8488 generate_c_call_args ~handle:"g" style;
8491 pr " if (%s == NULL)\n" n;
8492 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8493 pr " RETVAL = newSVpv (%s, 0);\n" n;
8496 | RConstOptString n ->
8498 pr " const char *%s;\n" n;
8500 pr " %s = guestfs_%s " n name;
8501 generate_c_call_args ~handle:"g" style;
8504 pr " if (%s == NULL)\n" n;
8505 pr " RETVAL = &PL_sv_undef;\n";
8507 pr " RETVAL = newSVpv (%s, 0);\n" n;
8512 pr " char *%s;\n" n;
8514 pr " %s = guestfs_%s " n name;
8515 generate_c_call_args ~handle:"g" style;
8518 pr " if (%s == NULL)\n" n;
8519 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8520 pr " RETVAL = newSVpv (%s, 0);\n" n;
8521 pr " free (%s);\n" n;
8524 | RStringList n | RHashtable n ->
8526 pr " char **%s;\n" n;
8529 pr " %s = guestfs_%s " n name;
8530 generate_c_call_args ~handle:"g" style;
8533 pr " if (%s == NULL)\n" n;
8534 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8535 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8536 pr " EXTEND (SP, n);\n";
8537 pr " for (i = 0; i < n; ++i) {\n";
8538 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8539 pr " free (%s[i]);\n" n;
8541 pr " free (%s);\n" n;
8542 | RStruct (n, typ) ->
8543 let cols = cols_of_struct typ in
8544 generate_perl_struct_code typ cols name style n do_cleanups
8545 | RStructList (n, typ) ->
8546 let cols = cols_of_struct typ in
8547 generate_perl_struct_list_code typ cols name style n do_cleanups
8550 pr " char *%s;\n" n;
8551 pr " size_t size;\n";
8553 pr " %s = guestfs_%s " n name;
8554 generate_c_call_args ~handle:"g" style;
8557 pr " if (%s == NULL)\n" n;
8558 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8559 pr " RETVAL = newSVpvn (%s, size);\n" n;
8560 pr " free (%s);\n" n;
8568 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8570 pr " struct guestfs_%s_list *%s;\n" typ n;
8574 pr " %s = guestfs_%s " n name;
8575 generate_c_call_args ~handle:"g" style;
8578 pr " if (%s == NULL)\n" n;
8579 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8580 pr " EXTEND (SP, %s->len);\n" n;
8581 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8582 pr " hv = newHV ();\n";
8586 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8587 name (String.length name) n name
8589 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8590 name (String.length name) n name
8592 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8593 name (String.length name) n name n name
8594 | name, (FBytes|FUInt64) ->
8595 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8596 name (String.length name) n name
8598 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8599 name (String.length name) n name
8600 | name, (FInt32|FUInt32) ->
8601 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8602 name (String.length name) n name
8604 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8605 name (String.length name) n name
8606 | name, FOptPercent ->
8607 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8608 name (String.length name) n name
8610 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8612 pr " guestfs_free_%s_list (%s);\n" typ n
8614 and generate_perl_struct_code typ cols name style n do_cleanups =
8616 pr " struct guestfs_%s *%s;\n" typ n;
8618 pr " %s = guestfs_%s " n name;
8619 generate_c_call_args ~handle:"g" style;
8622 pr " if (%s == NULL)\n" n;
8623 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8624 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8626 fun ((name, _) as col) ->
8627 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8631 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8634 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8637 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8639 | name, (FBytes|FUInt64) ->
8640 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8643 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8645 | name, (FInt32|FUInt32) ->
8646 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8649 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8651 | name, FOptPercent ->
8652 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8655 pr " free (%s);\n" n
8657 (* Generate Sys/Guestfs.pm. *)
8658 and generate_perl_pm () =
8659 generate_header HashStyle LGPLv2plus;
8666 Sys::Guestfs - Perl bindings for libguestfs
8672 my $h = Sys::Guestfs->new ();
8673 $h->add_drive ('guest.img');
8675 $h->mount ('/dev/sda1', '/');
8676 $h->touch ('/hello');
8681 The C<Sys::Guestfs> module provides a Perl XS binding to the
8682 libguestfs API for examining and modifying virtual machine
8685 Amongst the things this is good for: making batch configuration
8686 changes to guests, getting disk used/free statistics (see also:
8687 virt-df), migrating between virtualization systems (see also:
8688 virt-p2v), performing partial backups, performing partial guest
8689 clones, cloning guests and changing registry/UUID/hostname info, and
8692 Libguestfs uses Linux kernel and qemu code, and can access any type of
8693 guest filesystem that Linux and qemu can, including but not limited
8694 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8695 schemes, qcow, qcow2, vmdk.
8697 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8698 LVs, what filesystem is in each LV, etc.). It can also run commands
8699 in the context of the guest. Also you can access filesystems over
8702 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8703 functions for using libguestfs from Perl, including integration
8708 All errors turn into calls to C<croak> (see L<Carp(3)>).
8716 package Sys::Guestfs;
8722 XSLoader::load ('Sys::Guestfs');
8724 =item $h = Sys::Guestfs->new ();
8726 Create a new guestfs handle.
8732 my $class = ref ($proto) || $proto;
8734 my $self = Sys::Guestfs::_create ();
8735 bless $self, $class;
8741 (* Actions. We only need to print documentation for these as
8742 * they are pulled in from the XS code automatically.
8745 fun (name, style, _, flags, _, _, longdesc) ->
8746 if not (List.mem NotInDocs flags) then (
8747 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8749 generate_perl_prototype name style;
8751 pr "%s\n\n" longdesc;
8752 if List.mem ProtocolLimitWarning flags then
8753 pr "%s\n\n" protocol_limit_warning;
8754 if List.mem DangerWillRobinson flags then
8755 pr "%s\n\n" danger_will_robinson;
8756 match deprecation_notice flags with
8758 | Some txt -> pr "%s\n\n" txt
8760 ) all_functions_sorted;
8772 Copyright (C) %s Red Hat Inc.
8776 Please see the file COPYING.LIB for the full license.
8782 L<http://libguestfs.org>,
8783 L<Sys::Guestfs::Lib(3)>.
8788 and generate_perl_prototype name style =
8789 (match fst style with
8797 | RBufferOut n -> pr "$%s = " n
8799 | RHashtable n -> pr "%%%s = " n
8801 | RStructList (n,_) -> pr "@%s = " n
8804 let comma = ref false in
8807 if !comma then pr ", ";
8810 | Pathname n | Device n | Dev_or_Path n | String n
8811 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8813 | StringList n | DeviceList n ->
8818 (* Generate Python C module. *)
8819 and generate_python_c () =
8820 generate_header CStyle LGPLv2plus;
8829 #include \"guestfs.h\"
8837 get_handle (PyObject *obj)
8840 assert (obj != Py_None);
8841 return ((Pyguestfs_Object *) obj)->g;
8845 put_handle (guestfs_h *g)
8849 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8852 /* This list should be freed (but not the strings) after use. */
8854 get_string_list (PyObject *obj)
8861 if (!PyList_Check (obj)) {
8862 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8866 len = PyList_Size (obj);
8867 r = malloc (sizeof (char *) * (len+1));
8869 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8873 for (i = 0; i < len; ++i)
8874 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8881 put_string_list (char * const * const argv)
8886 for (argc = 0; argv[argc] != NULL; ++argc)
8889 list = PyList_New (argc);
8890 for (i = 0; i < argc; ++i)
8891 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8897 put_table (char * const * const argv)
8899 PyObject *list, *item;
8902 for (argc = 0; argv[argc] != NULL; ++argc)
8905 list = PyList_New (argc >> 1);
8906 for (i = 0; i < argc; i += 2) {
8907 item = PyTuple_New (2);
8908 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8909 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8910 PyList_SetItem (list, i >> 1, item);
8917 free_strings (char **argv)
8921 for (argc = 0; argv[argc] != NULL; ++argc)
8927 py_guestfs_create (PyObject *self, PyObject *args)
8931 g = guestfs_create ();
8933 PyErr_SetString (PyExc_RuntimeError,
8934 \"guestfs.create: failed to allocate handle\");
8937 guestfs_set_error_handler (g, NULL, NULL);
8938 return put_handle (g);
8942 py_guestfs_close (PyObject *self, PyObject *args)
8947 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8949 g = get_handle (py_g);
8953 Py_INCREF (Py_None);
8959 let emit_put_list_function typ =
8960 pr "static PyObject *\n";
8961 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8963 pr " PyObject *list;\n";
8966 pr " list = PyList_New (%ss->len);\n" typ;
8967 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8968 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8969 pr " return list;\n";
8974 (* Structures, turned into Python dictionaries. *)
8977 pr "static PyObject *\n";
8978 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8980 pr " PyObject *dict;\n";
8982 pr " dict = PyDict_New ();\n";
8986 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8987 pr " PyString_FromString (%s->%s));\n"
8990 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8991 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8994 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8995 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8997 | name, (FBytes|FUInt64) ->
8998 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8999 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9002 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9003 pr " PyLong_FromLongLong (%s->%s));\n"
9006 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9007 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9010 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9011 pr " PyLong_FromLong (%s->%s));\n"
9013 | name, FOptPercent ->
9014 pr " if (%s->%s >= 0)\n" typ name;
9015 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9016 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9019 pr " Py_INCREF (Py_None);\n";
9020 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9023 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9024 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9026 pr " return dict;\n";
9032 (* Emit a put_TYPE_list function definition only if that function is used. *)
9035 | typ, (RStructListOnly | RStructAndList) ->
9036 (* generate the function for typ *)
9037 emit_put_list_function typ
9038 | typ, _ -> () (* empty *)
9039 ) (rstructs_used_by all_functions);
9041 (* Python wrapper functions. *)
9043 fun (name, style, _, _, _, _, _) ->
9044 pr "static PyObject *\n";
9045 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9048 pr " PyObject *py_g;\n";
9049 pr " guestfs_h *g;\n";
9050 pr " PyObject *py_r;\n";
9053 match fst style with
9054 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9055 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9056 | RConstString _ | RConstOptString _ ->
9057 pr " const char *r;\n"; "NULL"
9058 | RString _ -> pr " char *r;\n"; "NULL"
9059 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9060 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9061 | RStructList (_, typ) ->
9062 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9065 pr " size_t size;\n";
9070 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9071 pr " const char *%s;\n" n
9072 | OptString n -> pr " const char *%s;\n" n
9073 | StringList n | DeviceList n ->
9074 pr " PyObject *py_%s;\n" n;
9075 pr " char **%s;\n" n
9076 | Bool n -> pr " int %s;\n" n
9077 | Int n -> pr " int %s;\n" n
9078 | Int64 n -> pr " long long %s;\n" n
9083 (* Convert the parameters. *)
9084 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9087 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9088 | OptString _ -> pr "z"
9089 | StringList _ | DeviceList _ -> pr "O"
9090 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9092 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9093 * emulate C's int/long/long long in Python?
9096 pr ":guestfs_%s\",\n" name;
9100 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9101 | OptString n -> pr ", &%s" n
9102 | StringList n | DeviceList n -> pr ", &py_%s" n
9103 | Bool n -> pr ", &%s" n
9104 | Int n -> pr ", &%s" n
9105 | Int64 n -> pr ", &%s" n
9109 pr " return NULL;\n";
9111 pr " g = get_handle (py_g);\n";
9114 | Pathname _ | Device _ | Dev_or_Path _ | String _
9115 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9116 | StringList n | DeviceList n ->
9117 pr " %s = get_string_list (py_%s);\n" n n;
9118 pr " if (!%s) return NULL;\n" n
9123 pr " r = guestfs_%s " name;
9124 generate_c_call_args ~handle:"g" style;
9129 | Pathname _ | Device _ | Dev_or_Path _ | String _
9130 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9131 | StringList n | DeviceList n ->
9132 pr " free (%s);\n" n
9135 pr " if (r == %s) {\n" error_code;
9136 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9137 pr " return NULL;\n";
9141 (match fst style with
9143 pr " Py_INCREF (Py_None);\n";
9144 pr " py_r = Py_None;\n"
9146 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9147 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9148 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9149 | RConstOptString _ ->
9151 pr " py_r = PyString_FromString (r);\n";
9153 pr " Py_INCREF (Py_None);\n";
9154 pr " py_r = Py_None;\n";
9157 pr " py_r = PyString_FromString (r);\n";
9160 pr " py_r = put_string_list (r);\n";
9161 pr " free_strings (r);\n"
9162 | RStruct (_, typ) ->
9163 pr " py_r = put_%s (r);\n" typ;
9164 pr " guestfs_free_%s (r);\n" typ
9165 | RStructList (_, typ) ->
9166 pr " py_r = put_%s_list (r);\n" typ;
9167 pr " guestfs_free_%s_list (r);\n" typ
9169 pr " py_r = put_table (r);\n";
9170 pr " free_strings (r);\n"
9172 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9176 pr " return py_r;\n";
9181 (* Table of functions. *)
9182 pr "static PyMethodDef methods[] = {\n";
9183 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9184 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9186 fun (name, _, _, _, _, _, _) ->
9187 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9190 pr " { NULL, NULL, 0, NULL }\n";
9194 (* Init function. *)
9197 initlibguestfsmod (void)
9199 static int initialized = 0;
9201 if (initialized) return;
9202 Py_InitModule ((char *) \"libguestfsmod\", methods);
9207 (* Generate Python module. *)
9208 and generate_python_py () =
9209 generate_header HashStyle LGPLv2plus;
9212 u\"\"\"Python bindings for libguestfs
9215 g = guestfs.GuestFS ()
9216 g.add_drive (\"guest.img\")
9218 parts = g.list_partitions ()
9220 The guestfs module provides a Python binding to the libguestfs API
9221 for examining and modifying virtual machine disk images.
9223 Amongst the things this is good for: making batch configuration
9224 changes to guests, getting disk used/free statistics (see also:
9225 virt-df), migrating between virtualization systems (see also:
9226 virt-p2v), performing partial backups, performing partial guest
9227 clones, cloning guests and changing registry/UUID/hostname info, and
9230 Libguestfs uses Linux kernel and qemu code, and can access any type of
9231 guest filesystem that Linux and qemu can, including but not limited
9232 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9233 schemes, qcow, qcow2, vmdk.
9235 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9236 LVs, what filesystem is in each LV, etc.). It can also run commands
9237 in the context of the guest. Also you can access filesystems over
9240 Errors which happen while using the API are turned into Python
9241 RuntimeError exceptions.
9243 To create a guestfs handle you usually have to perform the following
9246 # Create the handle, call add_drive at least once, and possibly
9247 # several times if the guest has multiple block devices:
9248 g = guestfs.GuestFS ()
9249 g.add_drive (\"guest.img\")
9251 # Launch the qemu subprocess and wait for it to become ready:
9254 # Now you can issue commands, for example:
9259 import libguestfsmod
9262 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9264 def __init__ (self):
9265 \"\"\"Create a new libguestfs handle.\"\"\"
9266 self._o = libguestfsmod.create ()
9269 libguestfsmod.close (self._o)
9274 fun (name, style, _, flags, _, _, longdesc) ->
9276 generate_py_call_args ~handle:"self" (snd style);
9279 if not (List.mem NotInDocs flags) then (
9280 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9282 match fst style with
9283 | RErr | RInt _ | RInt64 _ | RBool _
9284 | RConstOptString _ | RConstString _
9285 | RString _ | RBufferOut _ -> doc
9287 doc ^ "\n\nThis function returns a list of strings."
9288 | RStruct (_, typ) ->
9289 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9290 | RStructList (_, typ) ->
9291 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9293 doc ^ "\n\nThis function returns a dictionary." in
9295 if List.mem ProtocolLimitWarning flags then
9296 doc ^ "\n\n" ^ protocol_limit_warning
9299 if List.mem DangerWillRobinson flags then
9300 doc ^ "\n\n" ^ danger_will_robinson
9303 match deprecation_notice flags with
9305 | Some txt -> doc ^ "\n\n" ^ txt in
9306 let doc = pod2text ~width:60 name doc in
9307 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9308 let doc = String.concat "\n " doc in
9309 pr " u\"\"\"%s\"\"\"\n" doc;
9311 pr " return libguestfsmod.%s " name;
9312 generate_py_call_args ~handle:"self._o" (snd style);
9317 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9318 and generate_py_call_args ~handle args =
9320 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9323 (* Useful if you need the longdesc POD text as plain text. Returns a
9326 * Because this is very slow (the slowest part of autogeneration),
9327 * we memoize the results.
9329 and pod2text ~width name longdesc =
9330 let key = width, name, longdesc in
9331 try Hashtbl.find pod2text_memo key
9333 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9334 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9336 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9337 let chan = open_process_in cmd in
9338 let lines = ref [] in
9340 let line = input_line chan in
9341 if i = 1 then (* discard the first line of output *)
9344 let line = triml line in
9345 lines := line :: !lines;
9348 let lines = try loop 1 with End_of_file -> List.rev !lines in
9350 (match close_process_in chan with
9353 failwithf "pod2text: process exited with non-zero status (%d)" i
9354 | WSIGNALED i | WSTOPPED i ->
9355 failwithf "pod2text: process signalled or stopped by signal %d" i
9357 Hashtbl.add pod2text_memo key lines;
9358 pod2text_memo_updated ();
9361 (* Generate ruby bindings. *)
9362 and generate_ruby_c () =
9363 generate_header CStyle LGPLv2plus;
9371 #include \"guestfs.h\"
9373 #include \"extconf.h\"
9375 /* For Ruby < 1.9 */
9377 #define RARRAY_LEN(r) (RARRAY((r))->len)
9380 static VALUE m_guestfs; /* guestfs module */
9381 static VALUE c_guestfs; /* guestfs_h handle */
9382 static VALUE e_Error; /* used for all errors */
9384 static void ruby_guestfs_free (void *p)
9387 guestfs_close ((guestfs_h *) p);
9390 static VALUE ruby_guestfs_create (VALUE m)
9394 g = guestfs_create ();
9396 rb_raise (e_Error, \"failed to create guestfs handle\");
9398 /* Don't print error messages to stderr by default. */
9399 guestfs_set_error_handler (g, NULL, NULL);
9401 /* Wrap it, and make sure the close function is called when the
9404 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9407 static VALUE ruby_guestfs_close (VALUE gv)
9410 Data_Get_Struct (gv, guestfs_h, g);
9412 ruby_guestfs_free (g);
9413 DATA_PTR (gv) = NULL;
9421 fun (name, style, _, _, _, _, _) ->
9422 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9423 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9426 pr " guestfs_h *g;\n";
9427 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9429 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9435 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9436 pr " Check_Type (%sv, T_STRING);\n" n;
9437 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9439 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9440 pr " \"%s\", \"%s\");\n" n name
9442 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9443 | StringList n | DeviceList n ->
9444 pr " char **%s;\n" n;
9445 pr " Check_Type (%sv, T_ARRAY);\n" n;
9447 pr " int i, len;\n";
9448 pr " len = RARRAY_LEN (%sv);\n" n;
9449 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9451 pr " for (i = 0; i < len; ++i) {\n";
9452 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9453 pr " %s[i] = StringValueCStr (v);\n" n;
9455 pr " %s[len] = NULL;\n" n;
9458 pr " int %s = RTEST (%sv);\n" n n
9460 pr " int %s = NUM2INT (%sv);\n" n n
9462 pr " long long %s = NUM2LL (%sv);\n" n n
9467 match fst style with
9468 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9469 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9470 | RConstString _ | RConstOptString _ ->
9471 pr " const char *r;\n"; "NULL"
9472 | RString _ -> pr " char *r;\n"; "NULL"
9473 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9474 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9475 | RStructList (_, typ) ->
9476 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9479 pr " size_t size;\n";
9483 pr " r = guestfs_%s " name;
9484 generate_c_call_args ~handle:"g" style;
9489 | Pathname _ | Device _ | Dev_or_Path _ | String _
9490 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9491 | StringList n | DeviceList n ->
9492 pr " free (%s);\n" n
9495 pr " if (r == %s)\n" error_code;
9496 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9499 (match fst style with
9501 pr " return Qnil;\n"
9502 | RInt _ | RBool _ ->
9503 pr " return INT2NUM (r);\n"
9505 pr " return ULL2NUM (r);\n"
9507 pr " return rb_str_new2 (r);\n";
9508 | RConstOptString _ ->
9510 pr " return rb_str_new2 (r);\n";
9512 pr " return Qnil;\n";
9514 pr " VALUE rv = rb_str_new2 (r);\n";
9518 pr " int i, len = 0;\n";
9519 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9520 pr " VALUE rv = rb_ary_new2 (len);\n";
9521 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9522 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9523 pr " free (r[i]);\n";
9527 | RStruct (_, typ) ->
9528 let cols = cols_of_struct typ in
9529 generate_ruby_struct_code typ cols
9530 | RStructList (_, typ) ->
9531 let cols = cols_of_struct typ in
9532 generate_ruby_struct_list_code typ cols
9534 pr " VALUE rv = rb_hash_new ();\n";
9536 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9537 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9538 pr " free (r[i]);\n";
9539 pr " free (r[i+1]);\n";
9544 pr " VALUE rv = rb_str_new (r, size);\n";
9554 /* Initialize the module. */
9555 void Init__guestfs ()
9557 m_guestfs = rb_define_module (\"Guestfs\");
9558 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9559 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9561 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9562 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9565 (* Define the rest of the methods. *)
9567 fun (name, style, _, _, _, _, _) ->
9568 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9569 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9574 (* Ruby code to return a struct. *)
9575 and generate_ruby_struct_code typ cols =
9576 pr " VALUE rv = rb_hash_new ();\n";
9580 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9582 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9584 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9585 | name, (FBytes|FUInt64) ->
9586 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9588 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9590 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9592 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9593 | name, FOptPercent ->
9594 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9595 | name, FChar -> (* XXX wrong? *)
9596 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9598 pr " guestfs_free_%s (r);\n" typ;
9601 (* Ruby code to return a struct list. *)
9602 and generate_ruby_struct_list_code typ cols =
9603 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9605 pr " for (i = 0; i < r->len; ++i) {\n";
9606 pr " VALUE hv = rb_hash_new ();\n";
9610 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9612 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
9614 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9615 | name, (FBytes|FUInt64) ->
9616 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9618 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9620 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9622 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9623 | name, FOptPercent ->
9624 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9625 | name, FChar -> (* XXX wrong? *)
9626 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9628 pr " rb_ary_push (rv, hv);\n";
9630 pr " guestfs_free_%s_list (r);\n" typ;
9633 (* Generate Java bindings GuestFS.java file. *)
9634 and generate_java_java () =
9635 generate_header CStyle LGPLv2plus;
9638 package com.redhat.et.libguestfs;
9640 import java.util.HashMap;
9641 import com.redhat.et.libguestfs.LibGuestFSException;
9642 import com.redhat.et.libguestfs.PV;
9643 import com.redhat.et.libguestfs.VG;
9644 import com.redhat.et.libguestfs.LV;
9645 import com.redhat.et.libguestfs.Stat;
9646 import com.redhat.et.libguestfs.StatVFS;
9647 import com.redhat.et.libguestfs.IntBool;
9648 import com.redhat.et.libguestfs.Dirent;
9651 * The GuestFS object is a libguestfs handle.
9655 public class GuestFS {
9656 // Load the native code.
9658 System.loadLibrary (\"guestfs_jni\");
9662 * The native guestfs_h pointer.
9667 * Create a libguestfs handle.
9669 * @throws LibGuestFSException
9671 public GuestFS () throws LibGuestFSException
9675 private native long _create () throws LibGuestFSException;
9678 * Close a libguestfs handle.
9680 * You can also leave handles to be collected by the garbage
9681 * collector, but this method ensures that the resources used
9682 * by the handle are freed up immediately. If you call any
9683 * other methods after closing the handle, you will get an
9686 * @throws LibGuestFSException
9688 public void close () throws LibGuestFSException
9694 private native void _close (long g) throws LibGuestFSException;
9696 public void finalize () throws LibGuestFSException
9704 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9705 if not (List.mem NotInDocs flags); then (
9706 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9708 if List.mem ProtocolLimitWarning flags then
9709 doc ^ "\n\n" ^ protocol_limit_warning
9712 if List.mem DangerWillRobinson flags then
9713 doc ^ "\n\n" ^ danger_will_robinson
9716 match deprecation_notice flags with
9718 | Some txt -> doc ^ "\n\n" ^ txt in
9719 let doc = pod2text ~width:60 name doc in
9720 let doc = List.map ( (* RHBZ#501883 *)
9723 | nonempty -> nonempty
9725 let doc = String.concat "\n * " doc in
9728 pr " * %s\n" shortdesc;
9731 pr " * @throws LibGuestFSException\n";
9735 generate_java_prototype ~public:true ~semicolon:false name style;
9738 pr " if (g == 0)\n";
9739 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9742 if fst style <> RErr then pr "return ";
9744 generate_java_call_args ~handle:"g" (snd style);
9748 generate_java_prototype ~privat:true ~native:true name style;
9755 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9756 and generate_java_call_args ~handle args =
9758 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9761 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9762 ?(semicolon=true) name style =
9763 if privat then pr "private ";
9764 if public then pr "public ";
9765 if native then pr "native ";
9768 (match fst style with
9769 | RErr -> pr "void ";
9770 | RInt _ -> pr "int ";
9771 | RInt64 _ -> pr "long ";
9772 | RBool _ -> pr "boolean ";
9773 | RConstString _ | RConstOptString _ | RString _
9774 | RBufferOut _ -> pr "String ";
9775 | RStringList _ -> pr "String[] ";
9776 | RStruct (_, typ) ->
9777 let name = java_name_of_struct typ in
9779 | RStructList (_, typ) ->
9780 let name = java_name_of_struct typ in
9782 | RHashtable _ -> pr "HashMap<String,String> ";
9785 if native then pr "_%s " name else pr "%s " name;
9787 let needs_comma = ref false in
9796 if !needs_comma then pr ", ";
9797 needs_comma := true;
9801 | Device n | Dev_or_Path n
9807 | StringList n | DeviceList n ->
9818 pr " throws LibGuestFSException";
9819 if semicolon then pr ";"
9821 and generate_java_struct jtyp cols () =
9822 generate_header CStyle LGPLv2plus;
9825 package com.redhat.et.libguestfs;
9828 * Libguestfs %s structure.
9840 | name, FBuffer -> pr " public String %s;\n" name
9841 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9842 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9843 | name, FChar -> pr " public char %s;\n" name
9844 | name, FOptPercent ->
9845 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9846 pr " public float %s;\n" name
9851 and generate_java_c () =
9852 generate_header CStyle LGPLv2plus;
9859 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9860 #include \"guestfs.h\"
9862 /* Note that this function returns. The exception is not thrown
9863 * until after the wrapper function returns.
9866 throw_exception (JNIEnv *env, const char *msg)
9869 cl = (*env)->FindClass (env,
9870 \"com/redhat/et/libguestfs/LibGuestFSException\");
9871 (*env)->ThrowNew (env, cl, msg);
9874 JNIEXPORT jlong JNICALL
9875 Java_com_redhat_et_libguestfs_GuestFS__1create
9876 (JNIEnv *env, jobject obj)
9880 g = guestfs_create ();
9882 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9885 guestfs_set_error_handler (g, NULL, NULL);
9886 return (jlong) (long) g;
9889 JNIEXPORT void JNICALL
9890 Java_com_redhat_et_libguestfs_GuestFS__1close
9891 (JNIEnv *env, jobject obj, jlong jg)
9893 guestfs_h *g = (guestfs_h *) (long) jg;
9900 fun (name, style, _, _, _, _, _) ->
9902 (match fst style with
9903 | RErr -> pr "void ";
9904 | RInt _ -> pr "jint ";
9905 | RInt64 _ -> pr "jlong ";
9906 | RBool _ -> pr "jboolean ";
9907 | RConstString _ | RConstOptString _ | RString _
9908 | RBufferOut _ -> pr "jstring ";
9909 | RStruct _ | RHashtable _ ->
9911 | RStringList _ | RStructList _ ->
9915 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9916 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9918 pr " (JNIEnv *env, jobject obj, jlong jg";
9922 | Device n | Dev_or_Path n
9927 pr ", jstring j%s" n
9928 | StringList n | DeviceList n ->
9929 pr ", jobjectArray j%s" n
9931 pr ", jboolean j%s" n
9939 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9940 let error_code, no_ret =
9941 match fst style with
9942 | RErr -> pr " int r;\n"; "-1", ""
9944 | RInt _ -> pr " int r;\n"; "-1", "0"
9945 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9946 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9947 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9949 pr " jstring jr;\n";
9950 pr " char *r;\n"; "NULL", "NULL"
9952 pr " jobjectArray jr;\n";
9955 pr " jstring jstr;\n";
9956 pr " char **r;\n"; "NULL", "NULL"
9957 | RStruct (_, typ) ->
9958 pr " jobject jr;\n";
9960 pr " jfieldID fl;\n";
9961 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9962 | RStructList (_, typ) ->
9963 pr " jobjectArray jr;\n";
9965 pr " jfieldID fl;\n";
9966 pr " jobject jfl;\n";
9967 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9968 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9970 pr " jstring jr;\n";
9972 pr " size_t size;\n";
9977 | Device n | Dev_or_Path n
9982 pr " const char *%s;\n" n
9983 | StringList n | DeviceList n ->
9984 pr " int %s_len;\n" n;
9985 pr " const char **%s;\n" n
9990 pr " int64_t %s;\n" n
9994 (match fst style with
9995 | RStringList _ | RStructList _ -> true
9996 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9998 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9999 List.exists (function
10000 | StringList _ -> true
10001 | DeviceList _ -> true
10002 | _ -> false) (snd style) in
10008 (* Get the parameters. *)
10012 | Device n | Dev_or_Path n
10016 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10018 (* This is completely undocumented, but Java null becomes
10019 * a NULL parameter.
10021 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10022 | StringList n | DeviceList n ->
10023 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10024 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10025 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10026 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10028 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10030 pr " %s[%s_len] = NULL;\n" n n;
10034 pr " %s = j%s;\n" n n
10037 (* Make the call. *)
10038 pr " r = guestfs_%s " name;
10039 generate_c_call_args ~handle:"g" style;
10042 (* Release the parameters. *)
10046 | Device n | Dev_or_Path n
10050 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10052 pr " if (j%s)\n" n;
10053 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10054 | StringList n | DeviceList n ->
10055 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10056 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10058 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10060 pr " free (%s);\n" n
10066 (* Check for errors. *)
10067 pr " if (r == %s) {\n" error_code;
10068 pr " throw_exception (env, guestfs_last_error (g));\n";
10069 pr " return %s;\n" no_ret;
10072 (* Return value. *)
10073 (match fst style with
10075 | RInt _ -> pr " return (jint) r;\n"
10076 | RBool _ -> pr " return (jboolean) r;\n"
10077 | RInt64 _ -> pr " return (jlong) r;\n"
10078 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10079 | RConstOptString _ ->
10080 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10082 pr " jr = (*env)->NewStringUTF (env, r);\n";
10086 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10087 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10088 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10089 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10090 pr " for (i = 0; i < r_len; ++i) {\n";
10091 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10092 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10093 pr " free (r[i]);\n";
10097 | RStruct (_, typ) ->
10098 let jtyp = java_name_of_struct typ in
10099 let cols = cols_of_struct typ in
10100 generate_java_struct_return typ jtyp cols
10101 | RStructList (_, typ) ->
10102 let jtyp = java_name_of_struct typ in
10103 let cols = cols_of_struct typ in
10104 generate_java_struct_list_return typ jtyp cols
10107 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10108 pr " return NULL;\n"
10110 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10119 and generate_java_struct_return typ jtyp cols =
10120 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10121 pr " jr = (*env)->AllocObject (env, cl);\n";
10125 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10126 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10129 pr " char s[33];\n";
10130 pr " memcpy (s, r->%s, 32);\n" name;
10131 pr " s[32] = 0;\n";
10132 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10133 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10137 pr " int len = r->%s_len;\n" name;
10138 pr " char s[len+1];\n";
10139 pr " memcpy (s, r->%s, len);\n" name;
10140 pr " s[len] = 0;\n";
10141 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10142 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10144 | name, (FBytes|FUInt64|FInt64) ->
10145 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10146 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10147 | name, (FUInt32|FInt32) ->
10148 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10149 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10150 | name, FOptPercent ->
10151 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10152 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10154 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10155 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10160 and generate_java_struct_list_return typ jtyp cols =
10161 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10162 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10163 pr " for (i = 0; i < r->len; ++i) {\n";
10164 pr " jfl = (*env)->AllocObject (env, cl);\n";
10168 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10169 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10172 pr " char s[33];\n";
10173 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10174 pr " s[32] = 0;\n";
10175 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10176 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10180 pr " int len = r->val[i].%s_len;\n" name;
10181 pr " char s[len+1];\n";
10182 pr " memcpy (s, r->val[i].%s, len);\n" name;
10183 pr " s[len] = 0;\n";
10184 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10185 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10187 | name, (FBytes|FUInt64|FInt64) ->
10188 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10189 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10190 | name, (FUInt32|FInt32) ->
10191 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10192 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10193 | name, FOptPercent ->
10194 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10195 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10197 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10198 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10200 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10202 pr " guestfs_free_%s_list (r);\n" typ;
10205 and generate_java_makefile_inc () =
10206 generate_header HashStyle GPLv2plus;
10208 pr "java_built_sources = \\\n";
10211 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10213 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10215 and generate_haskell_hs () =
10216 generate_header HaskellStyle LGPLv2plus;
10218 (* XXX We only know how to generate partial FFI for Haskell
10219 * at the moment. Please help out!
10221 let can_generate style =
10225 | RInt64 _, _ -> true
10227 | RConstString _, _
10228 | RConstOptString _, _
10234 | RBufferOut _, _ -> false in
10237 {-# INCLUDE <guestfs.h> #-}
10238 {-# LANGUAGE ForeignFunctionInterface #-}
10243 (* List out the names of the actions we want to export. *)
10245 fun (name, style, _, _, _, _, _) ->
10246 if can_generate style then pr ",\n %s" name
10252 -- Unfortunately some symbols duplicate ones already present
10253 -- in Prelude. We don't know which, so we hard-code a list
10255 import Prelude hiding (truncate)
10259 import Foreign.C.Types
10261 import Control.Exception
10262 import Data.Typeable
10264 data GuestfsS = GuestfsS -- represents the opaque C struct
10265 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10266 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10268 -- XXX define properly later XXX
10272 data IntBool = IntBool
10274 data StatVFS = StatVFS
10275 data Hashtable = Hashtable
10277 foreign import ccall unsafe \"guestfs_create\" c_create
10279 foreign import ccall unsafe \"&guestfs_close\" c_close
10280 :: FunPtr (GuestfsP -> IO ())
10281 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10282 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10284 create :: IO GuestfsH
10287 c_set_error_handler p nullPtr nullPtr
10288 h <- newForeignPtr c_close p
10291 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10292 :: GuestfsP -> IO CString
10294 -- last_error :: GuestfsH -> IO (Maybe String)
10295 -- last_error h = do
10296 -- str <- withForeignPtr h (\\p -> c_last_error p)
10297 -- maybePeek peekCString str
10299 last_error :: GuestfsH -> IO (String)
10301 str <- withForeignPtr h (\\p -> c_last_error p)
10302 if (str == nullPtr)
10303 then return \"no error\"
10304 else peekCString str
10308 (* Generate wrappers for each foreign function. *)
10310 fun (name, style, _, _, _, _, _) ->
10311 if can_generate style then (
10312 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10314 generate_haskell_prototype ~handle:"GuestfsP" style;
10318 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10320 pr "%s %s = do\n" name
10321 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10323 (* Convert pointer arguments using with* functions. *)
10328 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10329 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10330 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10331 | Bool _ | Int _ | Int64 _ -> ()
10333 (* Convert integer arguments. *)
10337 | Bool n -> sprintf "(fromBool %s)" n
10338 | Int n -> sprintf "(fromIntegral %s)" n
10339 | Int64 n -> sprintf "(fromIntegral %s)" n
10340 | FileIn n | FileOut n
10341 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10343 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10344 (String.concat " " ("p" :: args));
10345 (match fst style with
10346 | RErr | RInt _ | RInt64 _ | RBool _ ->
10347 pr " if (r == -1)\n";
10349 pr " err <- last_error h\n";
10351 | RConstString _ | RConstOptString _ | RString _
10352 | RStringList _ | RStruct _
10353 | RStructList _ | RHashtable _ | RBufferOut _ ->
10354 pr " if (r == nullPtr)\n";
10356 pr " err <- last_error h\n";
10359 (match fst style with
10361 pr " else return ()\n"
10363 pr " else return (fromIntegral r)\n"
10365 pr " else return (fromIntegral r)\n"
10367 pr " else return (toBool r)\n"
10369 | RConstOptString _
10376 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10382 and generate_haskell_prototype ~handle ?(hs = false) style =
10383 pr "%s -> " handle;
10384 let string = if hs then "String" else "CString" in
10385 let int = if hs then "Int" else "CInt" in
10386 let bool = if hs then "Bool" else "CInt" in
10387 let int64 = if hs then "Integer" else "Int64" in
10391 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10392 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10393 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10394 | Bool _ -> pr "%s" bool
10395 | Int _ -> pr "%s" int
10396 | Int64 _ -> pr "%s" int
10397 | FileIn _ -> pr "%s" string
10398 | FileOut _ -> pr "%s" string
10403 (match fst style with
10404 | RErr -> if not hs then pr "CInt"
10405 | RInt _ -> pr "%s" int
10406 | RInt64 _ -> pr "%s" int64
10407 | RBool _ -> pr "%s" bool
10408 | RConstString _ -> pr "%s" string
10409 | RConstOptString _ -> pr "Maybe %s" string
10410 | RString _ -> pr "%s" string
10411 | RStringList _ -> pr "[%s]" string
10412 | RStruct (_, typ) ->
10413 let name = java_name_of_struct typ in
10415 | RStructList (_, typ) ->
10416 let name = java_name_of_struct typ in
10418 | RHashtable _ -> pr "Hashtable"
10419 | RBufferOut _ -> pr "%s" string
10423 and generate_csharp () =
10424 generate_header CPlusPlusStyle LGPLv2plus;
10426 (* XXX Make this configurable by the C# assembly users. *)
10427 let library = "libguestfs.so.0" in
10430 // These C# bindings are highly experimental at present.
10432 // Firstly they only work on Linux (ie. Mono). In order to get them
10433 // to work on Windows (ie. .Net) you would need to port the library
10434 // itself to Windows first.
10436 // The second issue is that some calls are known to be incorrect and
10437 // can cause Mono to segfault. Particularly: calls which pass or
10438 // return string[], or return any structure value. This is because
10439 // we haven't worked out the correct way to do this from C#.
10441 // The third issue is that when compiling you get a lot of warnings.
10442 // We are not sure whether the warnings are important or not.
10444 // Fourthly we do not routinely build or test these bindings as part
10445 // of the make && make check cycle, which means that regressions might
10448 // Suggestions and patches are welcome.
10452 // gmcs Libguestfs.cs
10453 // mono Libguestfs.exe
10455 // (You'll probably want to add a Test class / static main function
10456 // otherwise this won't do anything useful).
10460 using System.Runtime.InteropServices;
10461 using System.Runtime.Serialization;
10462 using System.Collections;
10466 class Error : System.ApplicationException
10468 public Error (string message) : base (message) {}
10469 protected Error (SerializationInfo info, StreamingContext context) {}
10476 [DllImport (\"%s\")]
10477 static extern IntPtr guestfs_create ();
10481 _handle = guestfs_create ();
10482 if (_handle == IntPtr.Zero)
10483 throw new Error (\"could not create guestfs handle\");
10486 [DllImport (\"%s\")]
10487 static extern void guestfs_close (IntPtr h);
10491 guestfs_close (_handle);
10494 [DllImport (\"%s\")]
10495 static extern string guestfs_last_error (IntPtr h);
10497 " library library library;
10499 (* Generate C# structure bindings. We prefix struct names with
10500 * underscore because C# cannot have conflicting struct names and
10501 * method names (eg. "class stat" and "stat").
10505 pr " [StructLayout (LayoutKind.Sequential)]\n";
10506 pr " public class _%s {\n" typ;
10509 | name, FChar -> pr " char %s;\n" name
10510 | name, FString -> pr " string %s;\n" name
10512 pr " uint %s_len;\n" name;
10513 pr " string %s;\n" name
10515 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10516 pr " string %s;\n" name
10517 | name, FUInt32 -> pr " uint %s;\n" name
10518 | name, FInt32 -> pr " int %s;\n" name
10519 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10520 | name, FInt64 -> pr " long %s;\n" name
10521 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10527 (* Generate C# function bindings. *)
10529 fun (name, style, _, _, _, shortdesc, _) ->
10530 let rec csharp_return_type () =
10531 match fst style with
10533 | RBool n -> "bool"
10535 | RInt64 n -> "long"
10537 | RConstOptString n
10539 | RBufferOut n -> "string"
10540 | RStruct (_,n) -> "_" ^ n
10541 | RHashtable n -> "Hashtable"
10542 | RStringList n -> "string[]"
10543 | RStructList (_,n) -> sprintf "_%s[]" n
10545 and c_return_type () =
10546 match fst style with
10550 | RInt64 _ -> "long"
10552 | RConstOptString _
10554 | RBufferOut _ -> "string"
10555 | RStruct (_,n) -> "_" ^ n
10557 | RStringList _ -> "string[]"
10558 | RStructList (_,n) -> sprintf "_%s[]" n
10560 and c_error_comparison () =
10561 match fst style with
10565 | RInt64 _ -> "== -1"
10567 | RConstOptString _
10573 | RStructList (_,_) -> "== null"
10575 and generate_extern_prototype () =
10576 pr " static extern %s guestfs_%s (IntPtr h"
10577 (c_return_type ()) name;
10580 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10581 | FileIn n | FileOut n ->
10582 pr ", [In] string %s" n
10583 | StringList n | DeviceList n ->
10584 pr ", [In] string[] %s" n
10594 and generate_public_prototype () =
10595 pr " public %s %s (" (csharp_return_type ()) name;
10596 let comma = ref false in
10598 if !comma then pr ", ";
10603 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10604 | FileIn n | FileOut n ->
10605 next (); pr "string %s" n
10606 | StringList n | DeviceList n ->
10607 next (); pr "string[] %s" n
10609 next (); pr "bool %s" n
10611 next (); pr "int %s" n
10613 next (); pr "long %s" n
10617 and generate_call () =
10618 pr "guestfs_%s (_handle" name;
10619 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10623 pr " [DllImport (\"%s\")]\n" library;
10624 generate_extern_prototype ();
10626 pr " /// <summary>\n";
10627 pr " /// %s\n" shortdesc;
10628 pr " /// </summary>\n";
10629 generate_public_prototype ();
10631 pr " %s r;\n" (c_return_type ());
10634 pr " if (r %s)\n" (c_error_comparison ());
10635 pr " throw new Error (guestfs_last_error (_handle));\n";
10636 (match fst style with
10639 pr " return r != 0 ? true : false;\n"
10641 pr " Hashtable rr = new Hashtable ();\n";
10642 pr " for (int i = 0; i < r.Length; i += 2)\n";
10643 pr " rr.Add (r[i], r[i+1]);\n";
10645 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10646 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10652 ) all_functions_sorted;
10658 and generate_bindtests () =
10659 generate_header CStyle LGPLv2plus;
10663 #include <stdlib.h>
10664 #include <inttypes.h>
10665 #include <string.h>
10667 #include \"guestfs.h\"
10668 #include \"guestfs-internal.h\"
10669 #include \"guestfs-internal-actions.h\"
10670 #include \"guestfs_protocol.h\"
10672 #define error guestfs_error
10673 #define safe_calloc guestfs_safe_calloc
10674 #define safe_malloc guestfs_safe_malloc
10677 print_strings (char *const *argv)
10682 for (argc = 0; argv[argc] != NULL; ++argc) {
10683 if (argc > 0) printf (\", \");
10684 printf (\"\\\"%%s\\\"\", argv[argc]);
10689 /* The test0 function prints its parameters to stdout. */
10693 match test_functions with
10694 | [] -> assert false
10695 | test0 :: tests -> test0, tests in
10698 let (name, style, _, _, _, _, _) = test0 in
10699 generate_prototype ~extern:false ~semicolon:false ~newline:true
10700 ~handle:"g" ~prefix:"guestfs__" name style;
10705 | Device n | Dev_or_Path n
10708 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10709 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10710 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10711 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10712 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10713 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10715 pr " /* Java changes stdout line buffering so we need this: */\n";
10716 pr " fflush (stdout);\n";
10722 fun (name, style, _, _, _, _, _) ->
10723 if String.sub name (String.length name - 3) 3 <> "err" then (
10724 pr "/* Test normal return. */\n";
10725 generate_prototype ~extern:false ~semicolon:false ~newline:true
10726 ~handle:"g" ~prefix:"guestfs__" name style;
10728 (match fst style with
10733 pr " sscanf (val, \"%%d\", &r);\n";
10736 pr " int64_t r;\n";
10737 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10740 pr " return STREQ (val, \"true\");\n"
10742 | RConstOptString _ ->
10743 (* Can't return the input string here. Return a static
10744 * string so we ensure we get a segfault if the caller
10745 * tries to free it.
10747 pr " return \"static string\";\n"
10749 pr " return strdup (val);\n"
10751 pr " char **strs;\n";
10753 pr " sscanf (val, \"%%d\", &n);\n";
10754 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10755 pr " for (i = 0; i < n; ++i) {\n";
10756 pr " strs[i] = safe_malloc (g, 16);\n";
10757 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10759 pr " strs[n] = NULL;\n";
10760 pr " return strs;\n"
10761 | RStruct (_, typ) ->
10762 pr " struct guestfs_%s *r;\n" typ;
10763 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10765 | RStructList (_, typ) ->
10766 pr " struct guestfs_%s_list *r;\n" typ;
10767 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10768 pr " sscanf (val, \"%%d\", &r->len);\n";
10769 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10772 pr " char **strs;\n";
10774 pr " sscanf (val, \"%%d\", &n);\n";
10775 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10776 pr " for (i = 0; i < n; ++i) {\n";
10777 pr " strs[i*2] = safe_malloc (g, 16);\n";
10778 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10779 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10780 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10782 pr " strs[n*2] = NULL;\n";
10783 pr " return strs;\n"
10785 pr " return strdup (val);\n"
10790 pr "/* Test error return. */\n";
10791 generate_prototype ~extern:false ~semicolon:false ~newline:true
10792 ~handle:"g" ~prefix:"guestfs__" name style;
10794 pr " error (g, \"error\");\n";
10795 (match fst style with
10796 | RErr | RInt _ | RInt64 _ | RBool _ ->
10798 | RConstString _ | RConstOptString _
10799 | RString _ | RStringList _ | RStruct _
10803 pr " return NULL;\n"
10810 and generate_ocaml_bindtests () =
10811 generate_header OCamlStyle GPLv2plus;
10815 let g = Guestfs.create () in
10819 String.concat " " (
10822 | CallString s -> "\"" ^ s ^ "\""
10823 | CallOptString None -> "None"
10824 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10825 | CallStringList xs ->
10826 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10827 | CallInt i when i >= 0 -> string_of_int i
10828 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10829 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10830 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10831 | CallBool b -> string_of_bool b
10836 generate_lang_bindtests (
10837 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10840 pr "print_endline \"EOF\"\n"
10842 and generate_perl_bindtests () =
10843 pr "#!/usr/bin/perl -w\n";
10844 generate_header HashStyle GPLv2plus;
10851 my $g = Sys::Guestfs->new ();
10855 String.concat ", " (
10858 | CallString s -> "\"" ^ s ^ "\""
10859 | CallOptString None -> "undef"
10860 | CallOptString (Some s) -> sprintf "\"%s\"" s
10861 | CallStringList xs ->
10862 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10863 | CallInt i -> string_of_int i
10864 | CallInt64 i -> Int64.to_string i
10865 | CallBool b -> if b then "1" else "0"
10870 generate_lang_bindtests (
10871 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10874 pr "print \"EOF\\n\"\n"
10876 and generate_python_bindtests () =
10877 generate_header HashStyle GPLv2plus;
10882 g = guestfs.GuestFS ()
10886 String.concat ", " (
10889 | CallString s -> "\"" ^ s ^ "\""
10890 | CallOptString None -> "None"
10891 | CallOptString (Some s) -> sprintf "\"%s\"" s
10892 | CallStringList xs ->
10893 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10894 | CallInt i -> string_of_int i
10895 | CallInt64 i -> Int64.to_string i
10896 | CallBool b -> if b then "1" else "0"
10901 generate_lang_bindtests (
10902 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10905 pr "print \"EOF\"\n"
10907 and generate_ruby_bindtests () =
10908 generate_header HashStyle GPLv2plus;
10913 g = Guestfs::create()
10917 String.concat ", " (
10920 | CallString s -> "\"" ^ s ^ "\""
10921 | CallOptString None -> "nil"
10922 | CallOptString (Some s) -> sprintf "\"%s\"" s
10923 | CallStringList xs ->
10924 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10925 | CallInt i -> string_of_int i
10926 | CallInt64 i -> Int64.to_string i
10927 | CallBool b -> string_of_bool b
10932 generate_lang_bindtests (
10933 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10936 pr "print \"EOF\\n\"\n"
10938 and generate_java_bindtests () =
10939 generate_header CStyle GPLv2plus;
10942 import com.redhat.et.libguestfs.*;
10944 public class Bindtests {
10945 public static void main (String[] argv)
10948 GuestFS g = new GuestFS ();
10952 String.concat ", " (
10955 | CallString s -> "\"" ^ s ^ "\""
10956 | CallOptString None -> "null"
10957 | CallOptString (Some s) -> sprintf "\"%s\"" s
10958 | CallStringList xs ->
10960 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10961 | CallInt i -> string_of_int i
10962 | CallInt64 i -> Int64.to_string i
10963 | CallBool b -> string_of_bool b
10968 generate_lang_bindtests (
10969 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10973 System.out.println (\"EOF\");
10975 catch (Exception exn) {
10976 System.err.println (exn);
10983 and generate_haskell_bindtests () =
10984 generate_header HaskellStyle GPLv2plus;
10987 module Bindtests where
10988 import qualified Guestfs
10991 g <- Guestfs.create
10995 String.concat " " (
10998 | CallString s -> "\"" ^ s ^ "\""
10999 | CallOptString None -> "Nothing"
11000 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11001 | CallStringList xs ->
11002 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11003 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11004 | CallInt i -> string_of_int i
11005 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11006 | CallInt64 i -> Int64.to_string i
11007 | CallBool true -> "True"
11008 | CallBool false -> "False"
11013 generate_lang_bindtests (
11014 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11017 pr " putStrLn \"EOF\"\n"
11019 (* Language-independent bindings tests - we do it this way to
11020 * ensure there is parity in testing bindings across all languages.
11022 and generate_lang_bindtests call =
11023 call "test0" [CallString "abc"; CallOptString (Some "def");
11024 CallStringList []; CallBool false;
11025 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11026 call "test0" [CallString "abc"; CallOptString None;
11027 CallStringList []; CallBool false;
11028 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11029 call "test0" [CallString ""; CallOptString (Some "def");
11030 CallStringList []; CallBool false;
11031 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11032 call "test0" [CallString ""; CallOptString (Some "");
11033 CallStringList []; CallBool false;
11034 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11035 call "test0" [CallString "abc"; CallOptString (Some "def");
11036 CallStringList ["1"]; CallBool false;
11037 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11038 call "test0" [CallString "abc"; CallOptString (Some "def");
11039 CallStringList ["1"; "2"]; CallBool false;
11040 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11041 call "test0" [CallString "abc"; CallOptString (Some "def");
11042 CallStringList ["1"]; CallBool true;
11043 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11044 call "test0" [CallString "abc"; CallOptString (Some "def");
11045 CallStringList ["1"]; CallBool false;
11046 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11047 call "test0" [CallString "abc"; CallOptString (Some "def");
11048 CallStringList ["1"]; CallBool false;
11049 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11050 call "test0" [CallString "abc"; CallOptString (Some "def");
11051 CallStringList ["1"]; CallBool false;
11052 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11053 call "test0" [CallString "abc"; CallOptString (Some "def");
11054 CallStringList ["1"]; CallBool false;
11055 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11056 call "test0" [CallString "abc"; CallOptString (Some "def");
11057 CallStringList ["1"]; CallBool false;
11058 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11059 call "test0" [CallString "abc"; CallOptString (Some "def");
11060 CallStringList ["1"]; CallBool false;
11061 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11063 (* XXX Add here tests of the return and error functions. *)
11065 (* Code to generator bindings for virt-inspector. Currently only
11066 * implemented for OCaml code (for virt-p2v 2.0).
11068 let rng_input = "inspector/virt-inspector.rng"
11070 (* Read the input file and parse it into internal structures. This is
11071 * by no means a complete RELAX NG parser, but is just enough to be
11072 * able to parse the specific input file.
11075 | Element of string * rng list (* <element name=name/> *)
11076 | Attribute of string * rng list (* <attribute name=name/> *)
11077 | Interleave of rng list (* <interleave/> *)
11078 | ZeroOrMore of rng (* <zeroOrMore/> *)
11079 | OneOrMore of rng (* <oneOrMore/> *)
11080 | Optional of rng (* <optional/> *)
11081 | Choice of string list (* <choice><value/>*</choice> *)
11082 | Value of string (* <value>str</value> *)
11083 | Text (* <text/> *)
11085 let rec string_of_rng = function
11086 | Element (name, xs) ->
11087 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11088 | Attribute (name, xs) ->
11089 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11090 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11091 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11092 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11093 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11094 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11095 | Value value -> "Value \"" ^ value ^ "\""
11098 and string_of_rng_list xs =
11099 String.concat ", " (List.map string_of_rng xs)
11101 let rec parse_rng ?defines context = function
11103 | Xml.Element ("element", ["name", name], children) :: rest ->
11104 Element (name, parse_rng ?defines context children)
11105 :: parse_rng ?defines context rest
11106 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11107 Attribute (name, parse_rng ?defines context children)
11108 :: parse_rng ?defines context rest
11109 | Xml.Element ("interleave", [], children) :: rest ->
11110 Interleave (parse_rng ?defines context children)
11111 :: parse_rng ?defines context rest
11112 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11113 let rng = parse_rng ?defines context [child] in
11115 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11117 failwithf "%s: <zeroOrMore> contains more than one child element"
11120 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11121 let rng = parse_rng ?defines context [child] in
11123 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11125 failwithf "%s: <oneOrMore> contains more than one child element"
11128 | Xml.Element ("optional", [], [child]) :: rest ->
11129 let rng = parse_rng ?defines context [child] in
11131 | [child] -> Optional child :: parse_rng ?defines context rest
11133 failwithf "%s: <optional> contains more than one child element"
11136 | Xml.Element ("choice", [], children) :: rest ->
11137 let values = List.map (
11138 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11140 failwithf "%s: can't handle anything except <value> in <choice>"
11144 :: parse_rng ?defines context rest
11145 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11146 Value value :: parse_rng ?defines context rest
11147 | Xml.Element ("text", [], []) :: rest ->
11148 Text :: parse_rng ?defines context rest
11149 | Xml.Element ("ref", ["name", name], []) :: rest ->
11150 (* Look up the reference. Because of limitations in this parser,
11151 * we can't handle arbitrarily nested <ref> yet. You can only
11152 * use <ref> from inside <start>.
11154 (match defines with
11156 failwithf "%s: contains <ref>, but no refs are defined yet" context
11158 let rng = StringMap.find name map in
11159 rng @ parse_rng ?defines context rest
11162 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11165 let xml = Xml.parse_file rng_input in
11167 | Xml.Element ("grammar", _,
11168 Xml.Element ("start", _, gram) :: defines) ->
11169 (* The <define/> elements are referenced in the <start> section,
11170 * so build a map of those first.
11172 let defines = List.fold_left (
11174 function Xml.Element ("define", ["name", name], defn) ->
11175 StringMap.add name defn map
11177 failwithf "%s: expected <define name=name/>" rng_input
11178 ) StringMap.empty defines in
11179 let defines = StringMap.mapi parse_rng defines in
11181 (* Parse the <start> clause, passing the defines. *)
11182 parse_rng ~defines "<start>" gram
11184 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11187 let name_of_field = function
11188 | Element (name, _) | Attribute (name, _)
11189 | ZeroOrMore (Element (name, _))
11190 | OneOrMore (Element (name, _))
11191 | Optional (Element (name, _)) -> name
11192 | Optional (Attribute (name, _)) -> name
11193 | Text -> (* an unnamed field in an element *)
11196 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11198 (* At the moment this function only generates OCaml types. However we
11199 * should parameterize it later so it can generate types/structs in a
11200 * variety of languages.
11202 let generate_types xs =
11203 (* A simple type is one that can be printed out directly, eg.
11204 * "string option". A complex type is one which has a name and has
11205 * to be defined via another toplevel definition, eg. a struct.
11207 * generate_type generates code for either simple or complex types.
11208 * In the simple case, it returns the string ("string option"). In
11209 * the complex case, it returns the name ("mountpoint"). In the
11210 * complex case it has to print out the definition before returning,
11211 * so it should only be called when we are at the beginning of a
11212 * new line (BOL context).
11214 let rec generate_type = function
11215 | Text -> (* string *)
11217 | Choice values -> (* [`val1|`val2|...] *)
11218 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11219 | ZeroOrMore rng -> (* <rng> list *)
11220 let t, is_simple = generate_type rng in
11221 t ^ " list (* 0 or more *)", is_simple
11222 | OneOrMore rng -> (* <rng> list *)
11223 let t, is_simple = generate_type rng in
11224 t ^ " list (* 1 or more *)", is_simple
11225 (* virt-inspector hack: bool *)
11226 | Optional (Attribute (name, [Value "1"])) ->
11228 | Optional rng -> (* <rng> list *)
11229 let t, is_simple = generate_type rng in
11230 t ^ " option", is_simple
11231 (* type name = { fields ... } *)
11232 | Element (name, fields) when is_attrs_interleave fields ->
11233 generate_type_struct name (get_attrs_interleave fields)
11234 | Element (name, [field]) (* type name = field *)
11235 | Attribute (name, [field]) ->
11236 let t, is_simple = generate_type field in
11237 if is_simple then (t, true)
11239 pr "type %s = %s\n" name t;
11242 | Element (name, fields) -> (* type name = { fields ... } *)
11243 generate_type_struct name fields
11245 failwithf "generate_type failed at: %s" (string_of_rng rng)
11247 and is_attrs_interleave = function
11248 | [Interleave _] -> true
11249 | Attribute _ :: fields -> is_attrs_interleave fields
11250 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11253 and get_attrs_interleave = function
11254 | [Interleave fields] -> fields
11255 | ((Attribute _) as field) :: fields
11256 | ((Optional (Attribute _)) as field) :: fields ->
11257 field :: get_attrs_interleave fields
11258 | _ -> assert false
11260 and generate_types xs =
11261 List.iter (fun x -> ignore (generate_type x)) xs
11263 and generate_type_struct name fields =
11264 (* Calculate the types of the fields first. We have to do this
11265 * before printing anything so we are still in BOL context.
11267 let types = List.map fst (List.map generate_type fields) in
11269 (* Special case of a struct containing just a string and another
11270 * field. Turn it into an assoc list.
11273 | ["string"; other] ->
11274 let fname1, fname2 =
11276 | [f1; f2] -> name_of_field f1, name_of_field f2
11277 | _ -> assert false in
11278 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11282 pr "type %s = {\n" name;
11284 fun (field, ftype) ->
11285 let fname = name_of_field field in
11286 pr " %s_%s : %s;\n" name fname ftype
11287 ) (List.combine fields types);
11289 (* Return the name of this type, and
11290 * false because it's not a simple type.
11297 let generate_parsers xs =
11298 (* As for generate_type above, generate_parser makes a parser for
11299 * some type, and returns the name of the parser it has generated.
11300 * Because it (may) need to print something, it should always be
11301 * called in BOL context.
11303 let rec generate_parser = function
11304 | Text -> (* string *)
11305 "string_child_or_empty"
11306 | Choice values -> (* [`val1|`val2|...] *)
11307 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11309 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11310 | ZeroOrMore rng -> (* <rng> list *)
11311 let pa = generate_parser rng in
11312 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11313 | OneOrMore rng -> (* <rng> list *)
11314 let pa = generate_parser rng in
11315 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11316 (* virt-inspector hack: bool *)
11317 | Optional (Attribute (name, [Value "1"])) ->
11318 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11319 | Optional rng -> (* <rng> list *)
11320 let pa = generate_parser rng in
11321 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11322 (* type name = { fields ... } *)
11323 | Element (name, fields) when is_attrs_interleave fields ->
11324 generate_parser_struct name (get_attrs_interleave fields)
11325 | Element (name, [field]) -> (* type name = field *)
11326 let pa = generate_parser field in
11327 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11328 pr "let %s =\n" parser_name;
11330 pr "let parse_%s = %s\n" name parser_name;
11332 | Attribute (name, [field]) ->
11333 let pa = generate_parser field in
11334 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11335 pr "let %s =\n" parser_name;
11337 pr "let parse_%s = %s\n" name parser_name;
11339 | Element (name, fields) -> (* type name = { fields ... } *)
11340 generate_parser_struct name ([], fields)
11342 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11344 and is_attrs_interleave = function
11345 | [Interleave _] -> true
11346 | Attribute _ :: fields -> is_attrs_interleave fields
11347 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11350 and get_attrs_interleave = function
11351 | [Interleave fields] -> [], fields
11352 | ((Attribute _) as field) :: fields
11353 | ((Optional (Attribute _)) as field) :: fields ->
11354 let attrs, interleaves = get_attrs_interleave fields in
11355 (field :: attrs), interleaves
11356 | _ -> assert false
11358 and generate_parsers xs =
11359 List.iter (fun x -> ignore (generate_parser x)) xs
11361 and generate_parser_struct name (attrs, interleaves) =
11362 (* Generate parsers for the fields first. We have to do this
11363 * before printing anything so we are still in BOL context.
11365 let fields = attrs @ interleaves in
11366 let pas = List.map generate_parser fields in
11368 (* Generate an intermediate tuple from all the fields first.
11369 * If the type is just a string + another field, then we will
11370 * return this directly, otherwise it is turned into a record.
11372 * RELAX NG note: This code treats <interleave> and plain lists of
11373 * fields the same. In other words, it doesn't bother enforcing
11374 * any ordering of fields in the XML.
11376 pr "let parse_%s x =\n" name;
11377 pr " let t = (\n ";
11378 let comma = ref false in
11381 if !comma then pr ",\n ";
11384 | Optional (Attribute (fname, [field])), pa ->
11386 | Optional (Element (fname, [field])), pa ->
11387 pr "%s (optional_child %S x)" pa fname
11388 | Attribute (fname, [Text]), _ ->
11389 pr "attribute %S x" fname
11390 | (ZeroOrMore _ | OneOrMore _), pa ->
11395 let fname = name_of_field field in
11396 pr "%s (child %S x)" pa fname
11397 ) (List.combine fields pas);
11401 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11405 pr " (Obj.magic t : %s)\n" name
11409 | (Optional (Attribute (fname, [field])), pa) ->
11410 pr " %s_%s =\n" name fname;
11412 | (Optional (Element (fname, [field])), pa) ->
11413 pr " %s_%s =\n" name fname;
11414 pr " (let x = optional_child %S x in\n" fname;
11417 let fname = name_of_field field in
11418 pr " %s_%s =\n" name fname;
11419 pr " (let x = child %S x in\n" fname;
11421 ) (List.combine fields pas);
11425 sprintf "parse_%s" name
11428 generate_parsers xs
11430 (* Generate ocaml/guestfs_inspector.mli. *)
11431 let generate_ocaml_inspector_mli () =
11432 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11435 (** This is an OCaml language binding to the external [virt-inspector]
11438 For more information, please read the man page [virt-inspector(1)].
11443 generate_types grammar;
11444 pr "(** The nested information returned from the {!inspect} function. *)\n";
11448 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11449 (** To inspect a libvirt domain called [name], pass a singleton
11450 list: [inspect [name]]. When using libvirt only, you may
11451 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11453 To inspect a disk image or images, pass a list of the filenames
11454 of the disk images: [inspect filenames]
11456 This function inspects the given guest or disk images and
11457 returns a list of operating system(s) found and a large amount
11458 of information about them. In the vast majority of cases,
11459 a virtual machine only contains a single operating system.
11461 If the optional [~xml] parameter is given, then this function
11462 skips running the external virt-inspector program and just
11463 parses the given XML directly (which is expected to be XML
11464 produced from a previous run of virt-inspector). The list of
11465 names and connect URI are ignored in this case.
11467 This function can throw a wide variety of exceptions, for example
11468 if the external virt-inspector program cannot be found, or if
11469 it doesn't generate valid XML.
11473 (* Generate ocaml/guestfs_inspector.ml. *)
11474 let generate_ocaml_inspector_ml () =
11475 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11480 generate_types grammar;
11484 (* Misc functions which are used by the parser code below. *)
11485 let first_child = function
11486 | Xml.Element (_, _, c::_) -> c
11487 | Xml.Element (name, _, []) ->
11488 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11489 | Xml.PCData str ->
11490 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11492 let string_child_or_empty = function
11493 | Xml.Element (_, _, [Xml.PCData s]) -> s
11494 | Xml.Element (_, _, []) -> \"\"
11495 | Xml.Element (x, _, _) ->
11496 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11498 | Xml.PCData str ->
11499 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11501 let optional_child name xml =
11502 let children = Xml.children xml in
11504 Some (List.find (function
11505 | Xml.Element (n, _, _) when n = name -> true
11506 | _ -> false) children)
11510 let child name xml =
11511 match optional_child name xml with
11514 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11516 let attribute name xml =
11517 try Xml.attrib xml name
11518 with Xml.No_attribute _ ->
11519 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11523 generate_parsers grammar;
11527 (* Run external virt-inspector, then use parser to parse the XML. *)
11528 let inspect ?connect ?xml names =
11532 if names = [] then invalid_arg \"inspect: no names given\";
11533 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11534 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11536 let cmd = List.map Filename.quote cmd in
11537 let cmd = String.concat \" \" cmd in
11538 let chan = open_process_in cmd in
11539 let xml = Xml.parse_in chan in
11540 (match close_process_in chan with
11542 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11543 | WSIGNALED i | WSTOPPED i ->
11544 failwith (\"external virt-inspector command died or stopped on sig \" ^
11549 Xml.parse_string doc in
11550 parse_operatingsystems xml
11553 (* This is used to generate the src/MAX_PROC_NR file which
11554 * contains the maximum procedure number, a surrogate for the
11555 * ABI version number. See src/Makefile.am for the details.
11557 and generate_max_proc_nr () =
11558 let proc_nrs = List.map (
11559 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11560 ) daemon_functions in
11562 let max_proc_nr = List.fold_left max 0 proc_nrs in
11564 pr "%d\n" max_proc_nr
11566 let output_to filename k =
11567 let filename_new = filename ^ ".new" in
11568 chan := open_out filename_new;
11571 chan := Pervasives.stdout;
11573 (* Is the new file different from the current file? *)
11574 if Sys.file_exists filename && files_equal filename filename_new then
11575 unlink filename_new (* same, so skip it *)
11577 (* different, overwrite old one *)
11578 (try chmod filename 0o644 with Unix_error _ -> ());
11579 rename filename_new filename;
11580 chmod filename 0o444;
11581 printf "written %s\n%!" filename;
11584 let perror msg = function
11585 | Unix_error (err, _, _) ->
11586 eprintf "%s: %s\n" msg (error_message err)
11588 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11590 (* Main program. *)
11593 try openfile "HACKING" [O_RDWR] 0
11595 | Unix_error (ENOENT, _, _) ->
11597 You are probably running this from the wrong directory.
11598 Run it from the top source directory using the command
11603 perror "open: HACKING" exn;
11606 (* Acquire a lock so parallel builds won't try to run the generator
11607 * twice at the same time. Subsequent builds will wait for the first
11608 * one to finish. Note the lock is released implicitly when the
11611 (try lockf lock_fd F_LOCK 1
11613 perror "lock: HACKING" exn;
11616 check_functions ();
11618 output_to "src/guestfs_protocol.x" generate_xdr;
11619 output_to "src/guestfs-structs.h" generate_structs_h;
11620 output_to "src/guestfs-actions.h" generate_actions_h;
11621 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11622 output_to "src/guestfs-actions.c" generate_client_actions;
11623 output_to "src/guestfs-bindtests.c" generate_bindtests;
11624 output_to "src/guestfs-structs.pod" generate_structs_pod;
11625 output_to "src/guestfs-actions.pod" generate_actions_pod;
11626 output_to "src/guestfs-availability.pod" generate_availability_pod;
11627 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11628 output_to "src/libguestfs.syms" generate_linker_script;
11629 output_to "daemon/actions.h" generate_daemon_actions_h;
11630 output_to "daemon/stubs.c" generate_daemon_actions;
11631 output_to "daemon/names.c" generate_daemon_names;
11632 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11633 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11634 output_to "capitests/tests.c" generate_tests;
11635 output_to "fish/cmds.c" generate_fish_cmds;
11636 output_to "fish/completion.c" generate_fish_completion;
11637 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11638 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11639 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11640 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11641 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11642 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11643 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11644 output_to "perl/Guestfs.xs" generate_perl_xs;
11645 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11646 output_to "perl/bindtests.pl" generate_perl_bindtests;
11647 output_to "python/guestfs-py.c" generate_python_c;
11648 output_to "python/guestfs.py" generate_python_py;
11649 output_to "python/bindtests.py" generate_python_bindtests;
11650 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11651 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11652 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11656 let cols = cols_of_struct typ in
11657 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11658 output_to filename (generate_java_struct jtyp cols);
11661 output_to "java/Makefile.inc" generate_java_makefile_inc;
11662 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11663 output_to "java/Bindtests.java" generate_java_bindtests;
11664 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11665 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11666 output_to "csharp/Libguestfs.cs" generate_csharp;
11668 (* Always generate this file last, and unconditionally. It's used
11669 * by the Makefile to know when we must re-run the generator.
11671 let chan = open_out "src/stamp-generator" in
11672 fprintf chan "1\n";
11675 printf "generated %d lines of code\n" !lines