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.
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly. This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability. Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
971 ("sync", (RErr, []), 2, [],
972 [ InitEmpty, Always, TestRun [["sync"]]],
973 "sync disks, writes are flushed through to the disk image",
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
981 ("touch", (RErr, [Pathname "path"]), 3, [],
982 [InitBasicFS, Always, TestOutputTrue (
984 ["exists"; "/new"]])],
985 "update file timestamps or create a new file",
987 Touch acts like the L<touch(1)> command. It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
991 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992 [InitISOFS, Always, TestOutput (
993 [["cat"; "/known-2"]], "abcdef\n")],
994 "list the contents of a file",
996 Return the contents of the file named C<path>.
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string). For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1003 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004 [], (* XXX Tricky to test because it depends on the exact format
1005 * of the 'ls -l' command, which changes between F10 and F11.
1007 "list the files in a directory (long format)",
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1012 This command is mostly useful for interactive sessions. It
1013 is I<not> intended that you try to parse the output string.");
1015 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016 [InitBasicFS, Always, TestOutputList (
1018 ["touch"; "/newer"];
1019 ["touch"; "/newest"];
1020 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021 "list the files in a directory",
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd). The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1027 This command is mostly useful for interactive sessions. Programs
1028 should probably use C<guestfs_readdir> instead.");
1030 ("list_devices", (RStringList "devices", []), 7, [],
1031 [InitEmpty, Always, TestOutputListOfDevices (
1032 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033 "list the block devices",
1035 List all the block devices.
1037 The full block device names are returned, eg. C</dev/sda>");
1039 ("list_partitions", (RStringList "partitions", []), 8, [],
1040 [InitBasicFS, Always, TestOutputListOfDevices (
1041 [["list_partitions"]], ["/dev/sda1"]);
1042 InitEmpty, Always, TestOutputListOfDevices (
1043 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045 "list the partitions",
1047 List all the partitions detected on all block devices.
1049 The full partition device names are returned, eg. C</dev/sda1>
1051 This does not return logical volumes. For that you will need to
1052 call C<guestfs_lvs>.");
1054 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056 [["pvs"]], ["/dev/sda1"]);
1057 InitEmpty, Always, TestOutputListOfDevices (
1058 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059 ["pvcreate"; "/dev/sda1"];
1060 ["pvcreate"; "/dev/sda2"];
1061 ["pvcreate"; "/dev/sda3"];
1062 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063 "list the LVM physical volumes (PVs)",
1065 List all the physical volumes detected. This is the equivalent
1066 of the L<pvs(8)> command.
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1071 See also C<guestfs_pvs_full>.");
1073 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074 [InitBasicFSonLVM, Always, TestOutputList (
1076 InitEmpty, Always, TestOutputList (
1077 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078 ["pvcreate"; "/dev/sda1"];
1079 ["pvcreate"; "/dev/sda2"];
1080 ["pvcreate"; "/dev/sda3"];
1081 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082 ["vgcreate"; "VG2"; "/dev/sda3"];
1083 ["vgs"]], ["VG1"; "VG2"])],
1084 "list the LVM volume groups (VGs)",
1086 List all the volumes groups detected. This is the equivalent
1087 of the L<vgs(8)> command.
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1092 See also C<guestfs_vgs_full>.");
1094 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095 [InitBasicFSonLVM, Always, TestOutputList (
1096 [["lvs"]], ["/dev/VG/LV"]);
1097 InitEmpty, Always, TestOutputList (
1098 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099 ["pvcreate"; "/dev/sda1"];
1100 ["pvcreate"; "/dev/sda2"];
1101 ["pvcreate"; "/dev/sda3"];
1102 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103 ["vgcreate"; "VG2"; "/dev/sda3"];
1104 ["lvcreate"; "LV1"; "VG1"; "50"];
1105 ["lvcreate"; "LV2"; "VG1"; "50"];
1106 ["lvcreate"; "LV3"; "VG2"; "50"];
1107 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108 "list the LVM logical volumes (LVs)",
1110 List all the logical volumes detected. This is the equivalent
1111 of the L<lvs(8)> command.
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1116 See also C<guestfs_lvs_full>.");
1118 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119 [], (* XXX how to test? *)
1120 "list the LVM physical volumes (PVs)",
1122 List all the physical volumes detected. This is the equivalent
1123 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1125 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM volume groups (VGs)",
1129 List all the volumes groups detected. This is the equivalent
1130 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1132 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133 [], (* XXX how to test? *)
1134 "list the LVM logical volumes (LVs)",
1136 List all the logical volumes detected. This is the equivalent
1137 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1139 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140 [InitISOFS, Always, TestOutputList (
1141 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142 InitISOFS, Always, TestOutputList (
1143 [["read_lines"; "/empty"]], [])],
1144 "read file as lines",
1146 Return the contents of the file named C<path>.
1148 The file contents are returned as a list of lines. Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line). For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1156 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157 [], (* XXX Augeas code needs tests. *)
1158 "create a new Augeas handle",
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1164 You must call this before using any other C<guestfs_aug_*>
1167 C<root> is the filesystem root. C<root> must not be NULL,
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1176 =item C<AUG_SAVE_BACKUP> = 1
1178 Keep the original file with a C<.augsave> extension.
1180 =item C<AUG_SAVE_NEWFILE> = 2
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1185 =item C<AUG_TYPE_CHECK> = 4
1187 Typecheck lenses (can be expensive).
1189 =item C<AUG_NO_STDINC> = 8
1191 Do not use standard load path for modules.
1193 =item C<AUG_SAVE_NOOP> = 16
1195 Make save a no-op, just record what would have been changed.
1197 =item C<AUG_NO_LOAD> = 32
1199 Do not load the tree in C<guestfs_aug_init>.
1203 To close the handle, you can call C<guestfs_aug_close>.
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1207 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208 [], (* XXX Augeas code needs tests. *)
1209 "close the current Augeas handle",
1211 Close the current Augeas handle and free up any resources
1212 used by it. After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1216 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217 [], (* XXX Augeas code needs tests. *)
1218 "define an Augeas variable",
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1227 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228 [], (* XXX Augeas code needs tests. *)
1229 "define an Augeas node",
1231 Defines a variable C<name> whose value is the result of
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1242 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "look up the value of an Augeas path",
1246 Look up the value associated with C<path>. If C<path>
1247 matches exactly one node, the C<value> is returned.");
1249 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250 [], (* XXX Augeas code needs tests. *)
1251 "set Augeas path to value",
1253 Set the value associated with C<path> to C<val>.
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL. Due to an oversight in the libguestfs API
1257 you cannot do that with this call. Instead you must use the
1258 C<guestfs_aug_clear> call.");
1260 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261 [], (* XXX Augeas code needs tests. *)
1262 "insert a sibling Augeas node",
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1272 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273 [], (* XXX Augeas code needs tests. *)
1274 "remove an Augeas path",
1276 Remove C<path> and all of its children.
1278 On success this returns the number of entries which were removed.");
1280 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1284 Move the node C<src> to C<dest>. C<src> must match exactly
1285 one node. C<dest> is overwritten if it exists.");
1287 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1289 "return Augeas nodes which match augpath",
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1295 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296 [], (* XXX Augeas code needs tests. *)
1297 "write all pending Augeas changes to disk",
1299 This writes all pending changes to disk.
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1304 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305 [], (* XXX Augeas code needs tests. *)
1306 "load files into the tree",
1308 Load files into the tree.
1310 See C<aug_load> in the Augeas documentation for the full gory
1313 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314 [], (* XXX Augeas code needs tests. *)
1315 "list Augeas nodes under augpath",
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1320 ("rm", (RErr, [Pathname "path"]), 29, [],
1321 [InitBasicFS, Always, TestRun
1324 InitBasicFS, Always, TestLastFail
1326 InitBasicFS, Always, TestLastFail
1331 Remove the single file C<path>.");
1333 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334 [InitBasicFS, Always, TestRun
1337 InitBasicFS, Always, TestLastFail
1338 [["rmdir"; "/new"]];
1339 InitBasicFS, Always, TestLastFail
1341 ["rmdir"; "/new"]]],
1342 "remove a directory",
1344 Remove the single directory C<path>.");
1346 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347 [InitBasicFS, Always, TestOutputFalse
1349 ["mkdir"; "/new/foo"];
1350 ["touch"; "/new/foo/bar"];
1352 ["exists"; "/new"]]],
1353 "remove a file or directory recursively",
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory. This is like the C<rm -rf> shell
1359 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360 [InitBasicFS, Always, TestOutputTrue
1362 ["is_dir"; "/new"]];
1363 InitBasicFS, Always, TestLastFail
1364 [["mkdir"; "/new/foo/bar"]]],
1365 "create a directory",
1367 Create a directory named C<path>.");
1369 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370 [InitBasicFS, Always, TestOutputTrue
1371 [["mkdir_p"; "/new/foo/bar"];
1372 ["is_dir"; "/new/foo/bar"]];
1373 InitBasicFS, Always, TestOutputTrue
1374 [["mkdir_p"; "/new/foo/bar"];
1375 ["is_dir"; "/new/foo"]];
1376 InitBasicFS, Always, TestOutputTrue
1377 [["mkdir_p"; "/new/foo/bar"];
1378 ["is_dir"; "/new"]];
1379 (* Regression tests for RHBZ#503133: *)
1380 InitBasicFS, Always, TestRun
1382 ["mkdir_p"; "/new"]];
1383 InitBasicFS, Always, TestLastFail
1385 ["mkdir_p"; "/new"]]],
1386 "create a directory and parents",
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary. This is like the C<mkdir -p> shell command.");
1391 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392 [], (* XXX Need stat command to test *)
1395 Change the mode (permissions) of C<path> to C<mode>. Only
1396 numeric modes are supported.
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1402 The mode actually set is affected by the umask.");
1404 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405 [], (* XXX Need stat command to test *)
1406 "change file owner and group",
1408 Change the file owner to C<owner> and group to C<group>.
1410 Only numeric uid and gid are supported. If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1414 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415 [InitISOFS, Always, TestOutputTrue (
1416 [["exists"; "/empty"]]);
1417 InitISOFS, Always, TestOutputTrue (
1418 [["exists"; "/directory"]])],
1419 "test if file or directory exists",
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1426 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427 [InitISOFS, Always, TestOutputTrue (
1428 [["is_file"; "/known-1"]]);
1429 InitISOFS, Always, TestOutputFalse (
1430 [["is_file"; "/directory"]])],
1431 "test if file exists",
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name. Note that it returns false for
1435 other objects like directories.
1437 See also C<guestfs_stat>.");
1439 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440 [InitISOFS, Always, TestOutputFalse (
1441 [["is_dir"; "/known-3"]]);
1442 InitISOFS, Always, TestOutputTrue (
1443 [["is_dir"; "/directory"]])],
1444 "test if file exists",
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name. Note that it returns false for
1448 other objects like files.
1450 See also C<guestfs_stat>.");
1452 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453 [InitEmpty, Always, TestOutputListOfDevices (
1454 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455 ["pvcreate"; "/dev/sda1"];
1456 ["pvcreate"; "/dev/sda2"];
1457 ["pvcreate"; "/dev/sda3"];
1458 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459 "create an LVM physical volume",
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1465 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466 [InitEmpty, Always, TestOutputList (
1467 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468 ["pvcreate"; "/dev/sda1"];
1469 ["pvcreate"; "/dev/sda2"];
1470 ["pvcreate"; "/dev/sda3"];
1471 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472 ["vgcreate"; "VG2"; "/dev/sda3"];
1473 ["vgs"]], ["VG1"; "VG2"])],
1474 "create an LVM volume group",
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1479 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480 [InitEmpty, Always, TestOutputList (
1481 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482 ["pvcreate"; "/dev/sda1"];
1483 ["pvcreate"; "/dev/sda2"];
1484 ["pvcreate"; "/dev/sda3"];
1485 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486 ["vgcreate"; "VG2"; "/dev/sda3"];
1487 ["lvcreate"; "LV1"; "VG1"; "50"];
1488 ["lvcreate"; "LV2"; "VG1"; "50"];
1489 ["lvcreate"; "LV3"; "VG2"; "50"];
1490 ["lvcreate"; "LV4"; "VG2"; "50"];
1491 ["lvcreate"; "LV5"; "VG2"; "50"];
1493 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495 "create an LVM logical volume",
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1500 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501 [InitEmpty, Always, TestOutput (
1502 [["part_disk"; "/dev/sda"; "mbr"];
1503 ["mkfs"; "ext2"; "/dev/sda1"];
1504 ["mount_options"; ""; "/dev/sda1"; "/"];
1505 ["write_file"; "/new"; "new file contents"; "0"];
1506 ["cat"; "/new"]], "new file contents")],
1507 "make a filesystem",
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume). The filesystem type is C<fstype>, for
1513 ("sfdisk", (RErr, [Device "device";
1514 Int "cyls"; Int "heads"; Int "sectors";
1515 StringList "lines"]), 43, [DangerWillRobinson],
1517 "create partitions on a block device",
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1522 C<device> should be a block device, for example C</dev/sda>.
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted. Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1532 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1533 information refer to the L<sfdisk(8)> manpage.
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1542 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543 [InitBasicFS, Always, TestOutput (
1544 [["write_file"; "/new"; "new file contents"; "0"];
1545 ["cat"; "/new"]], "new file contents");
1546 InitBasicFS, Always, TestOutput (
1547 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548 ["cat"; "/new"]], "\nnew file contents\n");
1549 InitBasicFS, Always, TestOutput (
1550 [["write_file"; "/new"; "\n\n"; "0"];
1551 ["cat"; "/new"]], "\n\n");
1552 InitBasicFS, Always, TestOutput (
1553 [["write_file"; "/new"; ""; "0"];
1554 ["cat"; "/new"]], "");
1555 InitBasicFS, Always, TestOutput (
1556 [["write_file"; "/new"; "\n\n\n"; "0"];
1557 ["cat"; "/new"]], "\n\n\n");
1558 InitBasicFS, Always, TestOutput (
1559 [["write_file"; "/new"; "\n"; "0"];
1560 ["cat"; "/new"]], "\n")],
1563 This call creates a file called C<path>. The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version. In the meantime
1574 use C<guestfs_upload>.");
1576 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577 [InitEmpty, Always, TestOutputListOfDevices (
1578 [["part_disk"; "/dev/sda"; "mbr"];
1579 ["mkfs"; "ext2"; "/dev/sda1"];
1580 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 ["mounts"]], ["/dev/sda1"]);
1582 InitEmpty, Always, TestOutputList (
1583 [["part_disk"; "/dev/sda"; "mbr"];
1584 ["mkfs"; "ext2"; "/dev/sda1"];
1585 ["mount_options"; ""; "/dev/sda1"; "/"];
1588 "unmount a filesystem",
1590 This unmounts the given filesystem. The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1594 ("mounts", (RStringList "devices", []), 46, [],
1595 [InitBasicFS, Always, TestOutputListOfDevices (
1596 [["mounts"]], ["/dev/sda1"])],
1597 "show mounted filesystems",
1599 This returns the list of currently mounted filesystems. It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1602 Some internal mounts are not shown.
1604 See also: C<guestfs_mountpoints>");
1606 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607 [InitBasicFS, Always, TestOutputList (
1610 (* check that umount_all can unmount nested mounts correctly: *)
1611 InitEmpty, Always, TestOutputList (
1612 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613 ["mkfs"; "ext2"; "/dev/sda1"];
1614 ["mkfs"; "ext2"; "/dev/sda2"];
1615 ["mkfs"; "ext2"; "/dev/sda3"];
1616 ["mount_options"; ""; "/dev/sda1"; "/"];
1618 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619 ["mkdir"; "/mp1/mp2"];
1620 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621 ["mkdir"; "/mp1/mp2/mp3"];
1624 "unmount all filesystems",
1626 This unmounts all mounted filesystems.
1628 Some internal mounts are not unmounted by this call.");
1630 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1632 "remove all LVM LVs, VGs and PVs",
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1637 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638 [InitISOFS, Always, TestOutput (
1639 [["file"; "/empty"]], "empty");
1640 InitISOFS, Always, TestOutput (
1641 [["file"; "/known-1"]], "ASCII text");
1642 InitISOFS, Always, TestLastFail (
1643 [["file"; "/notexists"]])],
1644 "determine file type",
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file. This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1650 This call will also transparently look inside various types
1653 The exact command which runs is C<file -zbsL path>. Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1657 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658 [InitBasicFS, Always, TestOutput (
1659 [["upload"; "test-command"; "/test-command"];
1660 ["chmod"; "0o755"; "/test-command"];
1661 ["command"; "/test-command 1"]], "Result1");
1662 InitBasicFS, Always, TestOutput (
1663 [["upload"; "test-command"; "/test-command"];
1664 ["chmod"; "0o755"; "/test-command"];
1665 ["command"; "/test-command 2"]], "Result2\n");
1666 InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 3"]], "\nResult3");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 4"]], "\nResult4\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 5"]], "\nResult5\n\n");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682 InitBasicFS, Always, TestOutput (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command 7"]], "");
1686 InitBasicFS, Always, TestOutput (
1687 [["upload"; "test-command"; "/test-command"];
1688 ["chmod"; "0o755"; "/test-command"];
1689 ["command"; "/test-command 8"]], "\n");
1690 InitBasicFS, Always, TestOutput (
1691 [["upload"; "test-command"; "/test-command"];
1692 ["chmod"; "0o755"; "/test-command"];
1693 ["command"; "/test-command 9"]], "\n\n");
1694 InitBasicFS, Always, TestOutput (
1695 [["upload"; "test-command"; "/test-command"];
1696 ["chmod"; "0o755"; "/test-command"];
1697 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698 InitBasicFS, Always, TestOutput (
1699 [["upload"; "test-command"; "/test-command"];
1700 ["chmod"; "0o755"; "/test-command"];
1701 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702 InitBasicFS, Always, TestLastFail (
1703 [["upload"; "test-command"; "/test-command"];
1704 ["chmod"; "0o755"; "/test-command"];
1705 ["command"; "/test-command"]])],
1706 "run a command from the guest filesystem",
1708 This call runs a command from the guest filesystem. The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters. The list must be
1716 non-empty (ie. must contain a program name). Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1720 The return value is anything printed to I<stdout> by
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message. The error message
1725 string is the content of I<stderr> from the command.
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>. If you require a program from
1729 another location, you should provide the full path in the
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places. It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1738 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739 [InitBasicFS, Always, TestOutputList (
1740 [["upload"; "test-command"; "/test-command"];
1741 ["chmod"; "0o755"; "/test-command"];
1742 ["command_lines"; "/test-command 1"]], ["Result1"]);
1743 InitBasicFS, Always, TestOutputList (
1744 [["upload"; "test-command"; "/test-command"];
1745 ["chmod"; "0o755"; "/test-command"];
1746 ["command_lines"; "/test-command 2"]], ["Result2"]);
1747 InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763 InitBasicFS, Always, TestOutputList (
1764 [["upload"; "test-command"; "/test-command"];
1765 ["chmod"; "0o755"; "/test-command"];
1766 ["command_lines"; "/test-command 7"]], []);
1767 InitBasicFS, Always, TestOutputList (
1768 [["upload"; "test-command"; "/test-command"];
1769 ["chmod"; "0o755"; "/test-command"];
1770 ["command_lines"; "/test-command 8"]], [""]);
1771 InitBasicFS, Always, TestOutputList (
1772 [["upload"; "test-command"; "/test-command"];
1773 ["chmod"; "0o755"; "/test-command"];
1774 ["command_lines"; "/test-command 9"]], ["";""]);
1775 InitBasicFS, Always, TestOutputList (
1776 [["upload"; "test-command"; "/test-command"];
1777 ["chmod"; "0o755"; "/test-command"];
1778 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779 InitBasicFS, Always, TestOutputList (
1780 [["upload"; "test-command"; "/test-command"];
1781 ["chmod"; "0o755"; "/test-command"];
1782 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783 "run a command, returning lines",
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1788 See also: C<guestfs_sh_lines>");
1790 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791 [InitISOFS, Always, TestOutputStruct (
1792 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793 "get file information",
1795 Returns file information for the given C<path>.
1797 This is the same as the C<stat(2)> system call.");
1799 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800 [InitISOFS, Always, TestOutputStruct (
1801 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802 "get file information for a symbolic link",
1804 Returns file information for the given C<path>.
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1810 This is the same as the C<lstat(2)> system call.");
1812 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813 [InitISOFS, Always, TestOutputStruct (
1814 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815 "get file system statistics",
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1821 This is the same as the C<statvfs(2)> system call.");
1823 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1825 "get ext2/ext3/ext4 superblock details",
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1830 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1831 manpage for more details. The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1835 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836 [InitEmpty, Always, TestOutputTrue (
1837 [["blockdev_setro"; "/dev/sda"];
1838 ["blockdev_getro"; "/dev/sda"]])],
1839 "set block device to read-only",
1841 Sets the block device named C<device> to read-only.
1843 This uses the L<blockdev(8)> command.");
1845 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846 [InitEmpty, Always, TestOutputFalse (
1847 [["blockdev_setrw"; "/dev/sda"];
1848 ["blockdev_getro"; "/dev/sda"]])],
1849 "set block device to read-write",
1851 Sets the block device named C<device> to read-write.
1853 This uses the L<blockdev(8)> command.");
1855 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856 [InitEmpty, Always, TestOutputTrue (
1857 [["blockdev_setro"; "/dev/sda"];
1858 ["blockdev_getro"; "/dev/sda"]])],
1859 "is block device set to read-only",
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1864 This uses the L<blockdev(8)> command.");
1866 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867 [InitEmpty, Always, TestOutputInt (
1868 [["blockdev_getss"; "/dev/sda"]], 512)],
1869 "get sectorsize of block device",
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1877 This uses the L<blockdev(8)> command.");
1879 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880 [InitEmpty, Always, TestOutputInt (
1881 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882 "get blocksize of block device",
1884 This returns the block size of a device.
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1889 This uses the L<blockdev(8)> command.");
1891 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1893 "set blocksize of block device",
1895 This sets the block size of a device.
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1900 This uses the L<blockdev(8)> command.");
1902 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903 [InitEmpty, Always, TestOutputInt (
1904 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905 "get total size of device in 512-byte sectors",
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1914 This uses the L<blockdev(8)> command.");
1916 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917 [InitEmpty, Always, TestOutputInt (
1918 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919 "get total size of device in bytes",
1921 This returns the size of the device in bytes.
1923 See also C<guestfs_blockdev_getsz>.
1925 This uses the L<blockdev(8)> command.");
1927 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928 [InitEmpty, Always, TestRun
1929 [["blockdev_flushbufs"; "/dev/sda"]]],
1930 "flush device buffers",
1932 This tells the kernel to flush internal buffers associated
1935 This uses the L<blockdev(8)> command.");
1937 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938 [InitEmpty, Always, TestRun
1939 [["blockdev_rereadpt"; "/dev/sda"]]],
1940 "reread partition table",
1942 Reread the partition table on C<device>.
1944 This uses the L<blockdev(8)> command.");
1946 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947 [InitBasicFS, Always, TestOutput (
1948 (* Pick a file from cwd which isn't likely to change. *)
1949 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950 ["checksum"; "md5"; "/COPYING.LIB"]],
1951 Digest.to_hex (Digest.file "COPYING.LIB"))],
1952 "upload a file from the local machine",
1954 Upload local file C<filename> to C<remotefilename> on the
1957 C<filename> can also be a named pipe.
1959 See also C<guestfs_download>.");
1961 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962 [InitBasicFS, Always, TestOutput (
1963 (* Pick a file from cwd which isn't likely to change. *)
1964 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966 ["upload"; "testdownload.tmp"; "/upload"];
1967 ["checksum"; "md5"; "/upload"]],
1968 Digest.to_hex (Digest.file "COPYING.LIB"))],
1969 "download a file to the local machine",
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1974 C<filename> can also be a named pipe.
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1978 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979 [InitISOFS, Always, TestOutput (
1980 [["checksum"; "crc"; "/known-3"]], "2891671662");
1981 InitISOFS, Always, TestLastFail (
1982 [["checksum"; "crc"; "/notexists"]]);
1983 InitISOFS, Always, TestOutput (
1984 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985 InitISOFS, Always, TestOutput (
1986 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987 InitISOFS, Always, TestOutput (
1988 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989 InitISOFS, Always, TestOutput (
1990 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991 InitISOFS, Always, TestOutput (
1992 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993 InitISOFS, Always, TestOutput (
1994 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1995 "compute MD5, SHAx or CRC checksum of file",
1997 This call computes the MD5, SHAx or CRC checksum of the
2000 The type of checksum to compute is given by the C<csumtype>
2001 parameter which must have one of the following values:
2007 Compute the cyclic redundancy check (CRC) specified by POSIX
2008 for the C<cksum> command.
2012 Compute the MD5 hash (using the C<md5sum> program).
2016 Compute the SHA1 hash (using the C<sha1sum> program).
2020 Compute the SHA224 hash (using the C<sha224sum> program).
2024 Compute the SHA256 hash (using the C<sha256sum> program).
2028 Compute the SHA384 hash (using the C<sha384sum> program).
2032 Compute the SHA512 hash (using the C<sha512sum> program).
2036 The checksum is returned as a printable string.
2038 To get the checksum for a device, use C<guestfs_checksum_device>.
2040 To get the checksums for many files, use C<guestfs_checksums_out>.");
2042 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2043 [InitBasicFS, Always, TestOutput (
2044 [["tar_in"; "../images/helloworld.tar"; "/"];
2045 ["cat"; "/hello"]], "hello\n")],
2046 "unpack tarfile to directory",
2048 This command uploads and unpacks local file C<tarfile> (an
2049 I<uncompressed> tar file) into C<directory>.
2051 To upload a compressed tarball, use C<guestfs_tgz_in>
2052 or C<guestfs_txz_in>.");
2054 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2056 "pack directory into tarfile",
2058 This command packs the contents of C<directory> and downloads
2059 it to local file C<tarfile>.
2061 To download a compressed tarball, use C<guestfs_tgz_out>
2062 or C<guestfs_txz_out>.");
2064 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2065 [InitBasicFS, Always, TestOutput (
2066 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2067 ["cat"; "/hello"]], "hello\n")],
2068 "unpack compressed tarball to directory",
2070 This command uploads and unpacks local file C<tarball> (a
2071 I<gzip compressed> tar file) into C<directory>.
2073 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2075 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2077 "pack directory into compressed tarball",
2079 This command packs the contents of C<directory> and downloads
2080 it to local file C<tarball>.
2082 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2084 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2085 [InitBasicFS, Always, TestLastFail (
2087 ["mount_ro"; "/dev/sda1"; "/"];
2088 ["touch"; "/new"]]);
2089 InitBasicFS, Always, TestOutput (
2090 [["write_file"; "/new"; "data"; "0"];
2092 ["mount_ro"; "/dev/sda1"; "/"];
2093 ["cat"; "/new"]], "data")],
2094 "mount a guest disk, read-only",
2096 This is the same as the C<guestfs_mount> command, but it
2097 mounts the filesystem with the read-only (I<-o ro>) flag.");
2099 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2101 "mount a guest disk with mount options",
2103 This is the same as the C<guestfs_mount> command, but it
2104 allows you to set the mount options as for the
2105 L<mount(8)> I<-o> flag.
2107 If the C<options> parameter is an empty string, then
2108 no options are passed (all options default to whatever
2109 the filesystem uses).");
2111 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2113 "mount a guest disk with mount options and vfstype",
2115 This is the same as the C<guestfs_mount> command, but it
2116 allows you to set both the mount options and the vfstype
2117 as for the L<mount(8)> I<-o> and I<-t> flags.");
2119 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2121 "debugging and internals",
2123 The C<guestfs_debug> command exposes some internals of
2124 C<guestfsd> (the guestfs daemon) that runs inside the
2127 There is no comprehensive help for this command. You have
2128 to look at the file C<daemon/debug.c> in the libguestfs source
2129 to find out what you can do.");
2131 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2132 [InitEmpty, Always, TestOutputList (
2133 [["part_disk"; "/dev/sda"; "mbr"];
2134 ["pvcreate"; "/dev/sda1"];
2135 ["vgcreate"; "VG"; "/dev/sda1"];
2136 ["lvcreate"; "LV1"; "VG"; "50"];
2137 ["lvcreate"; "LV2"; "VG"; "50"];
2138 ["lvremove"; "/dev/VG/LV1"];
2139 ["lvs"]], ["/dev/VG/LV2"]);
2140 InitEmpty, Always, TestOutputList (
2141 [["part_disk"; "/dev/sda"; "mbr"];
2142 ["pvcreate"; "/dev/sda1"];
2143 ["vgcreate"; "VG"; "/dev/sda1"];
2144 ["lvcreate"; "LV1"; "VG"; "50"];
2145 ["lvcreate"; "LV2"; "VG"; "50"];
2146 ["lvremove"; "/dev/VG"];
2148 InitEmpty, Always, TestOutputList (
2149 [["part_disk"; "/dev/sda"; "mbr"];
2150 ["pvcreate"; "/dev/sda1"];
2151 ["vgcreate"; "VG"; "/dev/sda1"];
2152 ["lvcreate"; "LV1"; "VG"; "50"];
2153 ["lvcreate"; "LV2"; "VG"; "50"];
2154 ["lvremove"; "/dev/VG"];
2156 "remove an LVM logical volume",
2158 Remove an LVM logical volume C<device>, where C<device> is
2159 the path to the LV, such as C</dev/VG/LV>.
2161 You can also remove all LVs in a volume group by specifying
2162 the VG name, C</dev/VG>.");
2164 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2165 [InitEmpty, Always, TestOutputList (
2166 [["part_disk"; "/dev/sda"; "mbr"];
2167 ["pvcreate"; "/dev/sda1"];
2168 ["vgcreate"; "VG"; "/dev/sda1"];
2169 ["lvcreate"; "LV1"; "VG"; "50"];
2170 ["lvcreate"; "LV2"; "VG"; "50"];
2173 InitEmpty, Always, TestOutputList (
2174 [["part_disk"; "/dev/sda"; "mbr"];
2175 ["pvcreate"; "/dev/sda1"];
2176 ["vgcreate"; "VG"; "/dev/sda1"];
2177 ["lvcreate"; "LV1"; "VG"; "50"];
2178 ["lvcreate"; "LV2"; "VG"; "50"];
2181 "remove an LVM volume group",
2183 Remove an LVM volume group C<vgname>, (for example C<VG>).
2185 This also forcibly removes all logical volumes in the volume
2188 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2189 [InitEmpty, Always, TestOutputListOfDevices (
2190 [["part_disk"; "/dev/sda"; "mbr"];
2191 ["pvcreate"; "/dev/sda1"];
2192 ["vgcreate"; "VG"; "/dev/sda1"];
2193 ["lvcreate"; "LV1"; "VG"; "50"];
2194 ["lvcreate"; "LV2"; "VG"; "50"];
2196 ["pvremove"; "/dev/sda1"];
2198 InitEmpty, Always, TestOutputListOfDevices (
2199 [["part_disk"; "/dev/sda"; "mbr"];
2200 ["pvcreate"; "/dev/sda1"];
2201 ["vgcreate"; "VG"; "/dev/sda1"];
2202 ["lvcreate"; "LV1"; "VG"; "50"];
2203 ["lvcreate"; "LV2"; "VG"; "50"];
2205 ["pvremove"; "/dev/sda1"];
2207 InitEmpty, Always, TestOutputListOfDevices (
2208 [["part_disk"; "/dev/sda"; "mbr"];
2209 ["pvcreate"; "/dev/sda1"];
2210 ["vgcreate"; "VG"; "/dev/sda1"];
2211 ["lvcreate"; "LV1"; "VG"; "50"];
2212 ["lvcreate"; "LV2"; "VG"; "50"];
2214 ["pvremove"; "/dev/sda1"];
2216 "remove an LVM physical volume",
2218 This wipes a physical volume C<device> so that LVM will no longer
2221 The implementation uses the C<pvremove> command which refuses to
2222 wipe physical volumes that contain any volume groups, so you have
2223 to remove those first.");
2225 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2226 [InitBasicFS, Always, TestOutput (
2227 [["set_e2label"; "/dev/sda1"; "testlabel"];
2228 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2229 "set the ext2/3/4 filesystem label",
2231 This sets the ext2/3/4 filesystem label of the filesystem on
2232 C<device> to C<label>. Filesystem labels are limited to
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2236 to return the existing label on a filesystem.");
2238 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2240 "get the ext2/3/4 filesystem label",
2242 This returns the ext2/3/4 filesystem label of the filesystem on
2245 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2246 (let uuid = uuidgen () in
2247 [InitBasicFS, Always, TestOutput (
2248 [["set_e2uuid"; "/dev/sda1"; uuid];
2249 ["get_e2uuid"; "/dev/sda1"]], uuid);
2250 InitBasicFS, Always, TestOutput (
2251 [["set_e2uuid"; "/dev/sda1"; "clear"];
2252 ["get_e2uuid"; "/dev/sda1"]], "");
2253 (* We can't predict what UUIDs will be, so just check the commands run. *)
2254 InitBasicFS, Always, TestRun (
2255 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2256 InitBasicFS, Always, TestRun (
2257 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2258 "set the ext2/3/4 filesystem UUID",
2260 This sets the ext2/3/4 filesystem UUID of the filesystem on
2261 C<device> to C<uuid>. The format of the UUID and alternatives
2262 such as C<clear>, C<random> and C<time> are described in the
2263 L<tune2fs(8)> manpage.
2265 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2266 to return the existing UUID of a filesystem.");
2268 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2270 "get the ext2/3/4 filesystem UUID",
2272 This returns the ext2/3/4 filesystem UUID of the filesystem on
2275 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2276 [InitBasicFS, Always, TestOutputInt (
2277 [["umount"; "/dev/sda1"];
2278 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2279 InitBasicFS, Always, TestOutputInt (
2280 [["umount"; "/dev/sda1"];
2281 ["zero"; "/dev/sda1"];
2282 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2283 "run the filesystem checker",
2285 This runs the filesystem checker (fsck) on C<device> which
2286 should have filesystem type C<fstype>.
2288 The returned integer is the status. See L<fsck(8)> for the
2289 list of status codes from C<fsck>.
2297 Multiple status codes can be summed together.
2301 A non-zero return code can mean \"success\", for example if
2302 errors have been corrected on the filesystem.
2306 Checking or repairing NTFS volumes is not supported
2311 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2313 ("zero", (RErr, [Device "device"]), 85, [],
2314 [InitBasicFS, Always, TestOutput (
2315 [["umount"; "/dev/sda1"];
2316 ["zero"; "/dev/sda1"];
2317 ["file"; "/dev/sda1"]], "data")],
2318 "write zeroes to the device",
2320 This command writes zeroes over the first few blocks of C<device>.
2322 How many blocks are zeroed isn't specified (but it's I<not> enough
2323 to securely wipe the device). It should be sufficient to remove
2324 any partition tables, filesystem superblocks and so on.
2326 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2328 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2329 (* Test disabled because grub-install incompatible with virtio-blk driver.
2330 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2332 [InitBasicFS, Disabled, TestOutputTrue (
2333 [["grub_install"; "/"; "/dev/sda1"];
2334 ["is_dir"; "/boot"]])],
2337 This command installs GRUB (the Grand Unified Bootloader) on
2338 C<device>, with the root directory being C<root>.");
2340 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2341 [InitBasicFS, Always, TestOutput (
2342 [["write_file"; "/old"; "file content"; "0"];
2343 ["cp"; "/old"; "/new"];
2344 ["cat"; "/new"]], "file content");
2345 InitBasicFS, Always, TestOutputTrue (
2346 [["write_file"; "/old"; "file content"; "0"];
2347 ["cp"; "/old"; "/new"];
2348 ["is_file"; "/old"]]);
2349 InitBasicFS, Always, TestOutput (
2350 [["write_file"; "/old"; "file content"; "0"];
2352 ["cp"; "/old"; "/dir/new"];
2353 ["cat"; "/dir/new"]], "file content")],
2356 This copies a file from C<src> to C<dest> where C<dest> is
2357 either a destination filename or destination directory.");
2359 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2360 [InitBasicFS, Always, TestOutput (
2361 [["mkdir"; "/olddir"];
2362 ["mkdir"; "/newdir"];
2363 ["write_file"; "/olddir/file"; "file content"; "0"];
2364 ["cp_a"; "/olddir"; "/newdir"];
2365 ["cat"; "/newdir/olddir/file"]], "file content")],
2366 "copy a file or directory recursively",
2368 This copies a file or directory from C<src> to C<dest>
2369 recursively using the C<cp -a> command.");
2371 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2372 [InitBasicFS, Always, TestOutput (
2373 [["write_file"; "/old"; "file content"; "0"];
2374 ["mv"; "/old"; "/new"];
2375 ["cat"; "/new"]], "file content");
2376 InitBasicFS, Always, TestOutputFalse (
2377 [["write_file"; "/old"; "file content"; "0"];
2378 ["mv"; "/old"; "/new"];
2379 ["is_file"; "/old"]])],
2382 This moves a file from C<src> to C<dest> where C<dest> is
2383 either a destination filename or destination directory.");
2385 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2386 [InitEmpty, Always, TestRun (
2387 [["drop_caches"; "3"]])],
2388 "drop kernel page cache, dentries and inodes",
2390 This instructs the guest kernel to drop its page cache,
2391 and/or dentries and inode caches. The parameter C<whattodrop>
2392 tells the kernel what precisely to drop, see
2393 L<http://linux-mm.org/Drop_Caches>
2395 Setting C<whattodrop> to 3 should drop everything.
2397 This automatically calls L<sync(2)> before the operation,
2398 so that the maximum guest memory is freed.");
2400 ("dmesg", (RString "kmsgs", []), 91, [],
2401 [InitEmpty, Always, TestRun (
2403 "return kernel messages",
2405 This returns the kernel messages (C<dmesg> output) from
2406 the guest kernel. This is sometimes useful for extended
2407 debugging of problems.
2409 Another way to get the same information is to enable
2410 verbose messages with C<guestfs_set_verbose> or by setting
2411 the environment variable C<LIBGUESTFS_DEBUG=1> before
2412 running the program.");
2414 ("ping_daemon", (RErr, []), 92, [],
2415 [InitEmpty, Always, TestRun (
2416 [["ping_daemon"]])],
2417 "ping the guest daemon",
2419 This is a test probe into the guestfs daemon running inside
2420 the qemu subprocess. Calling this function checks that the
2421 daemon responds to the ping message, without affecting the daemon
2422 or attached block device(s) in any other way.");
2424 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2425 [InitBasicFS, Always, TestOutputTrue (
2426 [["write_file"; "/file1"; "contents of a file"; "0"];
2427 ["cp"; "/file1"; "/file2"];
2428 ["equal"; "/file1"; "/file2"]]);
2429 InitBasicFS, Always, TestOutputFalse (
2430 [["write_file"; "/file1"; "contents of a file"; "0"];
2431 ["write_file"; "/file2"; "contents of another file"; "0"];
2432 ["equal"; "/file1"; "/file2"]]);
2433 InitBasicFS, Always, TestLastFail (
2434 [["equal"; "/file1"; "/file2"]])],
2435 "test if two files have equal contents",
2437 This compares the two files C<file1> and C<file2> and returns
2438 true if their content is exactly equal, or false otherwise.
2440 The external L<cmp(1)> program is used for the comparison.");
2442 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2443 [InitISOFS, Always, TestOutputList (
2444 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2445 InitISOFS, Always, TestOutputList (
2446 [["strings"; "/empty"]], [])],
2447 "print the printable strings in a file",
2449 This runs the L<strings(1)> command on a file and returns
2450 the list of printable strings found.");
2452 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2453 [InitISOFS, Always, TestOutputList (
2454 [["strings_e"; "b"; "/known-5"]], []);
2455 InitBasicFS, Disabled, TestOutputList (
2456 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2457 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2458 "print the printable strings in a file",
2460 This is like the C<guestfs_strings> command, but allows you to
2461 specify the encoding.
2463 See the L<strings(1)> manpage for the full list of encodings.
2465 Commonly useful encodings are C<l> (lower case L) which will
2466 show strings inside Windows/x86 files.
2468 The returned strings are transcoded to UTF-8.");
2470 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2471 [InitISOFS, Always, TestOutput (
2472 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2473 (* Test for RHBZ#501888c2 regression which caused large hexdump
2474 * commands to segfault.
2476 InitISOFS, Always, TestRun (
2477 [["hexdump"; "/100krandom"]]);
2478 (* Test for RHBZ#579608, absolute symbolic links. *)
2479 InitISOFS, Always, TestRun (
2480 [["hexdump"; "/abssymlink"]])],
2481 "dump a file in hexadecimal",
2483 This runs C<hexdump -C> on the given C<path>. The result is
2484 the human-readable, canonical hex dump of the file.");
2486 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2487 [InitNone, Always, TestOutput (
2488 [["part_disk"; "/dev/sda"; "mbr"];
2489 ["mkfs"; "ext3"; "/dev/sda1"];
2490 ["mount_options"; ""; "/dev/sda1"; "/"];
2491 ["write_file"; "/new"; "test file"; "0"];
2492 ["umount"; "/dev/sda1"];
2493 ["zerofree"; "/dev/sda1"];
2494 ["mount_options"; ""; "/dev/sda1"; "/"];
2495 ["cat"; "/new"]], "test file")],
2496 "zero unused inodes and disk blocks on ext2/3 filesystem",
2498 This runs the I<zerofree> program on C<device>. This program
2499 claims to zero unused inodes and disk blocks on an ext2/3
2500 filesystem, thus making it possible to compress the filesystem
2503 You should B<not> run this program if the filesystem is
2506 It is possible that using this program can damage the filesystem
2507 or data on the filesystem.");
2509 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2511 "resize an LVM physical volume",
2513 This resizes (expands or shrinks) an existing LVM physical
2514 volume to match the new size of the underlying device.");
2516 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2517 Int "cyls"; Int "heads"; Int "sectors";
2518 String "line"]), 99, [DangerWillRobinson],
2520 "modify a single partition on a block device",
2522 This runs L<sfdisk(8)> option to modify just the single
2523 partition C<n> (note: C<n> counts from 1).
2525 For other parameters, see C<guestfs_sfdisk>. You should usually
2526 pass C<0> for the cyls/heads/sectors parameters.
2528 See also: C<guestfs_part_add>");
2530 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2532 "display the partition table",
2534 This displays the partition table on C<device>, in the
2535 human-readable output of the L<sfdisk(8)> command. It is
2536 not intended to be parsed.
2538 See also: C<guestfs_part_list>");
2540 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2542 "display the kernel geometry",
2544 This displays the kernel's idea of the geometry of C<device>.
2546 The result is in human-readable format, and not designed to
2549 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2551 "display the disk geometry from the partition table",
2553 This displays the disk geometry of C<device> read from the
2554 partition table. Especially in the case where the underlying
2555 block device has been resized, this can be different from the
2556 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2558 The result is in human-readable format, and not designed to
2561 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2563 "activate or deactivate all volume groups",
2565 This command activates or (if C<activate> is false) deactivates
2566 all logical volumes in all volume groups.
2567 If activated, then they are made known to the
2568 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2569 then those devices disappear.
2571 This command is the same as running C<vgchange -a y|n>");
2573 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2575 "activate or deactivate some volume groups",
2577 This command activates or (if C<activate> is false) deactivates
2578 all logical volumes in the listed volume groups C<volgroups>.
2579 If activated, then they are made known to the
2580 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2581 then those devices disappear.
2583 This command is the same as running C<vgchange -a y|n volgroups...>
2585 Note that if C<volgroups> is an empty list then B<all> volume groups
2586 are activated or deactivated.");
2588 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2589 [InitNone, Always, TestOutput (
2590 [["part_disk"; "/dev/sda"; "mbr"];
2591 ["pvcreate"; "/dev/sda1"];
2592 ["vgcreate"; "VG"; "/dev/sda1"];
2593 ["lvcreate"; "LV"; "VG"; "10"];
2594 ["mkfs"; "ext2"; "/dev/VG/LV"];
2595 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2596 ["write_file"; "/new"; "test content"; "0"];
2598 ["lvresize"; "/dev/VG/LV"; "20"];
2599 ["e2fsck_f"; "/dev/VG/LV"];
2600 ["resize2fs"; "/dev/VG/LV"];
2601 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2602 ["cat"; "/new"]], "test content");
2603 InitNone, Always, TestRun (
2604 (* Make an LV smaller to test RHBZ#587484. *)
2605 [["part_disk"; "/dev/sda"; "mbr"];
2606 ["pvcreate"; "/dev/sda1"];
2607 ["vgcreate"; "VG"; "/dev/sda1"];
2608 ["lvcreate"; "LV"; "VG"; "20"];
2609 ["lvresize"; "/dev/VG/LV"; "10"]])],
2610 "resize an LVM logical volume",
2612 This resizes (expands or shrinks) an existing LVM logical
2613 volume to C<mbytes>. When reducing, data in the reduced part
2616 ("resize2fs", (RErr, [Device "device"]), 106, [],
2617 [], (* lvresize tests this *)
2618 "resize an ext2/ext3 filesystem",
2620 This resizes an ext2 or ext3 filesystem to match the size of
2621 the underlying device.
2623 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2624 on the C<device> before calling this command. For unknown reasons
2625 C<resize2fs> sometimes gives an error about this and sometimes not.
2626 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2627 calling this function.");
2629 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2630 [InitBasicFS, Always, TestOutputList (
2631 [["find"; "/"]], ["lost+found"]);
2632 InitBasicFS, Always, TestOutputList (
2636 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2637 InitBasicFS, Always, TestOutputList (
2638 [["mkdir_p"; "/a/b/c"];
2639 ["touch"; "/a/b/c/d"];
2640 ["find"; "/a/b/"]], ["c"; "c/d"])],
2641 "find all files and directories",
2643 This command lists out all files and directories, recursively,
2644 starting at C<directory>. It is essentially equivalent to
2645 running the shell command C<find directory -print> but some
2646 post-processing happens on the output, described below.
2648 This returns a list of strings I<without any prefix>. Thus
2649 if the directory structure was:
2655 then the returned list from C<guestfs_find> C</tmp> would be
2663 If C<directory> is not a directory, then this command returns
2666 The returned list is sorted.
2668 See also C<guestfs_find0>.");
2670 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2671 [], (* lvresize tests this *)
2672 "check an ext2/ext3 filesystem",
2674 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2675 filesystem checker on C<device>, noninteractively (C<-p>),
2676 even if the filesystem appears to be clean (C<-f>).
2678 This command is only needed because of C<guestfs_resize2fs>
2679 (q.v.). Normally you should use C<guestfs_fsck>.");
2681 ("sleep", (RErr, [Int "secs"]), 109, [],
2682 [InitNone, Always, TestRun (
2684 "sleep for some seconds",
2686 Sleep for C<secs> seconds.");
2688 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2689 [InitNone, Always, TestOutputInt (
2690 [["part_disk"; "/dev/sda"; "mbr"];
2691 ["mkfs"; "ntfs"; "/dev/sda1"];
2692 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2693 InitNone, Always, TestOutputInt (
2694 [["part_disk"; "/dev/sda"; "mbr"];
2695 ["mkfs"; "ext2"; "/dev/sda1"];
2696 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2697 "probe NTFS volume",
2699 This command runs the L<ntfs-3g.probe(8)> command which probes
2700 an NTFS C<device> for mountability. (Not all NTFS volumes can
2701 be mounted read-write, and some cannot be mounted at all).
2703 C<rw> is a boolean flag. Set it to true if you want to test
2704 if the volume can be mounted read-write. Set it to false if
2705 you want to test if the volume can be mounted read-only.
2707 The return value is an integer which C<0> if the operation
2708 would succeed, or some non-zero value documented in the
2709 L<ntfs-3g.probe(8)> manual page.");
2711 ("sh", (RString "output", [String "command"]), 111, [],
2712 [], (* XXX needs tests *)
2713 "run a command via the shell",
2715 This call runs a command from the guest filesystem via the
2718 This is like C<guestfs_command>, but passes the command to:
2720 /bin/sh -c \"command\"
2722 Depending on the guest's shell, this usually results in
2723 wildcards being expanded, shell expressions being interpolated
2726 All the provisos about C<guestfs_command> apply to this call.");
2728 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2729 [], (* XXX needs tests *)
2730 "run a command via the shell returning lines",
2732 This is the same as C<guestfs_sh>, but splits the result
2733 into a list of lines.
2735 See also: C<guestfs_command_lines>");
2737 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2738 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2739 * code in stubs.c, since all valid glob patterns must start with "/".
2740 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2742 [InitBasicFS, Always, TestOutputList (
2743 [["mkdir_p"; "/a/b/c"];
2744 ["touch"; "/a/b/c/d"];
2745 ["touch"; "/a/b/c/e"];
2746 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2747 InitBasicFS, Always, TestOutputList (
2748 [["mkdir_p"; "/a/b/c"];
2749 ["touch"; "/a/b/c/d"];
2750 ["touch"; "/a/b/c/e"];
2751 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2752 InitBasicFS, Always, TestOutputList (
2753 [["mkdir_p"; "/a/b/c"];
2754 ["touch"; "/a/b/c/d"];
2755 ["touch"; "/a/b/c/e"];
2756 ["glob_expand"; "/a/*/x/*"]], [])],
2757 "expand a wildcard path",
2759 This command searches for all the pathnames matching
2760 C<pattern> according to the wildcard expansion rules
2763 If no paths match, then this returns an empty list
2764 (note: not an error).
2766 It is just a wrapper around the C L<glob(3)> function
2767 with flags C<GLOB_MARK|GLOB_BRACE>.
2768 See that manual page for more details.");
2770 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2771 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2772 [["scrub_device"; "/dev/sdc"]])],
2773 "scrub (securely wipe) a device",
2775 This command writes patterns over C<device> to make data retrieval
2778 It is an interface to the L<scrub(1)> program. See that
2779 manual page for more details.");
2781 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2782 [InitBasicFS, Always, TestRun (
2783 [["write_file"; "/file"; "content"; "0"];
2784 ["scrub_file"; "/file"]])],
2785 "scrub (securely wipe) a file",
2787 This command writes patterns over a file to make data retrieval
2790 The file is I<removed> after scrubbing.
2792 It is an interface to the L<scrub(1)> program. See that
2793 manual page for more details.");
2795 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2796 [], (* XXX needs testing *)
2797 "scrub (securely wipe) free space",
2799 This command creates the directory C<dir> and then fills it
2800 with files until the filesystem is full, and scrubs the files
2801 as for C<guestfs_scrub_file>, and deletes them.
2802 The intention is to scrub any free space on the partition
2805 It is an interface to the L<scrub(1)> program. See that
2806 manual page for more details.");
2808 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2809 [InitBasicFS, Always, TestRun (
2811 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2812 "create a temporary directory",
2814 This command creates a temporary directory. The
2815 C<template> parameter should be a full pathname for the
2816 temporary directory name with the final six characters being
2819 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2820 the second one being suitable for Windows filesystems.
2822 The name of the temporary directory that was created
2825 The temporary directory is created with mode 0700
2826 and is owned by root.
2828 The caller is responsible for deleting the temporary
2829 directory and its contents after use.
2831 See also: L<mkdtemp(3)>");
2833 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2834 [InitISOFS, Always, TestOutputInt (
2835 [["wc_l"; "/10klines"]], 10000)],
2836 "count lines in a file",
2838 This command counts the lines in a file, using the
2839 C<wc -l> external command.");
2841 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2842 [InitISOFS, Always, TestOutputInt (
2843 [["wc_w"; "/10klines"]], 10000)],
2844 "count words in a file",
2846 This command counts the words in a file, using the
2847 C<wc -w> external command.");
2849 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2850 [InitISOFS, Always, TestOutputInt (
2851 [["wc_c"; "/100kallspaces"]], 102400)],
2852 "count characters in a file",
2854 This command counts the characters in a file, using the
2855 C<wc -c> external command.");
2857 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2858 [InitISOFS, Always, TestOutputList (
2859 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2860 "return first 10 lines of a file",
2862 This command returns up to the first 10 lines of a file as
2863 a list of strings.");
2865 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2866 [InitISOFS, Always, TestOutputList (
2867 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2868 InitISOFS, Always, TestOutputList (
2869 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2870 InitISOFS, Always, TestOutputList (
2871 [["head_n"; "0"; "/10klines"]], [])],
2872 "return first N lines of a file",
2874 If the parameter C<nrlines> is a positive number, this returns the first
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>, excluding the last C<nrlines> lines.
2880 If the parameter C<nrlines> is zero, this returns an empty list.");
2882 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2883 [InitISOFS, Always, TestOutputList (
2884 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2885 "return last 10 lines of a file",
2887 This command returns up to the last 10 lines of a file as
2888 a list of strings.");
2890 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2891 [InitISOFS, Always, TestOutputList (
2892 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2893 InitISOFS, Always, TestOutputList (
2894 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2895 InitISOFS, Always, TestOutputList (
2896 [["tail_n"; "0"; "/10klines"]], [])],
2897 "return last N lines of a file",
2899 If the parameter C<nrlines> is a positive number, this returns the last
2900 C<nrlines> lines of the file C<path>.
2902 If the parameter C<nrlines> is a negative number, this returns lines
2903 from the file C<path>, starting with the C<-nrlines>th line.
2905 If the parameter C<nrlines> is zero, this returns an empty list.");
2907 ("df", (RString "output", []), 125, [],
2908 [], (* XXX Tricky to test because it depends on the exact format
2909 * of the 'df' command and other imponderables.
2911 "report file system disk space usage",
2913 This command runs the C<df> command to report disk space used.
2915 This command is mostly useful for interactive sessions. It
2916 is I<not> intended that you try to parse the output string.
2917 Use C<statvfs> from programs.");
2919 ("df_h", (RString "output", []), 126, [],
2920 [], (* XXX Tricky to test because it depends on the exact format
2921 * of the 'df' command and other imponderables.
2923 "report file system disk space usage (human readable)",
2925 This command runs the C<df -h> command to report disk space used
2926 in human-readable format.
2928 This command is mostly useful for interactive sessions. It
2929 is I<not> intended that you try to parse the output string.
2930 Use C<statvfs> from programs.");
2932 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2933 [InitISOFS, Always, TestOutputInt (
2934 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2935 "estimate file space usage",
2937 This command runs the C<du -s> command to estimate file space
2940 C<path> can be a file or a directory. If C<path> is a directory
2941 then the estimate includes the contents of the directory and all
2942 subdirectories (recursively).
2944 The result is the estimated size in I<kilobytes>
2945 (ie. units of 1024 bytes).");
2947 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2948 [InitISOFS, Always, TestOutputList (
2949 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2950 "list files in an initrd",
2952 This command lists out files contained in an initrd.
2954 The files are listed without any initial C</> character. The
2955 files are listed in the order they appear (not necessarily
2956 alphabetical). Directory names are listed as separate items.
2958 Old Linux kernels (2.4 and earlier) used a compressed ext2
2959 filesystem as initrd. We I<only> support the newer initramfs
2960 format (compressed cpio files).");
2962 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2964 "mount a file using the loop device",
2966 This command lets you mount C<file> (a filesystem image
2967 in a file) on a mount point. It is entirely equivalent to
2968 the command C<mount -o loop file mountpoint>.");
2970 ("mkswap", (RErr, [Device "device"]), 130, [],
2971 [InitEmpty, Always, TestRun (
2972 [["part_disk"; "/dev/sda"; "mbr"];
2973 ["mkswap"; "/dev/sda1"]])],
2974 "create a swap partition",
2976 Create a swap partition on C<device>.");
2978 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2979 [InitEmpty, Always, TestRun (
2980 [["part_disk"; "/dev/sda"; "mbr"];
2981 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2982 "create a swap partition with a label",
2984 Create a swap partition on C<device> with label C<label>.
2986 Note that you cannot attach a swap label to a block device
2987 (eg. C</dev/sda>), just to a partition. This appears to be
2988 a limitation of the kernel or swap tools.");
2990 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2991 (let uuid = uuidgen () in
2992 [InitEmpty, Always, TestRun (
2993 [["part_disk"; "/dev/sda"; "mbr"];
2994 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2995 "create a swap partition with an explicit UUID",
2997 Create a swap partition on C<device> with UUID C<uuid>.");
2999 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3000 [InitBasicFS, Always, TestOutputStruct (
3001 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3002 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3003 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3004 InitBasicFS, Always, TestOutputStruct (
3005 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3006 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3007 "make block, character or FIFO devices",
3009 This call creates block or character special devices, or
3010 named pipes (FIFOs).
3012 The C<mode> parameter should be the mode, using the standard
3013 constants. C<devmajor> and C<devminor> are the
3014 device major and minor numbers, only used when creating block
3015 and character special devices.
3017 Note that, just like L<mknod(2)>, the mode must be bitwise
3018 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3019 just creates a regular file). These constants are
3020 available in the standard Linux header files, or you can use
3021 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3022 which are wrappers around this command which bitwise OR
3023 in the appropriate constant for you.
3025 The mode actually set is affected by the umask.");
3027 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3028 [InitBasicFS, Always, TestOutputStruct (
3029 [["mkfifo"; "0o777"; "/node"];
3030 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3031 "make FIFO (named pipe)",
3033 This call creates a FIFO (named pipe) called C<path> with
3034 mode C<mode>. It is just a convenient wrapper around
3037 The mode actually set is affected by the umask.");
3039 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3040 [InitBasicFS, Always, TestOutputStruct (
3041 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3042 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3043 "make block device node",
3045 This call creates a block device node called C<path> with
3046 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3047 It is just a convenient wrapper around C<guestfs_mknod>.
3049 The mode actually set is affected by the umask.");
3051 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3052 [InitBasicFS, Always, TestOutputStruct (
3053 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3054 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3055 "make char device node",
3057 This call creates a char device node called C<path> with
3058 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3059 It is just a convenient wrapper around C<guestfs_mknod>.
3061 The mode actually set is affected by the umask.");
3063 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3064 [InitEmpty, Always, TestOutputInt (
3065 [["umask"; "0o22"]], 0o22)],
3066 "set file mode creation mask (umask)",
3068 This function sets the mask used for creating new files and
3069 device nodes to C<mask & 0777>.
3071 Typical umask values would be C<022> which creates new files
3072 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3073 C<002> which creates new files with permissions like
3074 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3076 The default umask is C<022>. This is important because it
3077 means that directories and device nodes will be created with
3078 C<0644> or C<0755> mode even if you specify C<0777>.
3080 See also C<guestfs_get_umask>,
3081 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3083 This call returns the previous umask.");
3085 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3087 "read directories entries",
3089 This returns the list of directory entries in directory C<dir>.
3091 All entries in the directory are returned, including C<.> and
3092 C<..>. The entries are I<not> sorted, but returned in the same
3093 order as the underlying filesystem.
3095 Also this call returns basic file type information about each
3096 file. The C<ftyp> field will contain one of the following characters:
3134 The L<readdir(3)> returned a C<d_type> field with an
3139 This function is primarily intended for use by programs. To
3140 get a simple list of names, use C<guestfs_ls>. To get a printable
3141 directory for human consumption, use C<guestfs_ll>.");
3143 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3145 "create partitions on a block device",
3147 This is a simplified interface to the C<guestfs_sfdisk>
3148 command, where partition sizes are specified in megabytes
3149 only (rounded to the nearest cylinder) and you don't need
3150 to specify the cyls, heads and sectors parameters which
3151 were rarely if ever used anyway.
3153 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3154 and C<guestfs_part_disk>");
3156 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3158 "determine file type inside a compressed file",
3160 This command runs C<file> after first decompressing C<path>
3163 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3165 Since 1.0.63, use C<guestfs_file> instead which can now
3166 process compressed files.");
3168 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3170 "list extended attributes of a file or directory",
3172 This call lists the extended attributes of the file or directory
3175 At the system call level, this is a combination of the
3176 L<listxattr(2)> and L<getxattr(2)> calls.
3178 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3180 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3182 "list extended attributes of a file or directory",
3184 This is the same as C<guestfs_getxattrs>, but if C<path>
3185 is a symbolic link, then it returns the extended attributes
3186 of the link itself.");
3188 ("setxattr", (RErr, [String "xattr";
3189 String "val"; Int "vallen"; (* will be BufferIn *)
3190 Pathname "path"]), 143, [Optional "linuxxattrs"],
3192 "set extended attribute of a file or directory",
3194 This call sets the extended attribute named C<xattr>
3195 of the file C<path> to the value C<val> (of length C<vallen>).
3196 The value is arbitrary 8 bit data.
3198 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3200 ("lsetxattr", (RErr, [String "xattr";
3201 String "val"; Int "vallen"; (* will be BufferIn *)
3202 Pathname "path"]), 144, [Optional "linuxxattrs"],
3204 "set extended attribute of a file or directory",
3206 This is the same as C<guestfs_setxattr>, but if C<path>
3207 is a symbolic link, then it sets an extended attribute
3208 of the link itself.");
3210 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3212 "remove extended attribute of a file or directory",
3214 This call removes the extended attribute named C<xattr>
3215 of the file C<path>.
3217 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3219 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3221 "remove extended attribute of a file or directory",
3223 This is the same as C<guestfs_removexattr>, but if C<path>
3224 is a symbolic link, then it removes an extended attribute
3225 of the link itself.");
3227 ("mountpoints", (RHashtable "mps", []), 147, [],
3231 This call is similar to C<guestfs_mounts>. That call returns
3232 a list of devices. This one returns a hash table (map) of
3233 device name to directory where the device is mounted.");
3235 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3236 (* This is a special case: while you would expect a parameter
3237 * of type "Pathname", that doesn't work, because it implies
3238 * NEED_ROOT in the generated calling code in stubs.c, and
3239 * this function cannot use NEED_ROOT.
3242 "create a mountpoint",
3244 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3245 specialized calls that can be used to create extra mountpoints
3246 before mounting the first filesystem.
3248 These calls are I<only> necessary in some very limited circumstances,
3249 mainly the case where you want to mount a mix of unrelated and/or
3250 read-only filesystems together.
3252 For example, live CDs often contain a \"Russian doll\" nest of
3253 filesystems, an ISO outer layer, with a squashfs image inside, with
3254 an ext2/3 image inside that. You can unpack this as follows
3257 add-ro Fedora-11-i686-Live.iso
3260 mkmountpoint /squash
3263 mount-loop /cd/LiveOS/squashfs.img /squash
3264 mount-loop /squash/LiveOS/ext3fs.img /ext3
3266 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3268 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3270 "remove a mountpoint",
3272 This calls removes a mountpoint that was previously created
3273 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3274 for full details.");
3276 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3277 [InitISOFS, Always, TestOutputBuffer (
3278 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3281 This calls returns the contents of the file C<path> as a
3284 Unlike C<guestfs_cat>, this function can correctly
3285 handle files that contain embedded ASCII NUL characters.
3286 However unlike C<guestfs_download>, this function is limited
3287 in the total size of file that can be handled.");
3289 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3290 [InitISOFS, Always, TestOutputList (
3291 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3292 InitISOFS, Always, TestOutputList (
3293 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3294 "return lines matching a pattern",
3296 This calls the external C<grep> program and returns the
3299 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3300 [InitISOFS, Always, TestOutputList (
3301 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3302 "return lines matching a pattern",
3304 This calls the external C<egrep> program and returns the
3307 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3308 [InitISOFS, Always, TestOutputList (
3309 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3310 "return lines matching a pattern",
3312 This calls the external C<fgrep> program and returns the
3315 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3316 [InitISOFS, Always, TestOutputList (
3317 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3318 "return lines matching a pattern",
3320 This calls the external C<grep -i> program and returns the
3323 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3324 [InitISOFS, Always, TestOutputList (
3325 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3326 "return lines matching a pattern",
3328 This calls the external C<egrep -i> program and returns the
3331 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3332 [InitISOFS, Always, TestOutputList (
3333 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3334 "return lines matching a pattern",
3336 This calls the external C<fgrep -i> program and returns the
3339 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3340 [InitISOFS, Always, TestOutputList (
3341 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3342 "return lines matching a pattern",
3344 This calls the external C<zgrep> program and returns the
3347 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3348 [InitISOFS, Always, TestOutputList (
3349 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3350 "return lines matching a pattern",
3352 This calls the external C<zegrep> program and returns the
3355 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3356 [InitISOFS, Always, TestOutputList (
3357 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3358 "return lines matching a pattern",
3360 This calls the external C<zfgrep> program and returns the
3363 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3364 [InitISOFS, Always, TestOutputList (
3365 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3366 "return lines matching a pattern",
3368 This calls the external C<zgrep -i> program and returns the
3371 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3372 [InitISOFS, Always, TestOutputList (
3373 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3374 "return lines matching a pattern",
3376 This calls the external C<zegrep -i> program and returns the
3379 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3380 [InitISOFS, Always, TestOutputList (
3381 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3382 "return lines matching a pattern",
3384 This calls the external C<zfgrep -i> program and returns the
3387 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3388 [InitISOFS, Always, TestOutput (
3389 [["realpath"; "/../directory"]], "/directory")],
3390 "canonicalized absolute pathname",
3392 Return the canonicalized absolute pathname of C<path>. The
3393 returned path has no C<.>, C<..> or symbolic link path elements.");
3395 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3396 [InitBasicFS, Always, TestOutputStruct (
3399 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3400 "create a hard link",
3402 This command creates a hard link using the C<ln> command.");
3404 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3405 [InitBasicFS, Always, TestOutputStruct (
3408 ["ln_f"; "/a"; "/b"];
3409 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3410 "create a hard link",
3412 This command creates a hard link using the C<ln -f> command.
3413 The C<-f> option removes the link (C<linkname>) if it exists already.");
3415 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3416 [InitBasicFS, Always, TestOutputStruct (
3418 ["ln_s"; "a"; "/b"];
3419 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3420 "create a symbolic link",
3422 This command creates a symbolic link using the C<ln -s> command.");
3424 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3425 [InitBasicFS, Always, TestOutput (
3426 [["mkdir_p"; "/a/b"];
3427 ["touch"; "/a/b/c"];
3428 ["ln_sf"; "../d"; "/a/b/c"];
3429 ["readlink"; "/a/b/c"]], "../d")],
3430 "create a symbolic link",
3432 This command creates a symbolic link using the C<ln -sf> command,
3433 The C<-f> option removes the link (C<linkname>) if it exists already.");
3435 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3436 [] (* XXX tested above *),
3437 "read the target of a symbolic link",
3439 This command reads the target of a symbolic link.");
3441 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3442 [InitBasicFS, Always, TestOutputStruct (
3443 [["fallocate"; "/a"; "1000000"];
3444 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3445 "preallocate a file in the guest filesystem",
3447 This command preallocates a file (containing zero bytes) named
3448 C<path> of size C<len> bytes. If the file exists already, it
3451 Do not confuse this with the guestfish-specific
3452 C<alloc> command which allocates a file in the host and
3453 attaches it as a device.");
3455 ("swapon_device", (RErr, [Device "device"]), 170, [],
3456 [InitPartition, Always, TestRun (
3457 [["mkswap"; "/dev/sda1"];
3458 ["swapon_device"; "/dev/sda1"];
3459 ["swapoff_device"; "/dev/sda1"]])],
3460 "enable swap on device",
3462 This command enables the libguestfs appliance to use the
3463 swap device or partition named C<device>. The increased
3464 memory is made available for all commands, for example
3465 those run using C<guestfs_command> or C<guestfs_sh>.
3467 Note that you should not swap to existing guest swap
3468 partitions unless you know what you are doing. They may
3469 contain hibernation information, or other information that
3470 the guest doesn't want you to trash. You also risk leaking
3471 information about the host to the guest this way. Instead,
3472 attach a new host device to the guest and swap on that.");
3474 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3475 [], (* XXX tested by swapon_device *)
3476 "disable swap on device",
3478 This command disables the libguestfs appliance swap
3479 device or partition named C<device>.
3480 See C<guestfs_swapon_device>.");
3482 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3483 [InitBasicFS, Always, TestRun (
3484 [["fallocate"; "/swap"; "8388608"];
3485 ["mkswap_file"; "/swap"];
3486 ["swapon_file"; "/swap"];
3487 ["swapoff_file"; "/swap"]])],
3488 "enable swap on file",
3490 This command enables swap to a file.
3491 See C<guestfs_swapon_device> for other notes.");
3493 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3494 [], (* XXX tested by swapon_file *)
3495 "disable swap on file",
3497 This command disables the libguestfs appliance swap on file.");
3499 ("swapon_label", (RErr, [String "label"]), 174, [],
3500 [InitEmpty, Always, TestRun (
3501 [["part_disk"; "/dev/sdb"; "mbr"];
3502 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3503 ["swapon_label"; "swapit"];
3504 ["swapoff_label"; "swapit"];
3505 ["zero"; "/dev/sdb"];
3506 ["blockdev_rereadpt"; "/dev/sdb"]])],
3507 "enable swap on labeled swap partition",
3509 This command enables swap to a labeled swap partition.
3510 See C<guestfs_swapon_device> for other notes.");
3512 ("swapoff_label", (RErr, [String "label"]), 175, [],
3513 [], (* XXX tested by swapon_label *)
3514 "disable swap on labeled swap partition",
3516 This command disables the libguestfs appliance swap on
3517 labeled swap partition.");
3519 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3520 (let uuid = uuidgen () in
3521 [InitEmpty, Always, TestRun (
3522 [["mkswap_U"; uuid; "/dev/sdb"];
3523 ["swapon_uuid"; uuid];
3524 ["swapoff_uuid"; uuid]])]),
3525 "enable swap on swap partition by UUID",
3527 This command enables swap to a swap partition with the given UUID.
3528 See C<guestfs_swapon_device> for other notes.");
3530 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3531 [], (* XXX tested by swapon_uuid *)
3532 "disable swap on swap partition by UUID",
3534 This command disables the libguestfs appliance swap partition
3535 with the given UUID.");
3537 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3538 [InitBasicFS, Always, TestRun (
3539 [["fallocate"; "/swap"; "8388608"];
3540 ["mkswap_file"; "/swap"]])],
3541 "create a swap file",
3545 This command just writes a swap file signature to an existing
3546 file. To create the file itself, use something like C<guestfs_fallocate>.");
3548 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3549 [InitISOFS, Always, TestRun (
3550 [["inotify_init"; "0"]])],
3551 "create an inotify handle",
3553 This command creates a new inotify handle.
3554 The inotify subsystem can be used to notify events which happen to
3555 objects in the guest filesystem.
3557 C<maxevents> is the maximum number of events which will be
3558 queued up between calls to C<guestfs_inotify_read> or
3559 C<guestfs_inotify_files>.
3560 If this is passed as C<0>, then the kernel (or previously set)
3561 default is used. For Linux 2.6.29 the default was 16384 events.
3562 Beyond this limit, the kernel throws away events, but records
3563 the fact that it threw them away by setting a flag
3564 C<IN_Q_OVERFLOW> in the returned structure list (see
3565 C<guestfs_inotify_read>).
3567 Before any events are generated, you have to add some
3568 watches to the internal watch list. See:
3569 C<guestfs_inotify_add_watch>,
3570 C<guestfs_inotify_rm_watch> and
3571 C<guestfs_inotify_watch_all>.
3573 Queued up events should be read periodically by calling
3574 C<guestfs_inotify_read>
3575 (or C<guestfs_inotify_files> which is just a helpful
3576 wrapper around C<guestfs_inotify_read>). If you don't
3577 read the events out often enough then you risk the internal
3580 The handle should be closed after use by calling
3581 C<guestfs_inotify_close>. This also removes any
3582 watches automatically.
3584 See also L<inotify(7)> for an overview of the inotify interface
3585 as exposed by the Linux kernel, which is roughly what we expose
3586 via libguestfs. Note that there is one global inotify handle
3587 per libguestfs instance.");
3589 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3590 [InitBasicFS, Always, TestOutputList (
3591 [["inotify_init"; "0"];
3592 ["inotify_add_watch"; "/"; "1073741823"];
3595 ["inotify_files"]], ["a"; "b"])],
3596 "add an inotify watch",
3598 Watch C<path> for the events listed in C<mask>.
3600 Note that if C<path> is a directory then events within that
3601 directory are watched, but this does I<not> happen recursively
3602 (in subdirectories).
3604 Note for non-C or non-Linux callers: the inotify events are
3605 defined by the Linux kernel ABI and are listed in
3606 C</usr/include/sys/inotify.h>.");
3608 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3610 "remove an inotify watch",
3612 Remove a previously defined inotify watch.
3613 See C<guestfs_inotify_add_watch>.");
3615 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3617 "return list of inotify events",
3619 Return the complete queue of events that have happened
3620 since the previous read call.
3622 If no events have happened, this returns an empty list.
3624 I<Note>: In order to make sure that all events have been
3625 read, you must call this function repeatedly until it
3626 returns an empty list. The reason is that the call will
3627 read events up to the maximum appliance-to-host message
3628 size and leave remaining events in the queue.");
3630 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3632 "return list of watched files that had events",
3634 This function is a helpful wrapper around C<guestfs_inotify_read>
3635 which just returns a list of pathnames of objects that were
3636 touched. The returned pathnames are sorted and deduplicated.");
3638 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3640 "close the inotify handle",
3642 This closes the inotify handle which was previously
3643 opened by inotify_init. It removes all watches, throws
3644 away any pending events, and deallocates all resources.");
3646 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3648 "set SELinux security context",
3650 This sets the SELinux security context of the daemon
3651 to the string C<context>.
3653 See the documentation about SELINUX in L<guestfs(3)>.");
3655 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3657 "get SELinux security context",
3659 This gets the SELinux security context of the daemon.
3661 See the documentation about SELINUX in L<guestfs(3)>,
3662 and C<guestfs_setcon>");
3664 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3665 [InitEmpty, Always, TestOutput (
3666 [["part_disk"; "/dev/sda"; "mbr"];
3667 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3668 ["mount_options"; ""; "/dev/sda1"; "/"];
3669 ["write_file"; "/new"; "new file contents"; "0"];
3670 ["cat"; "/new"]], "new file contents")],
3671 "make a filesystem with block size",
3673 This call is similar to C<guestfs_mkfs>, but it allows you to
3674 control the block size of the resulting filesystem. Supported
3675 block sizes depend on the filesystem type, but typically they
3676 are C<1024>, C<2048> or C<4096> only.");
3678 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3679 [InitEmpty, Always, TestOutput (
3680 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3681 ["mke2journal"; "4096"; "/dev/sda1"];
3682 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3683 ["mount_options"; ""; "/dev/sda2"; "/"];
3684 ["write_file"; "/new"; "new file contents"; "0"];
3685 ["cat"; "/new"]], "new file contents")],
3686 "make ext2/3/4 external journal",
3688 This creates an ext2 external journal on C<device>. It is equivalent
3691 mke2fs -O journal_dev -b blocksize device");
3693 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3694 [InitEmpty, Always, TestOutput (
3695 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3696 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3697 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3698 ["mount_options"; ""; "/dev/sda2"; "/"];
3699 ["write_file"; "/new"; "new file contents"; "0"];
3700 ["cat"; "/new"]], "new file contents")],
3701 "make ext2/3/4 external journal with label",
3703 This creates an ext2 external journal on C<device> with label C<label>.");
3705 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3706 (let uuid = uuidgen () in
3707 [InitEmpty, Always, TestOutput (
3708 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3709 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3710 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3711 ["mount_options"; ""; "/dev/sda2"; "/"];
3712 ["write_file"; "/new"; "new file contents"; "0"];
3713 ["cat"; "/new"]], "new file contents")]),
3714 "make ext2/3/4 external journal with UUID",
3716 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3718 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3720 "make ext2/3/4 filesystem with external journal",
3722 This creates an ext2/3/4 filesystem on C<device> with
3723 an external journal on C<journal>. It is equivalent
3726 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3728 See also C<guestfs_mke2journal>.");
3730 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3732 "make ext2/3/4 filesystem with external journal",
3734 This creates an ext2/3/4 filesystem on C<device> with
3735 an external journal on the journal labeled C<label>.
3737 See also C<guestfs_mke2journal_L>.");
3739 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3741 "make ext2/3/4 filesystem with external journal",
3743 This creates an ext2/3/4 filesystem on C<device> with
3744 an external journal on the journal with UUID C<uuid>.
3746 See also C<guestfs_mke2journal_U>.");
3748 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3749 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3750 "load a kernel module",
3752 This loads a kernel module in the appliance.
3754 The kernel module must have been whitelisted when libguestfs
3755 was built (see C<appliance/kmod.whitelist.in> in the source).");
3757 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3758 [InitNone, Always, TestOutput (
3759 [["echo_daemon"; "This is a test"]], "This is a test"
3761 "echo arguments back to the client",
3763 This command concatenate the list of C<words> passed with single spaces between
3764 them and returns the resulting string.
3766 You can use this command to test the connection through to the daemon.
3768 See also C<guestfs_ping_daemon>.");
3770 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3771 [], (* There is a regression test for this. *)
3772 "find all files and directories, returning NUL-separated list",
3774 This command lists out all files and directories, recursively,
3775 starting at C<directory>, placing the resulting list in the
3776 external file called C<files>.
3778 This command works the same way as C<guestfs_find> with the
3779 following exceptions:
3785 The resulting list is written to an external file.
3789 Items (filenames) in the result are separated
3790 by C<\\0> characters. See L<find(1)> option I<-print0>.
3794 This command is not limited in the number of names that it
3799 The result list is not sorted.
3803 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3804 [InitISOFS, Always, TestOutput (
3805 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3806 InitISOFS, Always, TestOutput (
3807 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3808 InitISOFS, Always, TestOutput (
3809 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3810 InitISOFS, Always, TestLastFail (
3811 [["case_sensitive_path"; "/Known-1/"]]);
3812 InitBasicFS, Always, TestOutput (
3814 ["mkdir"; "/a/bbb"];
3815 ["touch"; "/a/bbb/c"];
3816 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3817 InitBasicFS, Always, TestOutput (
3819 ["mkdir"; "/a/bbb"];
3820 ["touch"; "/a/bbb/c"];
3821 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3822 InitBasicFS, Always, TestLastFail (
3824 ["mkdir"; "/a/bbb"];
3825 ["touch"; "/a/bbb/c"];
3826 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3827 "return true path on case-insensitive filesystem",
3829 This can be used to resolve case insensitive paths on
3830 a filesystem which is case sensitive. The use case is
3831 to resolve paths which you have read from Windows configuration
3832 files or the Windows Registry, to the true path.
3834 The command handles a peculiarity of the Linux ntfs-3g
3835 filesystem driver (and probably others), which is that although
3836 the underlying filesystem is case-insensitive, the driver
3837 exports the filesystem to Linux as case-sensitive.
3839 One consequence of this is that special directories such
3840 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3841 (or other things) depending on the precise details of how
3842 they were created. In Windows itself this would not be
3845 Bug or feature? You decide:
3846 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3848 This function resolves the true case of each element in the
3849 path and returns the case-sensitive path.
3851 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3852 might return C<\"/WINDOWS/system32\"> (the exact return value
3853 would depend on details of how the directories were originally
3854 created under Windows).
3857 This function does not handle drive names, backslashes etc.
3859 See also C<guestfs_realpath>.");
3861 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3862 [InitBasicFS, Always, TestOutput (
3863 [["vfs_type"; "/dev/sda1"]], "ext2")],
3864 "get the Linux VFS type corresponding to a mounted device",
3866 This command gets the block device type corresponding to
3867 a mounted device called C<device>.
3869 Usually the result is the name of the Linux VFS module that
3870 is used to mount this device (probably determined automatically
3871 if you used the C<guestfs_mount> call).");
3873 ("truncate", (RErr, [Pathname "path"]), 199, [],
3874 [InitBasicFS, Always, TestOutputStruct (
3875 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3876 ["truncate"; "/test"];
3877 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3878 "truncate a file to zero size",
3880 This command truncates C<path> to a zero-length file. The
3881 file must exist already.");
3883 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3884 [InitBasicFS, Always, TestOutputStruct (
3885 [["touch"; "/test"];
3886 ["truncate_size"; "/test"; "1000"];
3887 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3888 "truncate a file to a particular size",
3890 This command truncates C<path> to size C<size> bytes. The file
3891 must exist already. If the file is smaller than C<size> then
3892 the file is extended to the required size with null bytes.");
3894 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3895 [InitBasicFS, Always, TestOutputStruct (
3896 [["touch"; "/test"];
3897 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3898 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3899 "set timestamp of a file with nanosecond precision",
3901 This command sets the timestamps of a file with nanosecond
3904 C<atsecs, atnsecs> are the last access time (atime) in secs and
3905 nanoseconds from the epoch.
3907 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3908 secs and nanoseconds from the epoch.
3910 If the C<*nsecs> field contains the special value C<-1> then
3911 the corresponding timestamp is set to the current time. (The
3912 C<*secs> field is ignored in this case).
3914 If the C<*nsecs> field contains the special value C<-2> then
3915 the corresponding timestamp is left unchanged. (The
3916 C<*secs> field is ignored in this case).");
3918 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3919 [InitBasicFS, Always, TestOutputStruct (
3920 [["mkdir_mode"; "/test"; "0o111"];
3921 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3922 "create a directory with a particular mode",
3924 This command creates a directory, setting the initial permissions
3925 of the directory to C<mode>.
3927 For common Linux filesystems, the actual mode which is set will
3928 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3929 interpret the mode in other ways.
3931 See also C<guestfs_mkdir>, C<guestfs_umask>");
3933 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3935 "change file owner and group",
3937 Change the file owner to C<owner> and group to C<group>.
3938 This is like C<guestfs_chown> but if C<path> is a symlink then
3939 the link itself is changed, not the target.
3941 Only numeric uid and gid are supported. If you want to use
3942 names, you will need to locate and parse the password file
3943 yourself (Augeas support makes this relatively easy).");
3945 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3947 "lstat on multiple files",
3949 This call allows you to perform the C<guestfs_lstat> operation
3950 on multiple files, where all files are in the directory C<path>.
3951 C<names> is the list of files from this directory.
3953 On return you get a list of stat structs, with a one-to-one
3954 correspondence to the C<names> list. If any name did not exist
3955 or could not be lstat'd, then the C<ino> field of that structure
3958 This call is intended for programs that want to efficiently
3959 list a directory contents without making many round-trips.
3960 See also C<guestfs_lxattrlist> for a similarly efficient call
3961 for getting extended attributes. Very long directory listings
3962 might cause the protocol message size to be exceeded, causing
3963 this call to fail. The caller must split up such requests
3964 into smaller groups of names.");
3966 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3968 "lgetxattr on multiple files",
3970 This call allows you to get the extended attributes
3971 of multiple files, where all files are in the directory C<path>.
3972 C<names> is the list of files from this directory.
3974 On return you get a flat list of xattr structs which must be
3975 interpreted sequentially. The first xattr struct always has a zero-length
3976 C<attrname>. C<attrval> in this struct is zero-length
3977 to indicate there was an error doing C<lgetxattr> for this
3978 file, I<or> is a C string which is a decimal number
3979 (the number of following attributes for this file, which could
3980 be C<\"0\">). Then after the first xattr struct are the
3981 zero or more attributes for the first named file.
3982 This repeats for the second and subsequent files.
3984 This call is intended for programs that want to efficiently
3985 list a directory contents without making many round-trips.
3986 See also C<guestfs_lstatlist> for a similarly efficient call
3987 for getting standard stats. Very long directory listings
3988 might cause the protocol message size to be exceeded, causing
3989 this call to fail. The caller must split up such requests
3990 into smaller groups of names.");
3992 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3994 "readlink on multiple files",
3996 This call allows you to do a C<readlink> operation
3997 on multiple files, where all files are in the directory C<path>.
3998 C<names> is the list of files from this directory.
4000 On return you get a list of strings, with a one-to-one
4001 correspondence to the C<names> list. Each string is the
4002 value of the symbol link.
4004 If the C<readlink(2)> operation fails on any name, then
4005 the corresponding result string is the empty string C<\"\">.
4006 However the whole operation is completed even if there
4007 were C<readlink(2)> errors, and so you can call this
4008 function with names where you don't know if they are
4009 symbolic links already (albeit slightly less efficient).
4011 This call is intended for programs that want to efficiently
4012 list a directory contents without making many round-trips.
4013 Very long directory listings might cause the protocol
4014 message size to be exceeded, causing
4015 this call to fail. The caller must split up such requests
4016 into smaller groups of names.");
4018 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4019 [InitISOFS, Always, TestOutputBuffer (
4020 [["pread"; "/known-4"; "1"; "3"]], "\n");
4021 InitISOFS, Always, TestOutputBuffer (
4022 [["pread"; "/empty"; "0"; "100"]], "")],
4023 "read part of a file",
4025 This command lets you read part of a file. It reads C<count>
4026 bytes of the file, starting at C<offset>, from file C<path>.
4028 This may read fewer bytes than requested. For further details
4029 see the L<pread(2)> system call.");
4031 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4032 [InitEmpty, Always, TestRun (
4033 [["part_init"; "/dev/sda"; "gpt"]])],
4034 "create an empty partition table",
4036 This creates an empty partition table on C<device> of one of the
4037 partition types listed below. Usually C<parttype> should be
4038 either C<msdos> or C<gpt> (for large disks).
4040 Initially there are no partitions. Following this, you should
4041 call C<guestfs_part_add> for each partition required.
4043 Possible values for C<parttype> are:
4047 =item B<efi> | B<gpt>
4049 Intel EFI / GPT partition table.
4051 This is recommended for >= 2 TB partitions that will be accessed
4052 from Linux and Intel-based Mac OS X. It also has limited backwards
4053 compatibility with the C<mbr> format.
4055 =item B<mbr> | B<msdos>
4057 The standard PC \"Master Boot Record\" (MBR) format used
4058 by MS-DOS and Windows. This partition type will B<only> work
4059 for device sizes up to 2 TB. For large disks we recommend
4064 Other partition table types that may work but are not
4073 =item B<amiga> | B<rdb>
4075 Amiga \"Rigid Disk Block\" format.
4083 DASD, used on IBM mainframes.
4091 Old Mac partition format. Modern Macs use C<gpt>.
4095 NEC PC-98 format, common in Japan apparently.
4103 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4104 [InitEmpty, Always, TestRun (
4105 [["part_init"; "/dev/sda"; "mbr"];
4106 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4107 InitEmpty, Always, TestRun (
4108 [["part_init"; "/dev/sda"; "gpt"];
4109 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4110 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4111 InitEmpty, Always, TestRun (
4112 [["part_init"; "/dev/sda"; "mbr"];
4113 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4114 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4115 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4116 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4117 "add a partition to the device",
4119 This command adds a partition to C<device>. If there is no partition
4120 table on the device, call C<guestfs_part_init> first.
4122 The C<prlogex> parameter is the type of partition. Normally you
4123 should pass C<p> or C<primary> here, but MBR partition tables also
4124 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4127 C<startsect> and C<endsect> are the start and end of the partition
4128 in I<sectors>. C<endsect> may be negative, which means it counts
4129 backwards from the end of the disk (C<-1> is the last sector).
4131 Creating a partition which covers the whole disk is not so easy.
4132 Use C<guestfs_part_disk> to do that.");
4134 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4135 [InitEmpty, Always, TestRun (
4136 [["part_disk"; "/dev/sda"; "mbr"]]);
4137 InitEmpty, Always, TestRun (
4138 [["part_disk"; "/dev/sda"; "gpt"]])],
4139 "partition whole disk with a single primary partition",
4141 This command is simply a combination of C<guestfs_part_init>
4142 followed by C<guestfs_part_add> to create a single primary partition
4143 covering the whole disk.
4145 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4146 but other possible values are described in C<guestfs_part_init>.");
4148 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4149 [InitEmpty, Always, TestRun (
4150 [["part_disk"; "/dev/sda"; "mbr"];
4151 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4152 "make a partition bootable",
4154 This sets the bootable flag on partition numbered C<partnum> on
4155 device C<device>. Note that partitions are numbered from 1.
4157 The bootable flag is used by some operating systems (notably
4158 Windows) to determine which partition to boot from. It is by
4159 no means universally recognized.");
4161 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4162 [InitEmpty, Always, TestRun (
4163 [["part_disk"; "/dev/sda"; "gpt"];
4164 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4165 "set partition name",
4167 This sets the partition name on partition numbered C<partnum> on
4168 device C<device>. Note that partitions are numbered from 1.
4170 The partition name can only be set on certain types of partition
4171 table. This works on C<gpt> but not on C<mbr> partitions.");
4173 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4174 [], (* XXX Add a regression test for this. *)
4175 "list partitions on a device",
4177 This command parses the partition table on C<device> and
4178 returns the list of partitions found.
4180 The fields in the returned structure are:
4186 Partition number, counting from 1.
4190 Start of the partition I<in bytes>. To get sectors you have to
4191 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4195 End of the partition in bytes.
4199 Size of the partition in bytes.
4203 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4204 [InitEmpty, Always, TestOutput (
4205 [["part_disk"; "/dev/sda"; "gpt"];
4206 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4207 "get the partition table type",
4209 This command examines the partition table on C<device> and
4210 returns the partition table type (format) being used.
4212 Common return values include: C<msdos> (a DOS/Windows style MBR
4213 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4214 values are possible, although unusual. See C<guestfs_part_init>
4217 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4218 [InitBasicFS, Always, TestOutputBuffer (
4219 [["fill"; "0x63"; "10"; "/test"];
4220 ["read_file"; "/test"]], "cccccccccc")],
4221 "fill a file with octets",
4223 This command creates a new file called C<path>. The initial
4224 content of the file is C<len> octets of C<c>, where C<c>
4225 must be a number in the range C<[0..255]>.
4227 To fill a file with zero bytes (sparsely), it is
4228 much more efficient to use C<guestfs_truncate_size>.");
4230 ("available", (RErr, [StringList "groups"]), 216, [],
4231 [InitNone, Always, TestRun [["available"; ""]]],
4232 "test availability of some parts of the API",
4234 This command is used to check the availability of some
4235 groups of functionality in the appliance, which not all builds of
4236 the libguestfs appliance will be able to provide.
4238 The libguestfs groups, and the functions that those
4239 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4241 The argument C<groups> is a list of group names, eg:
4242 C<[\"inotify\", \"augeas\"]> would check for the availability of
4243 the Linux inotify functions and Augeas (configuration file
4246 The command returns no error if I<all> requested groups are available.
4248 It fails with an error if one or more of the requested
4249 groups is unavailable in the appliance.
4251 If an unknown group name is included in the
4252 list of groups then an error is always returned.
4260 You must call C<guestfs_launch> before calling this function.
4262 The reason is because we don't know what groups are
4263 supported by the appliance/daemon until it is running and can
4268 If a group of functions is available, this does not necessarily
4269 mean that they will work. You still have to check for errors
4270 when calling individual API functions even if they are
4275 It is usually the job of distro packagers to build
4276 complete functionality into the libguestfs appliance.
4277 Upstream libguestfs, if built from source with all
4278 requirements satisfied, will support everything.
4282 This call was added in version C<1.0.80>. In previous
4283 versions of libguestfs all you could do would be to speculatively
4284 execute a command to find out if the daemon implemented it.
4285 See also C<guestfs_version>.
4289 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4290 [InitBasicFS, Always, TestOutputBuffer (
4291 [["write_file"; "/src"; "hello, world"; "0"];
4292 ["dd"; "/src"; "/dest"];
4293 ["read_file"; "/dest"]], "hello, world")],
4294 "copy from source to destination using dd",
4296 This command copies from one source device or file C<src>
4297 to another destination device or file C<dest>. Normally you
4298 would use this to copy to or from a device or partition, for
4299 example to duplicate a filesystem.
4301 If the destination is a device, it must be as large or larger
4302 than the source file or device, otherwise the copy will fail.
4303 This command cannot do partial copies (see C<guestfs_copy_size>).");
4305 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4306 [InitBasicFS, Always, TestOutputInt (
4307 [["write_file"; "/file"; "hello, world"; "0"];
4308 ["filesize"; "/file"]], 12)],
4309 "return the size of the file in bytes",
4311 This command returns the size of C<file> in bytes.
4313 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4314 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4315 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4317 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4318 [InitBasicFSonLVM, Always, TestOutputList (
4319 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4320 ["lvs"]], ["/dev/VG/LV2"])],
4321 "rename an LVM logical volume",
4323 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4325 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4326 [InitBasicFSonLVM, Always, TestOutputList (
4328 ["vg_activate"; "false"; "VG"];
4329 ["vgrename"; "VG"; "VG2"];
4330 ["vg_activate"; "true"; "VG2"];
4331 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4332 ["vgs"]], ["VG2"])],
4333 "rename an LVM volume group",
4335 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4337 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4338 [InitISOFS, Always, TestOutputBuffer (
4339 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4340 "list the contents of a single file in an initrd",
4342 This command unpacks the file C<filename> from the initrd file
4343 called C<initrdpath>. The filename must be given I<without> the
4344 initial C</> character.
4346 For example, in guestfish you could use the following command
4347 to examine the boot script (usually called C</init>)
4348 contained in a Linux initrd or initramfs image:
4350 initrd-cat /boot/initrd-<version>.img init
4352 See also C<guestfs_initrd_list>.");
4354 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4356 "get the UUID of a physical volume",
4358 This command returns the UUID of the LVM PV C<device>.");
4360 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4362 "get the UUID of a volume group",
4364 This command returns the UUID of the LVM VG named C<vgname>.");
4366 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4368 "get the UUID of a logical volume",
4370 This command returns the UUID of the LVM LV C<device>.");
4372 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4374 "get the PV UUIDs containing the volume group",
4376 Given a VG called C<vgname>, this returns the UUIDs of all
4377 the physical volumes that this volume group resides on.
4379 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4380 calls to associate physical volumes and volume groups.
4382 See also C<guestfs_vglvuuids>.");
4384 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4386 "get the LV UUIDs of all LVs in the volume group",
4388 Given a VG called C<vgname>, this returns the UUIDs of all
4389 the logical volumes created in this volume group.
4391 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4392 calls to associate logical volumes and volume groups.
4394 See also C<guestfs_vgpvuuids>.");
4396 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4397 [InitBasicFS, Always, TestOutputBuffer (
4398 [["write_file"; "/src"; "hello, world"; "0"];
4399 ["copy_size"; "/src"; "/dest"; "5"];
4400 ["read_file"; "/dest"]], "hello")],
4401 "copy size bytes from source to destination using dd",
4403 This command copies exactly C<size> bytes from one source device
4404 or file C<src> to another destination device or file C<dest>.
4406 Note this will fail if the source is too short or if the destination
4407 is not large enough.");
4409 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4410 [InitBasicFSonLVM, Always, TestRun (
4411 [["zero_device"; "/dev/VG/LV"]])],
4412 "write zeroes to an entire device",
4414 This command writes zeroes over the entire C<device>. Compare
4415 with C<guestfs_zero> which just zeroes the first few blocks of
4418 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4419 [InitBasicFS, Always, TestOutput (
4420 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4421 ["cat"; "/hello"]], "hello\n")],
4422 "unpack compressed tarball to directory",
4424 This command uploads and unpacks local file C<tarball> (an
4425 I<xz compressed> tar file) into C<directory>.");
4427 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4429 "pack directory into compressed tarball",
4431 This command packs the contents of C<directory> and downloads
4432 it to local file C<tarball> (as an xz compressed tar archive).");
4434 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4436 "resize an NTFS filesystem",
4438 This command resizes an NTFS filesystem, expanding or
4439 shrinking it to the size of the underlying device.
4440 See also L<ntfsresize(8)>.");
4442 ("vgscan", (RErr, []), 232, [],
4443 [InitEmpty, Always, TestRun (
4445 "rescan for LVM physical volumes, volume groups and logical volumes",
4447 This rescans all block devices and rebuilds the list of LVM
4448 physical volumes, volume groups and logical volumes.");
4450 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4451 [InitEmpty, Always, TestRun (
4452 [["part_init"; "/dev/sda"; "mbr"];
4453 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4454 ["part_del"; "/dev/sda"; "1"]])],
4455 "delete a partition",
4457 This command deletes the partition numbered C<partnum> on C<device>.
4459 Note that in the case of MBR partitioning, deleting an
4460 extended partition also deletes any logical partitions
4463 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4464 [InitEmpty, Always, TestOutputTrue (
4465 [["part_init"; "/dev/sda"; "mbr"];
4466 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4467 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4468 ["part_get_bootable"; "/dev/sda"; "1"]])],
4469 "return true if a partition is bootable",
4471 This command returns true if the partition C<partnum> on
4472 C<device> has the bootable flag set.
4474 See also C<guestfs_part_set_bootable>.");
4476 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4477 [InitEmpty, Always, TestOutputInt (
4478 [["part_init"; "/dev/sda"; "mbr"];
4479 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4480 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4481 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4482 "get the MBR type byte (ID byte) from a partition",
4484 Returns the MBR type byte (also known as the ID byte) from
4485 the numbered partition C<partnum>.
4487 Note that only MBR (old DOS-style) partitions have type bytes.
4488 You will get undefined results for other partition table
4489 types (see C<guestfs_part_get_parttype>).");
4491 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4492 [], (* tested by part_get_mbr_id *)
4493 "set the MBR type byte (ID byte) of a partition",
4495 Sets the MBR type byte (also known as the ID byte) of
4496 the numbered partition C<partnum> to C<idbyte>. Note
4497 that the type bytes quoted in most documentation are
4498 in fact hexadecimal numbers, but usually documented
4499 without any leading \"0x\" which might be confusing.
4501 Note that only MBR (old DOS-style) partitions have type bytes.
4502 You will get undefined results for other partition table
4503 types (see C<guestfs_part_get_parttype>).");
4505 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4506 [InitISOFS, Always, TestOutput (
4507 [["checksum_device"; "md5"; "/dev/sdd"]],
4508 (Digest.to_hex (Digest.file "images/test.iso")))],
4509 "compute MD5, SHAx or CRC checksum of the contents of a device",
4511 This call computes the MD5, SHAx or CRC checksum of the
4512 contents of the device named C<device>. For the types of
4513 checksums supported see the C<guestfs_checksum> command.");
4515 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4516 [InitNone, Always, TestRun (
4517 [["part_disk"; "/dev/sda"; "mbr"];
4518 ["pvcreate"; "/dev/sda1"];
4519 ["vgcreate"; "VG"; "/dev/sda1"];
4520 ["lvcreate"; "LV"; "VG"; "10"];
4521 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4522 "expand an LV to fill free space",
4524 This expands an existing logical volume C<lv> so that it fills
4525 C<pc>% of the remaining free space in the volume group. Commonly
4526 you would call this with pc = 100 which expands the logical volume
4527 as much as possible, using all remaining free space in the volume
4530 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4531 [], (* XXX Augeas code needs tests. *)
4532 "clear Augeas path",
4534 Set the value associated with C<path> to C<NULL>. This
4535 is the same as the L<augtool(1)> C<clear> command.");
4537 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4538 [InitEmpty, Always, TestOutputInt (
4539 [["get_umask"]], 0o22)],
4540 "get the current umask",
4542 Return the current umask. By default the umask is C<022>
4543 unless it has been set by calling C<guestfs_umask>.");
4545 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4547 "upload a file to the appliance (internal use only)",
4549 The C<guestfs_debug_upload> command uploads a file to
4550 the libguestfs appliance.
4552 There is no comprehensive help for this command. You have
4553 to look at the file C<daemon/debug.c> in the libguestfs source
4554 to find out what it is for.");
4556 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4557 [InitBasicFS, Always, TestOutput (
4558 [["base64_in"; "../images/hello.b64"; "/hello"];
4559 ["cat"; "/hello"]], "hello\n")],
4560 "upload base64-encoded data to file",
4562 This command uploads base64-encoded data from C<base64file>
4565 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4567 "download file and encode as base64",
4569 This command downloads the contents of C<filename>, writing
4570 it out to local file C<base64file> encoded as base64.");
4572 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4574 "compute MD5, SHAx or CRC checksum of files in a directory",
4576 This command computes the checksums of all regular files in
4577 C<directory> and then emits a list of those checksums to
4578 the local output file C<sumsfile>.
4580 This can be used for verifying the integrity of a virtual
4581 machine. However to be properly secure you should pay
4582 attention to the output of the checksum command (it uses
4583 the ones from GNU coreutils). In particular when the
4584 filename is not printable, coreutils uses a special
4585 backslash syntax. For more information, see the GNU
4586 coreutils info file.");
4590 let all_functions = non_daemon_functions @ daemon_functions
4592 (* In some places we want the functions to be displayed sorted
4593 * alphabetically, so this is useful:
4595 let all_functions_sorted =
4596 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4597 compare n1 n2) all_functions
4599 (* Field types for structures. *)
4601 | FChar (* C 'char' (really, a 7 bit byte). *)
4602 | FString (* nul-terminated ASCII string, NOT NULL. *)
4603 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4608 | FBytes (* Any int measure that counts bytes. *)
4609 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4610 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4612 (* Because we generate extra parsing code for LVM command line tools,
4613 * we have to pull out the LVM columns separately here.
4623 "pv_attr", FString (* XXX *);
4624 "pv_pe_count", FInt64;
4625 "pv_pe_alloc_count", FInt64;
4628 "pv_mda_count", FInt64;
4629 "pv_mda_free", FBytes;
4630 (* Not in Fedora 10:
4631 "pv_mda_size", FBytes;
4638 "vg_attr", FString (* XXX *);
4641 "vg_sysid", FString;
4642 "vg_extent_size", FBytes;
4643 "vg_extent_count", FInt64;
4644 "vg_free_count", FInt64;
4649 "snap_count", FInt64;
4652 "vg_mda_count", FInt64;
4653 "vg_mda_free", FBytes;
4654 (* Not in Fedora 10:
4655 "vg_mda_size", FBytes;
4661 "lv_attr", FString (* XXX *);
4664 "lv_kernel_major", FInt64;
4665 "lv_kernel_minor", FInt64;
4667 "seg_count", FInt64;
4669 "snap_percent", FOptPercent;
4670 "copy_percent", FOptPercent;
4673 "mirror_log", FString;
4677 (* Names and fields in all structures (in RStruct and RStructList)
4681 (* The old RIntBool return type, only ever used for aug_defnode. Do
4682 * not use this struct in any new code.
4685 "i", FInt32; (* for historical compatibility *)
4686 "b", FInt32; (* for historical compatibility *)
4689 (* LVM PVs, VGs, LVs. *)
4690 "lvm_pv", lvm_pv_cols;
4691 "lvm_vg", lvm_vg_cols;
4692 "lvm_lv", lvm_lv_cols;
4694 (* Column names and types from stat structures.
4695 * NB. Can't use things like 'st_atime' because glibc header files
4696 * define some of these as macros. Ugh.
4727 (* Column names in dirent structure. *)
4730 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4735 (* Version numbers. *)
4743 (* Extended attribute. *)
4745 "attrname", FString;
4749 (* Inotify events. *)
4753 "in_cookie", FUInt32;
4757 (* Partition table entry. *)
4760 "part_start", FBytes;
4762 "part_size", FBytes;
4764 ] (* end of structs *)
4766 (* Ugh, Java has to be different ..
4767 * These names are also used by the Haskell bindings.
4769 let java_structs = [
4770 "int_bool", "IntBool";
4775 "statvfs", "StatVFS";
4777 "version", "Version";
4779 "inotify_event", "INotifyEvent";
4780 "partition", "Partition";
4783 (* What structs are actually returned. *)
4784 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4786 (* Returns a list of RStruct/RStructList structs that are returned
4787 * by any function. Each element of returned list is a pair:
4789 * (structname, RStructOnly)
4790 * == there exists function which returns RStruct (_, structname)
4791 * (structname, RStructListOnly)
4792 * == there exists function which returns RStructList (_, structname)
4793 * (structname, RStructAndList)
4794 * == there are functions returning both RStruct (_, structname)
4795 * and RStructList (_, structname)
4797 let rstructs_used_by functions =
4798 (* ||| is a "logical OR" for rstructs_used_t *)
4802 | _, RStructAndList -> RStructAndList
4803 | RStructOnly, RStructListOnly
4804 | RStructListOnly, RStructOnly -> RStructAndList
4805 | RStructOnly, RStructOnly -> RStructOnly
4806 | RStructListOnly, RStructListOnly -> RStructListOnly
4809 let h = Hashtbl.create 13 in
4811 (* if elem->oldv exists, update entry using ||| operator,
4812 * else just add elem->newv to the hash
4814 let update elem newv =
4815 try let oldv = Hashtbl.find h elem in
4816 Hashtbl.replace h elem (newv ||| oldv)
4817 with Not_found -> Hashtbl.add h elem newv
4821 fun (_, style, _, _, _, _, _) ->
4822 match fst style with
4823 | RStruct (_, structname) -> update structname RStructOnly
4824 | RStructList (_, structname) -> update structname RStructListOnly
4828 (* return key->values as a list of (key,value) *)
4829 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4831 (* Used for testing language bindings. *)
4833 | CallString of string
4834 | CallOptString of string option
4835 | CallStringList of string list
4837 | CallInt64 of int64
4840 (* Used to memoize the result of pod2text. *)
4841 let pod2text_memo_filename = "src/.pod2text.data"
4842 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4844 let chan = open_in pod2text_memo_filename in
4845 let v = input_value chan in
4849 _ -> Hashtbl.create 13
4850 let pod2text_memo_updated () =
4851 let chan = open_out pod2text_memo_filename in
4852 output_value chan pod2text_memo;
4855 (* Useful functions.
4856 * Note we don't want to use any external OCaml libraries which
4857 * makes this a bit harder than it should be.
4859 module StringMap = Map.Make (String)
4861 let failwithf fs = ksprintf failwith fs
4863 let unique = let i = ref 0 in fun () -> incr i; !i
4865 let replace_char s c1 c2 =
4866 let s2 = String.copy s in
4867 let r = ref false in
4868 for i = 0 to String.length s2 - 1 do
4869 if String.unsafe_get s2 i = c1 then (
4870 String.unsafe_set s2 i c2;
4874 if not !r then s else s2
4878 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4880 let triml ?(test = isspace) str =
4882 let n = ref (String.length str) in
4883 while !n > 0 && test str.[!i]; do
4888 else String.sub str !i !n
4890 let trimr ?(test = isspace) str =
4891 let n = ref (String.length str) in
4892 while !n > 0 && test str.[!n-1]; do
4895 if !n = String.length str then str
4896 else String.sub str 0 !n
4898 let trim ?(test = isspace) str =
4899 trimr ~test (triml ~test str)
4901 let rec find s sub =
4902 let len = String.length s in
4903 let sublen = String.length sub in
4905 if i <= len-sublen then (
4907 if j < sublen then (
4908 if s.[i+j] = sub.[j] then loop2 (j+1)
4914 if r = -1 then loop (i+1) else r
4920 let rec replace_str s s1 s2 =
4921 let len = String.length s in
4922 let sublen = String.length s1 in
4923 let i = find s s1 in
4926 let s' = String.sub s 0 i in
4927 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4928 s' ^ s2 ^ replace_str s'' s1 s2
4931 let rec string_split sep str =
4932 let len = String.length str in
4933 let seplen = String.length sep in
4934 let i = find str sep in
4935 if i = -1 then [str]
4937 let s' = String.sub str 0 i in
4938 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4939 s' :: string_split sep s''
4942 let files_equal n1 n2 =
4943 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4944 match Sys.command cmd with
4947 | i -> failwithf "%s: failed with error code %d" cmd i
4949 let rec filter_map f = function
4953 | Some y -> y :: filter_map f xs
4954 | None -> filter_map f xs
4956 let rec find_map f = function
4957 | [] -> raise Not_found
4961 | None -> find_map f xs
4964 let rec loop i = function
4966 | x :: xs -> f i x; loop (i+1) xs
4971 let rec loop i = function
4973 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4977 let count_chars c str =
4978 let count = ref 0 in
4979 for i = 0 to String.length str - 1 do
4980 if c = String.unsafe_get str i then incr count
4984 let name_of_argt = function
4985 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4986 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4987 | FileIn n | FileOut n -> n
4989 let java_name_of_struct typ =
4990 try List.assoc typ java_structs
4993 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4995 let cols_of_struct typ =
4996 try List.assoc typ structs
4998 failwithf "cols_of_struct: unknown struct %s" typ
5000 let seq_of_test = function
5001 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5002 | TestOutputListOfDevices (s, _)
5003 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5004 | TestOutputTrue s | TestOutputFalse s
5005 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5006 | TestOutputStruct (s, _)
5007 | TestLastFail s -> s
5009 (* Handling for function flags. *)
5010 let protocol_limit_warning =
5011 "Because of the message protocol, there is a transfer limit
5012 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5014 let danger_will_robinson =
5015 "B<This command is dangerous. Without careful use you
5016 can easily destroy all your data>."
5018 let deprecation_notice flags =
5021 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5023 sprintf "This function is deprecated.
5024 In new code, use the C<%s> call instead.
5026 Deprecated functions will not be removed from the API, but the
5027 fact that they are deprecated indicates that there are problems
5028 with correct use of these functions." alt in
5033 (* Create list of optional groups. *)
5035 let h = Hashtbl.create 13 in
5037 fun (name, _, _, flags, _, _, _) ->
5041 let names = try Hashtbl.find h group with Not_found -> [] in
5042 Hashtbl.replace h group (name :: names)
5046 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5049 fun group -> group, List.sort compare (Hashtbl.find h group)
5051 List.sort (fun x y -> compare (fst x) (fst y)) groups
5053 (* Check function names etc. for consistency. *)
5054 let check_functions () =
5055 let contains_uppercase str =
5056 let len = String.length str in
5058 if i >= len then false
5061 if c >= 'A' && c <= 'Z' then true
5068 (* Check function names. *)
5070 fun (name, _, _, _, _, _, _) ->
5071 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5072 failwithf "function name %s does not need 'guestfs' prefix" name;
5074 failwithf "function name is empty";
5075 if name.[0] < 'a' || name.[0] > 'z' then
5076 failwithf "function name %s must start with lowercase a-z" name;
5077 if String.contains name '-' then
5078 failwithf "function name %s should not contain '-', use '_' instead."
5082 (* Check function parameter/return names. *)
5084 fun (name, style, _, _, _, _, _) ->
5085 let check_arg_ret_name n =
5086 if contains_uppercase n then
5087 failwithf "%s param/ret %s should not contain uppercase chars"
5089 if String.contains n '-' || String.contains n '_' then
5090 failwithf "%s param/ret %s should not contain '-' or '_'"
5093 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;
5094 if n = "int" || n = "char" || n = "short" || n = "long" then
5095 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5096 if n = "i" || n = "n" then
5097 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5098 if n = "argv" || n = "args" then
5099 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5101 (* List Haskell, OCaml and C keywords here.
5102 * http://www.haskell.org/haskellwiki/Keywords
5103 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5104 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5105 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5106 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5107 * Omitting _-containing words, since they're handled above.
5108 * Omitting the OCaml reserved word, "val", is ok,
5109 * and saves us from renaming several parameters.
5112 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5113 "char"; "class"; "const"; "constraint"; "continue"; "data";
5114 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5115 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5116 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5117 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5118 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5120 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5121 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5122 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5123 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5124 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5125 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5126 "volatile"; "when"; "where"; "while";
5128 if List.mem n reserved then
5129 failwithf "%s has param/ret using reserved word %s" name n;
5132 (match fst style with
5134 | RInt n | RInt64 n | RBool n
5135 | RConstString n | RConstOptString n | RString n
5136 | RStringList n | RStruct (n, _) | RStructList (n, _)
5137 | RHashtable n | RBufferOut n ->
5138 check_arg_ret_name n
5140 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5143 (* Check short descriptions. *)
5145 fun (name, _, _, _, _, shortdesc, _) ->
5146 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5147 failwithf "short description of %s should begin with lowercase." name;
5148 let c = shortdesc.[String.length shortdesc-1] in
5149 if c = '\n' || c = '.' then
5150 failwithf "short description of %s should not end with . or \\n." name
5153 (* Check long descriptions. *)
5155 fun (name, _, _, _, _, _, longdesc) ->
5156 if longdesc.[String.length longdesc-1] = '\n' then
5157 failwithf "long description of %s should not end with \\n." name
5160 (* Check proc_nrs. *)
5162 fun (name, _, proc_nr, _, _, _, _) ->
5163 if proc_nr <= 0 then
5164 failwithf "daemon function %s should have proc_nr > 0" name
5168 fun (name, _, proc_nr, _, _, _, _) ->
5169 if proc_nr <> -1 then
5170 failwithf "non-daemon function %s should have proc_nr -1" name
5171 ) non_daemon_functions;
5174 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5177 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5178 let rec loop = function
5181 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5183 | (name1,nr1) :: (name2,nr2) :: _ ->
5184 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5192 (* Ignore functions that have no tests. We generate a
5193 * warning when the user does 'make check' instead.
5195 | name, _, _, _, [], _, _ -> ()
5196 | name, _, _, _, tests, _, _ ->
5200 match seq_of_test test with
5202 failwithf "%s has a test containing an empty sequence" name
5203 | cmds -> List.map List.hd cmds
5205 let funcs = List.flatten funcs in
5207 let tested = List.mem name funcs in
5210 failwithf "function %s has tests but does not test itself" name
5213 (* 'pr' prints to the current output file. *)
5214 let chan = ref Pervasives.stdout
5219 let i = count_chars '\n' str in
5220 lines := !lines + i;
5221 output_string !chan str
5224 let copyright_years =
5225 let this_year = 1900 + (localtime (time ())).tm_year in
5226 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5228 (* Generate a header block in a number of standard styles. *)
5229 type comment_style =
5230 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5231 type license = GPLv2plus | LGPLv2plus
5233 let generate_header ?(extra_inputs = []) comment license =
5234 let inputs = "src/generator.ml" :: extra_inputs in
5235 let c = match comment with
5236 | CStyle -> pr "/* "; " *"
5237 | CPlusPlusStyle -> pr "// "; "//"
5238 | HashStyle -> pr "# "; "#"
5239 | OCamlStyle -> pr "(* "; " *"
5240 | HaskellStyle -> pr "{- "; " " in
5241 pr "libguestfs generated file\n";
5242 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5243 List.iter (pr "%s %s\n" c) inputs;
5244 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5246 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5250 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5251 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5252 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5253 pr "%s (at your option) any later version.\n" c;
5255 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5256 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5257 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5258 pr "%s GNU General Public License for more details.\n" c;
5260 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5261 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5262 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5265 pr "%s This library is free software; you can redistribute it and/or\n" c;
5266 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5267 pr "%s License as published by the Free Software Foundation; either\n" c;
5268 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5270 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5271 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5272 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5273 pr "%s Lesser General Public License for more details.\n" c;
5275 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5276 pr "%s License along with this library; if not, write to the Free Software\n" c;
5277 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5280 | CStyle -> pr " */\n"
5283 | OCamlStyle -> pr " *)\n"
5284 | HaskellStyle -> pr "-}\n"
5288 (* Start of main code generation functions below this line. *)
5290 (* Generate the pod documentation for the C API. *)
5291 let rec generate_actions_pod () =
5293 fun (shortname, style, _, flags, _, _, longdesc) ->
5294 if not (List.mem NotInDocs flags) then (
5295 let name = "guestfs_" ^ shortname in
5296 pr "=head2 %s\n\n" name;
5298 generate_prototype ~extern:false ~handle:"g" name style;
5300 pr "%s\n\n" longdesc;
5301 (match fst style with
5303 pr "This function returns 0 on success or -1 on error.\n\n"
5305 pr "On error this function returns -1.\n\n"
5307 pr "On error this function returns -1.\n\n"
5309 pr "This function returns a C truth value on success or -1 on error.\n\n"
5311 pr "This function returns a string, or NULL on error.
5312 The string is owned by the guest handle and must I<not> be freed.\n\n"
5313 | RConstOptString _ ->
5314 pr "This function returns a string which may be NULL.
5315 There is way to return an error from this function.
5316 The string is owned by the guest handle and must I<not> be freed.\n\n"
5318 pr "This function returns a string, or NULL on error.
5319 I<The caller must free the returned string after use>.\n\n"
5321 pr "This function returns a NULL-terminated array of strings
5322 (like L<environ(3)>), or NULL if there was an error.
5323 I<The caller must free the strings and the array after use>.\n\n"
5324 | RStruct (_, typ) ->
5325 pr "This function returns a C<struct guestfs_%s *>,
5326 or NULL if there was an error.
5327 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5328 | RStructList (_, typ) ->
5329 pr "This function returns a C<struct guestfs_%s_list *>
5330 (see E<lt>guestfs-structs.hE<gt>),
5331 or NULL if there was an error.
5332 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5334 pr "This function returns a NULL-terminated array of
5335 strings, or NULL if there was an error.
5336 The array of strings will always have length C<2n+1>, where
5337 C<n> keys and values alternate, followed by the trailing NULL entry.
5338 I<The caller must free the strings and the array after use>.\n\n"
5340 pr "This function returns a buffer, or NULL on error.
5341 The size of the returned buffer is written to C<*size_r>.
5342 I<The caller must free the returned buffer after use>.\n\n"
5344 if List.mem ProtocolLimitWarning flags then
5345 pr "%s\n\n" protocol_limit_warning;
5346 if List.mem DangerWillRobinson flags then
5347 pr "%s\n\n" danger_will_robinson;
5348 match deprecation_notice flags with
5350 | Some txt -> pr "%s\n\n" txt
5352 ) all_functions_sorted
5354 and generate_structs_pod () =
5355 (* Structs documentation. *)
5358 pr "=head2 guestfs_%s\n" typ;
5360 pr " struct guestfs_%s {\n" typ;
5363 | name, FChar -> pr " char %s;\n" name
5364 | name, FUInt32 -> pr " uint32_t %s;\n" name
5365 | name, FInt32 -> pr " int32_t %s;\n" name
5366 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5367 | name, FInt64 -> pr " int64_t %s;\n" name
5368 | name, FString -> pr " char *%s;\n" name
5370 pr " /* The next two fields describe a byte array. */\n";
5371 pr " uint32_t %s_len;\n" name;
5372 pr " char *%s;\n" name
5374 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5375 pr " char %s[32];\n" name
5376 | name, FOptPercent ->
5377 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5378 pr " float %s;\n" name
5382 pr " struct guestfs_%s_list {\n" typ;
5383 pr " uint32_t len; /* Number of elements in list. */\n";
5384 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5387 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5388 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5393 and generate_availability_pod () =
5394 (* Availability documentation. *)
5398 fun (group, functions) ->
5399 pr "=item B<%s>\n" group;
5401 pr "The following functions:\n";
5402 List.iter (pr "L</guestfs_%s>\n") functions;
5408 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5409 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5411 * We have to use an underscore instead of a dash because otherwise
5412 * rpcgen generates incorrect code.
5414 * This header is NOT exported to clients, but see also generate_structs_h.
5416 and generate_xdr () =
5417 generate_header CStyle LGPLv2plus;
5419 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5420 pr "typedef string str<>;\n";
5423 (* Internal structures. *)
5427 pr "struct guestfs_int_%s {\n" typ;
5429 | name, FChar -> pr " char %s;\n" name
5430 | name, FString -> pr " string %s<>;\n" name
5431 | name, FBuffer -> pr " opaque %s<>;\n" name
5432 | name, FUUID -> pr " opaque %s[32];\n" name
5433 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5434 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5435 | name, FOptPercent -> pr " float %s;\n" name
5439 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5444 fun (shortname, style, _, _, _, _, _) ->
5445 let name = "guestfs_" ^ shortname in
5447 (match snd style with
5450 pr "struct %s_args {\n" name;
5453 | Pathname n | Device n | Dev_or_Path n | String n ->
5454 pr " string %s<>;\n" n
5455 | OptString n -> pr " str *%s;\n" n
5456 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5457 | Bool n -> pr " bool %s;\n" n
5458 | Int n -> pr " int %s;\n" n
5459 | Int64 n -> pr " hyper %s;\n" n
5460 | FileIn _ | FileOut _ -> ()
5464 (match fst style with
5467 pr "struct %s_ret {\n" name;
5471 pr "struct %s_ret {\n" name;
5472 pr " hyper %s;\n" n;
5475 pr "struct %s_ret {\n" name;
5478 | RConstString _ | RConstOptString _ ->
5479 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5481 pr "struct %s_ret {\n" name;
5482 pr " string %s<>;\n" n;
5485 pr "struct %s_ret {\n" name;
5486 pr " str %s<>;\n" n;
5488 | RStruct (n, typ) ->
5489 pr "struct %s_ret {\n" name;
5490 pr " guestfs_int_%s %s;\n" typ n;
5492 | RStructList (n, typ) ->
5493 pr "struct %s_ret {\n" name;
5494 pr " guestfs_int_%s_list %s;\n" typ n;
5497 pr "struct %s_ret {\n" name;
5498 pr " str %s<>;\n" n;
5501 pr "struct %s_ret {\n" name;
5502 pr " opaque %s<>;\n" n;
5507 (* Table of procedure numbers. *)
5508 pr "enum guestfs_procedure {\n";
5510 fun (shortname, _, proc_nr, _, _, _, _) ->
5511 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5513 pr " GUESTFS_PROC_NR_PROCS\n";
5517 (* Having to choose a maximum message size is annoying for several
5518 * reasons (it limits what we can do in the API), but it (a) makes
5519 * the protocol a lot simpler, and (b) provides a bound on the size
5520 * of the daemon which operates in limited memory space.
5522 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5525 (* Message header, etc. *)
5527 /* The communication protocol is now documented in the guestfs(3)
5531 const GUESTFS_PROGRAM = 0x2000F5F5;
5532 const GUESTFS_PROTOCOL_VERSION = 1;
5534 /* These constants must be larger than any possible message length. */
5535 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5536 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5538 enum guestfs_message_direction {
5539 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5540 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5543 enum guestfs_message_status {
5544 GUESTFS_STATUS_OK = 0,
5545 GUESTFS_STATUS_ERROR = 1
5548 const GUESTFS_ERROR_LEN = 256;
5550 struct guestfs_message_error {
5551 string error_message<GUESTFS_ERROR_LEN>;
5554 struct guestfs_message_header {
5555 unsigned prog; /* GUESTFS_PROGRAM */
5556 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5557 guestfs_procedure proc; /* GUESTFS_PROC_x */
5558 guestfs_message_direction direction;
5559 unsigned serial; /* message serial number */
5560 guestfs_message_status status;
5563 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5565 struct guestfs_chunk {
5566 int cancel; /* if non-zero, transfer is cancelled */
5567 /* data size is 0 bytes if the transfer has finished successfully */
5568 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5572 (* Generate the guestfs-structs.h file. *)
5573 and generate_structs_h () =
5574 generate_header CStyle LGPLv2plus;
5576 (* This is a public exported header file containing various
5577 * structures. The structures are carefully written to have
5578 * exactly the same in-memory format as the XDR structures that
5579 * we use on the wire to the daemon. The reason for creating
5580 * copies of these structures here is just so we don't have to
5581 * export the whole of guestfs_protocol.h (which includes much
5582 * unrelated and XDR-dependent stuff that we don't want to be
5583 * public, or required by clients).
5585 * To reiterate, we will pass these structures to and from the
5586 * client with a simple assignment or memcpy, so the format
5587 * must be identical to what rpcgen / the RFC defines.
5590 (* Public structures. *)
5593 pr "struct guestfs_%s {\n" typ;
5596 | name, FChar -> pr " char %s;\n" name
5597 | name, FString -> pr " char *%s;\n" name
5599 pr " uint32_t %s_len;\n" name;
5600 pr " char *%s;\n" name
5601 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5602 | name, FUInt32 -> pr " uint32_t %s;\n" name
5603 | name, FInt32 -> pr " int32_t %s;\n" name
5604 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5605 | name, FInt64 -> pr " int64_t %s;\n" name
5606 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5610 pr "struct guestfs_%s_list {\n" typ;
5611 pr " uint32_t len;\n";
5612 pr " struct guestfs_%s *val;\n" typ;
5615 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5616 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5620 (* Generate the guestfs-actions.h file. *)
5621 and generate_actions_h () =
5622 generate_header CStyle LGPLv2plus;
5624 fun (shortname, style, _, _, _, _, _) ->
5625 let name = "guestfs_" ^ shortname in
5626 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5630 (* Generate the guestfs-internal-actions.h file. *)
5631 and generate_internal_actions_h () =
5632 generate_header CStyle LGPLv2plus;
5634 fun (shortname, style, _, _, _, _, _) ->
5635 let name = "guestfs__" ^ shortname in
5636 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5638 ) non_daemon_functions
5640 (* Generate the client-side dispatch stubs. *)
5641 and generate_client_actions () =
5642 generate_header CStyle LGPLv2plus;
5649 #include <inttypes.h>
5651 #include \"guestfs.h\"
5652 #include \"guestfs-internal.h\"
5653 #include \"guestfs-internal-actions.h\"
5654 #include \"guestfs_protocol.h\"
5656 #define error guestfs_error
5657 //#define perrorf guestfs_perrorf
5658 #define safe_malloc guestfs_safe_malloc
5659 #define safe_realloc guestfs_safe_realloc
5660 //#define safe_strdup guestfs_safe_strdup
5661 #define safe_memdup guestfs_safe_memdup
5663 /* Check the return message from a call for validity. */
5665 check_reply_header (guestfs_h *g,
5666 const struct guestfs_message_header *hdr,
5667 unsigned int proc_nr, unsigned int serial)
5669 if (hdr->prog != GUESTFS_PROGRAM) {
5670 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5673 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5674 error (g, \"wrong protocol version (%%d/%%d)\",
5675 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5678 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5679 error (g, \"unexpected message direction (%%d/%%d)\",
5680 hdr->direction, GUESTFS_DIRECTION_REPLY);
5683 if (hdr->proc != proc_nr) {
5684 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5687 if (hdr->serial != serial) {
5688 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5695 /* Check we are in the right state to run a high-level action. */
5697 check_state (guestfs_h *g, const char *caller)
5699 if (!guestfs__is_ready (g)) {
5700 if (guestfs__is_config (g) || guestfs__is_launching (g))
5701 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5704 error (g, \"%%s called from the wrong state, %%d != READY\",
5705 caller, guestfs__get_state (g));
5713 (* Generate code to generate guestfish call traces. *)
5714 let trace_call shortname style =
5715 pr " if (guestfs__get_trace (g)) {\n";
5718 List.exists (function
5719 | StringList _ | DeviceList _ -> true
5720 | _ -> false) (snd style) in
5726 pr " printf (\"%s\");\n" shortname;
5729 | String n (* strings *)
5735 (* guestfish doesn't support string escaping, so neither do we *)
5736 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5737 | OptString n -> (* string option *)
5738 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5739 pr " else printf (\" null\");\n"
5741 | DeviceList n -> (* string list *)
5742 pr " putchar (' ');\n";
5743 pr " putchar ('\"');\n";
5744 pr " for (i = 0; %s[i]; ++i) {\n" n;
5745 pr " if (i > 0) putchar (' ');\n";
5746 pr " fputs (%s[i], stdout);\n" n;
5748 pr " putchar ('\"');\n";
5749 | Bool n -> (* boolean *)
5750 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5751 | Int n -> (* int *)
5752 pr " printf (\" %%d\", %s);\n" n
5754 pr " printf (\" %%\" PRIi64, %s);\n" n
5756 pr " putchar ('\\n');\n";
5761 (* For non-daemon functions, generate a wrapper around each function. *)
5763 fun (shortname, style, _, _, _, _, _) ->
5764 let name = "guestfs_" ^ shortname in
5766 generate_prototype ~extern:false ~semicolon:false ~newline:true
5767 ~handle:"g" name style;
5769 trace_call shortname style;
5770 pr " return guestfs__%s " shortname;
5771 generate_c_call_args ~handle:"g" style;
5775 ) non_daemon_functions;
5777 (* Client-side stubs for each function. *)
5779 fun (shortname, style, _, _, _, _, _) ->
5780 let name = "guestfs_" ^ shortname in
5782 (* Generate the action stub. *)
5783 generate_prototype ~extern:false ~semicolon:false ~newline:true
5784 ~handle:"g" name style;
5787 match fst style with
5788 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5789 | RConstString _ | RConstOptString _ ->
5790 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5791 | RString _ | RStringList _
5792 | RStruct _ | RStructList _
5793 | RHashtable _ | RBufferOut _ ->
5798 (match snd style with
5800 | _ -> pr " struct %s_args args;\n" name
5803 pr " guestfs_message_header hdr;\n";
5804 pr " guestfs_message_error err;\n";
5806 match fst style with
5808 | RConstString _ | RConstOptString _ ->
5809 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5811 | RBool _ | RString _ | RStringList _
5812 | RStruct _ | RStructList _
5813 | RHashtable _ | RBufferOut _ ->
5814 pr " struct %s_ret ret;\n" name;
5817 pr " int serial;\n";
5820 trace_call shortname style;
5821 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5822 shortname error_code;
5823 pr " guestfs___set_busy (g);\n";
5826 (* Send the main header and arguments. *)
5827 (match snd style with
5829 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5830 (String.uppercase shortname)
5834 | Pathname n | Device n | Dev_or_Path n | String n ->
5835 pr " args.%s = (char *) %s;\n" n n
5837 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5838 | StringList n | DeviceList n ->
5839 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5840 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5842 pr " args.%s = %s;\n" n n
5844 pr " args.%s = %s;\n" n n
5846 pr " args.%s = %s;\n" n n
5847 | FileIn _ | FileOut _ -> ()
5849 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5850 (String.uppercase shortname);
5851 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5854 pr " if (serial == -1) {\n";
5855 pr " guestfs___end_busy (g);\n";
5856 pr " return %s;\n" error_code;
5860 (* Send any additional files (FileIn) requested. *)
5861 let need_read_reply_label = ref false in
5865 pr " r = guestfs___send_file (g, %s);\n" n;
5866 pr " if (r == -1) {\n";
5867 pr " guestfs___end_busy (g);\n";
5868 pr " return %s;\n" error_code;
5870 pr " if (r == -2) /* daemon cancelled */\n";
5871 pr " goto read_reply;\n";
5872 need_read_reply_label := true;
5877 (* Wait for the reply from the remote end. *)
5878 if !need_read_reply_label then pr " read_reply:\n";
5879 pr " memset (&hdr, 0, sizeof hdr);\n";
5880 pr " memset (&err, 0, sizeof err);\n";
5881 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5883 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5887 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5890 pr " if (r == -1) {\n";
5891 pr " guestfs___end_busy (g);\n";
5892 pr " return %s;\n" error_code;
5896 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5897 (String.uppercase shortname);
5898 pr " guestfs___end_busy (g);\n";
5899 pr " return %s;\n" error_code;
5903 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5904 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5905 pr " free (err.error_message);\n";
5906 pr " guestfs___end_busy (g);\n";
5907 pr " return %s;\n" error_code;
5911 (* Expecting to receive further files (FileOut)? *)
5915 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5916 pr " guestfs___end_busy (g);\n";
5917 pr " return %s;\n" error_code;
5923 pr " guestfs___end_busy (g);\n";
5925 (match fst style with
5926 | RErr -> pr " return 0;\n"
5927 | RInt n | RInt64 n | RBool n ->
5928 pr " return ret.%s;\n" n
5929 | RConstString _ | RConstOptString _ ->
5930 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5932 pr " return ret.%s; /* caller will free */\n" n
5933 | RStringList n | RHashtable n ->
5934 pr " /* caller will free this, but we need to add a NULL entry */\n";
5935 pr " ret.%s.%s_val =\n" n n;
5936 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5937 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5939 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5940 pr " return ret.%s.%s_val;\n" n n
5942 pr " /* caller will free this */\n";
5943 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5944 | RStructList (n, _) ->
5945 pr " /* caller will free this */\n";
5946 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5948 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5949 pr " * _val might be NULL here. To make the API saner for\n";
5950 pr " * callers, we turn this case into a unique pointer (using\n";
5951 pr " * malloc(1)).\n";
5953 pr " if (ret.%s.%s_len > 0) {\n" n n;
5954 pr " *size_r = ret.%s.%s_len;\n" n n;
5955 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5957 pr " free (ret.%s.%s_val);\n" n n;
5958 pr " char *p = safe_malloc (g, 1);\n";
5959 pr " *size_r = ret.%s.%s_len;\n" n n;
5967 (* Functions to free structures. *)
5968 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5969 pr " * structure format is identical to the XDR format. See note in\n";
5970 pr " * generator.ml.\n";
5977 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5979 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5985 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5987 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5994 (* Generate daemon/actions.h. *)
5995 and generate_daemon_actions_h () =
5996 generate_header CStyle GPLv2plus;
5998 pr "#include \"../src/guestfs_protocol.h\"\n";
6002 fun (name, style, _, _, _, _, _) ->
6004 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6008 (* Generate the linker script which controls the visibility of
6009 * symbols in the public ABI and ensures no other symbols get
6010 * exported accidentally.
6012 and generate_linker_script () =
6013 generate_header HashStyle GPLv2plus;
6018 "guestfs_get_error_handler";
6019 "guestfs_get_out_of_memory_handler";
6020 "guestfs_last_error";
6021 "guestfs_set_error_handler";
6022 "guestfs_set_launch_done_callback";
6023 "guestfs_set_log_message_callback";
6024 "guestfs_set_out_of_memory_handler";
6025 "guestfs_set_subprocess_quit_callback";
6027 (* Unofficial parts of the API: the bindings code use these
6028 * functions, so it is useful to export them.
6030 "guestfs_safe_calloc";
6031 "guestfs_safe_malloc";
6034 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6038 List.map (fun (typ, _) ->
6039 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6042 let globals = List.sort compare (globals @ functions @ structs) in
6046 List.iter (pr " %s;\n") globals;
6053 (* Generate the server-side stubs. *)
6054 and generate_daemon_actions () =
6055 generate_header CStyle GPLv2plus;
6057 pr "#include <config.h>\n";
6059 pr "#include <stdio.h>\n";
6060 pr "#include <stdlib.h>\n";
6061 pr "#include <string.h>\n";
6062 pr "#include <inttypes.h>\n";
6063 pr "#include <rpc/types.h>\n";
6064 pr "#include <rpc/xdr.h>\n";
6066 pr "#include \"daemon.h\"\n";
6067 pr "#include \"c-ctype.h\"\n";
6068 pr "#include \"../src/guestfs_protocol.h\"\n";
6069 pr "#include \"actions.h\"\n";
6073 fun (name, style, _, _, _, _, _) ->
6074 (* Generate server-side stubs. *)
6075 pr "static void %s_stub (XDR *xdr_in)\n" name;
6078 match fst style with
6079 | RErr | RInt _ -> pr " int r;\n"; "-1"
6080 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6081 | RBool _ -> pr " int r;\n"; "-1"
6082 | RConstString _ | RConstOptString _ ->
6083 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6084 | RString _ -> pr " char *r;\n"; "NULL"
6085 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6086 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6087 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6089 pr " size_t size = 1;\n";
6093 (match snd style with
6096 pr " struct guestfs_%s_args args;\n" name;
6099 | Device n | Dev_or_Path n
6102 | OptString n -> pr " char *%s;\n" n
6103 | StringList n | DeviceList n -> pr " char **%s;\n" n
6104 | Bool n -> pr " int %s;\n" n
6105 | Int n -> pr " int %s;\n" n
6106 | Int64 n -> pr " int64_t %s;\n" n
6107 | FileIn _ | FileOut _ -> ()
6113 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6115 (match snd style with
6118 pr " memset (&args, 0, sizeof args);\n";
6120 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6122 pr " cancel_receive ();\n";
6123 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6127 pr " char *%s = args.%s;\n" n n
6129 let pr_list_handling_code n =
6130 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6131 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6132 pr " if (%s == NULL) {\n" n;
6134 pr " cancel_receive ();\n";
6135 pr " reply_with_perror (\"realloc\");\n";
6138 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6139 pr " args.%s.%s_val = %s;\n" n n n;
6145 pr " ABS_PATH (%s, %s, goto done);\n"
6146 n (if is_filein then "cancel_receive ()" else "");
6149 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6150 n (if is_filein then "cancel_receive ()" else "");
6153 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6154 n (if is_filein then "cancel_receive ()" else "");
6155 | String n -> pr_args n
6156 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6158 pr_list_handling_code n;
6160 pr_list_handling_code n;
6161 pr " /* Ensure that each is a device,\n";
6162 pr " * and perform device name translation. */\n";
6163 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6164 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6165 (if is_filein then "cancel_receive ()" else "");
6167 | Bool n -> pr " %s = args.%s;\n" n n
6168 | Int n -> pr " %s = args.%s;\n" n n
6169 | Int64 n -> pr " %s = args.%s;\n" n n
6170 | FileIn _ | FileOut _ -> ()
6176 (* this is used at least for do_equal *)
6177 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6178 (* Emit NEED_ROOT just once, even when there are two or
6179 more Pathname args *)
6180 pr " NEED_ROOT (%s, goto done);\n"
6181 (if is_filein then "cancel_receive ()" else "");
6184 (* Don't want to call the impl with any FileIn or FileOut
6185 * parameters, since these go "outside" the RPC protocol.
6188 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6190 pr " r = do_%s " name;
6191 generate_c_call_args (fst style, args');
6194 (match fst style with
6195 | RErr | RInt _ | RInt64 _ | RBool _
6196 | RConstString _ | RConstOptString _
6197 | RString _ | RStringList _ | RHashtable _
6198 | RStruct (_, _) | RStructList (_, _) ->
6199 pr " if (r == %s)\n" error_code;
6200 pr " /* do_%s has already called reply_with_error */\n" name;
6204 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6205 pr " * an ordinary zero-length buffer), so be careful ...\n";
6207 pr " if (size == 1 && r == %s)\n" error_code;
6208 pr " /* do_%s has already called reply_with_error */\n" name;
6213 (* If there are any FileOut parameters, then the impl must
6214 * send its own reply.
6217 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6219 pr " /* do_%s has already sent a reply */\n" name
6221 match fst style with
6222 | RErr -> pr " reply (NULL, NULL);\n"
6223 | RInt n | RInt64 n | RBool n ->
6224 pr " struct guestfs_%s_ret ret;\n" name;
6225 pr " ret.%s = r;\n" n;
6226 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6228 | RConstString _ | RConstOptString _ ->
6229 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6231 pr " struct guestfs_%s_ret ret;\n" name;
6232 pr " ret.%s = r;\n" n;
6233 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6236 | RStringList n | RHashtable n ->
6237 pr " struct guestfs_%s_ret ret;\n" name;
6238 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6239 pr " ret.%s.%s_val = r;\n" n n;
6240 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6242 pr " free_strings (r);\n"
6244 pr " struct guestfs_%s_ret ret;\n" name;
6245 pr " ret.%s = *r;\n" n;
6246 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6248 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6250 | RStructList (n, _) ->
6251 pr " struct guestfs_%s_ret ret;\n" name;
6252 pr " ret.%s = *r;\n" n;
6253 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6255 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6258 pr " struct guestfs_%s_ret ret;\n" name;
6259 pr " ret.%s.%s_val = r;\n" n n;
6260 pr " ret.%s.%s_len = size;\n" n n;
6261 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6266 (* Free the args. *)
6268 (match snd style with
6271 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6278 (* Dispatch function. *)
6279 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6281 pr " switch (proc_nr) {\n";
6284 fun (name, style, _, _, _, _, _) ->
6285 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6286 pr " %s_stub (xdr_in);\n" name;
6291 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";
6296 (* LVM columns and tokenization functions. *)
6297 (* XXX This generates crap code. We should rethink how we
6303 pr "static const char *lvm_%s_cols = \"%s\";\n"
6304 typ (String.concat "," (List.map fst cols));
6307 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6309 pr " char *tok, *p, *next;\n";
6313 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6316 pr " if (!str) {\n";
6317 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6320 pr " if (!*str || c_isspace (*str)) {\n";
6321 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6326 fun (name, coltype) ->
6327 pr " if (!tok) {\n";
6328 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6331 pr " p = strchrnul (tok, ',');\n";
6332 pr " if (*p) next = p+1; else next = NULL;\n";
6333 pr " *p = '\\0';\n";
6336 pr " r->%s = strdup (tok);\n" name;
6337 pr " if (r->%s == NULL) {\n" name;
6338 pr " perror (\"strdup\");\n";
6342 pr " for (i = j = 0; i < 32; ++j) {\n";
6343 pr " if (tok[j] == '\\0') {\n";
6344 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6346 pr " } else if (tok[j] != '-')\n";
6347 pr " r->%s[i++] = tok[j];\n" name;
6350 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6351 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6355 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6356 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6360 pr " if (tok[0] == '\\0')\n";
6361 pr " r->%s = -1;\n" name;
6362 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6363 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6366 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6367 assert false (* can never be an LVM column *)
6369 pr " tok = next;\n";
6372 pr " if (tok != NULL) {\n";
6373 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6380 pr "guestfs_int_lvm_%s_list *\n" typ;
6381 pr "parse_command_line_%ss (void)\n" typ;
6383 pr " char *out, *err;\n";
6384 pr " char *p, *pend;\n";
6386 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6387 pr " void *newp;\n";
6389 pr " ret = malloc (sizeof *ret);\n";
6390 pr " if (!ret) {\n";
6391 pr " reply_with_perror (\"malloc\");\n";
6392 pr " return NULL;\n";
6395 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6396 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6398 pr " r = command (&out, &err,\n";
6399 pr " \"lvm\", \"%ss\",\n" typ;
6400 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6401 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6402 pr " if (r == -1) {\n";
6403 pr " reply_with_error (\"%%s\", err);\n";
6404 pr " free (out);\n";
6405 pr " free (err);\n";
6406 pr " free (ret);\n";
6407 pr " return NULL;\n";
6410 pr " free (err);\n";
6412 pr " /* Tokenize each line of the output. */\n";
6415 pr " while (p) {\n";
6416 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6417 pr " if (pend) {\n";
6418 pr " *pend = '\\0';\n";
6422 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6425 pr " if (!*p) { /* Empty line? Skip it. */\n";
6430 pr " /* Allocate some space to store this next entry. */\n";
6431 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6432 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6433 pr " if (newp == NULL) {\n";
6434 pr " reply_with_perror (\"realloc\");\n";
6435 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6436 pr " free (ret);\n";
6437 pr " free (out);\n";
6438 pr " return NULL;\n";
6440 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6442 pr " /* Tokenize the next entry. */\n";
6443 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6444 pr " if (r == -1) {\n";
6445 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6446 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6447 pr " free (ret);\n";
6448 pr " free (out);\n";
6449 pr " return NULL;\n";
6456 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6458 pr " free (out);\n";
6459 pr " return ret;\n";
6462 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6464 (* Generate a list of function names, for debugging in the daemon.. *)
6465 and generate_daemon_names () =
6466 generate_header CStyle GPLv2plus;
6468 pr "#include <config.h>\n";
6470 pr "#include \"daemon.h\"\n";
6473 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6474 pr "const char *function_names[] = {\n";
6476 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6480 (* Generate the optional groups for the daemon to implement
6481 * guestfs_available.
6483 and generate_daemon_optgroups_c () =
6484 generate_header CStyle GPLv2plus;
6486 pr "#include <config.h>\n";
6488 pr "#include \"daemon.h\"\n";
6489 pr "#include \"optgroups.h\"\n";
6492 pr "struct optgroup optgroups[] = {\n";
6495 pr " { \"%s\", optgroup_%s_available },\n" group group
6497 pr " { NULL, NULL }\n";
6500 and generate_daemon_optgroups_h () =
6501 generate_header CStyle GPLv2plus;
6505 pr "extern int optgroup_%s_available (void);\n" group
6508 (* Generate the tests. *)
6509 and generate_tests () =
6510 generate_header CStyle GPLv2plus;
6517 #include <sys/types.h>
6520 #include \"guestfs.h\"
6521 #include \"guestfs-internal.h\"
6523 static guestfs_h *g;
6524 static int suppress_error = 0;
6526 static void print_error (guestfs_h *g, void *data, const char *msg)
6528 if (!suppress_error)
6529 fprintf (stderr, \"%%s\\n\", msg);
6532 /* FIXME: nearly identical code appears in fish.c */
6533 static void print_strings (char *const *argv)
6537 for (argc = 0; argv[argc] != NULL; ++argc)
6538 printf (\"\\t%%s\\n\", argv[argc]);
6542 static void print_table (char const *const *argv)
6546 for (i = 0; argv[i] != NULL; i += 2)
6547 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6553 (* Generate a list of commands which are not tested anywhere. *)
6554 pr "static void no_test_warnings (void)\n";
6557 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6559 fun (_, _, _, _, tests, _, _) ->
6560 let tests = filter_map (
6562 | (_, (Always|If _|Unless _), test) -> Some test
6563 | (_, Disabled, _) -> None
6565 let seq = List.concat (List.map seq_of_test tests) in
6566 let cmds_tested = List.map List.hd seq in
6567 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6571 fun (name, _, _, _, _, _, _) ->
6572 if not (Hashtbl.mem hash name) then
6573 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6579 (* Generate the actual tests. Note that we generate the tests
6580 * in reverse order, deliberately, so that (in general) the
6581 * newest tests run first. This makes it quicker and easier to
6586 fun (name, _, _, flags, tests, _, _) ->
6587 mapi (generate_one_test name flags) tests
6588 ) (List.rev all_functions) in
6589 let test_names = List.concat test_names in
6590 let nr_tests = List.length test_names in
6593 int main (int argc, char *argv[])
6596 unsigned long int n_failed = 0;
6597 const char *filename;
6599 int nr_tests, test_num = 0;
6601 setbuf (stdout, NULL);
6603 no_test_warnings ();
6605 g = guestfs_create ();
6607 printf (\"guestfs_create FAILED\\n\");
6608 exit (EXIT_FAILURE);
6611 guestfs_set_error_handler (g, print_error, NULL);
6613 guestfs_set_path (g, \"../appliance\");
6615 filename = \"test1.img\";
6616 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6619 exit (EXIT_FAILURE);
6621 if (lseek (fd, %d, SEEK_SET) == -1) {
6625 exit (EXIT_FAILURE);
6627 if (write (fd, &c, 1) == -1) {
6631 exit (EXIT_FAILURE);
6633 if (close (fd) == -1) {
6636 exit (EXIT_FAILURE);
6638 if (guestfs_add_drive (g, filename) == -1) {
6639 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6640 exit (EXIT_FAILURE);
6643 filename = \"test2.img\";
6644 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6647 exit (EXIT_FAILURE);
6649 if (lseek (fd, %d, SEEK_SET) == -1) {
6653 exit (EXIT_FAILURE);
6655 if (write (fd, &c, 1) == -1) {
6659 exit (EXIT_FAILURE);
6661 if (close (fd) == -1) {
6664 exit (EXIT_FAILURE);
6666 if (guestfs_add_drive (g, filename) == -1) {
6667 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6668 exit (EXIT_FAILURE);
6671 filename = \"test3.img\";
6672 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6675 exit (EXIT_FAILURE);
6677 if (lseek (fd, %d, SEEK_SET) == -1) {
6681 exit (EXIT_FAILURE);
6683 if (write (fd, &c, 1) == -1) {
6687 exit (EXIT_FAILURE);
6689 if (close (fd) == -1) {
6692 exit (EXIT_FAILURE);
6694 if (guestfs_add_drive (g, filename) == -1) {
6695 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6696 exit (EXIT_FAILURE);
6699 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6700 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6701 exit (EXIT_FAILURE);
6704 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6707 if (guestfs_launch (g) == -1) {
6708 printf (\"guestfs_launch FAILED\\n\");
6709 exit (EXIT_FAILURE);
6712 /* Cancel previous alarm. */
6717 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6721 pr " test_num++;\n";
6722 pr " if (guestfs_get_verbose (g))\n";
6723 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
6724 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6725 pr " if (%s () == -1) {\n" test_name;
6726 pr " printf (\"%s FAILED\\n\");\n" test_name;
6727 pr " n_failed++;\n";
6732 pr " guestfs_close (g);\n";
6733 pr " unlink (\"test1.img\");\n";
6734 pr " unlink (\"test2.img\");\n";
6735 pr " unlink (\"test3.img\");\n";
6738 pr " if (n_failed > 0) {\n";
6739 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6740 pr " exit (EXIT_FAILURE);\n";
6744 pr " exit (EXIT_SUCCESS);\n";
6747 and generate_one_test name flags i (init, prereq, test) =
6748 let test_name = sprintf "test_%s_%d" name i in
6751 static int %s_skip (void)
6755 str = getenv (\"TEST_ONLY\");
6757 return strstr (str, \"%s\") == NULL;
6758 str = getenv (\"SKIP_%s\");
6759 if (str && STREQ (str, \"1\")) return 1;
6760 str = getenv (\"SKIP_TEST_%s\");
6761 if (str && STREQ (str, \"1\")) return 1;
6765 " test_name name (String.uppercase test_name) (String.uppercase name);
6768 | Disabled | Always -> ()
6769 | If code | Unless code ->
6770 pr "static int %s_prereq (void)\n" test_name;
6778 static int %s (void)
6781 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6785 " test_name test_name test_name;
6787 (* Optional functions should only be tested if the relevant
6788 * support is available in the daemon.
6794 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6796 pr " suppress_error = 1;\n";
6797 pr " r = guestfs_available (g, (char **) groups);\n";
6798 pr " suppress_error = 0;\n";
6799 pr " if (r == -1) {\n";
6800 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6809 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6811 pr " if (! %s_prereq ()) {\n" test_name;
6812 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6816 generate_one_test_body name i test_name init test;
6818 pr " if (%s_prereq ()) {\n" test_name;
6819 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6823 generate_one_test_body name i test_name init test;
6825 generate_one_test_body name i test_name init test
6833 and generate_one_test_body name i test_name init test =
6835 | InitNone (* XXX at some point, InitNone and InitEmpty became
6836 * folded together as the same thing. Really we should
6837 * make InitNone do nothing at all, but the tests may
6838 * need to be checked to make sure this is OK.
6841 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6842 List.iter (generate_test_command_call test_name)
6843 [["blockdev_setrw"; "/dev/sda"];
6847 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6848 List.iter (generate_test_command_call test_name)
6849 [["blockdev_setrw"; "/dev/sda"];
6852 ["part_disk"; "/dev/sda"; "mbr"]]
6854 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6855 List.iter (generate_test_command_call test_name)
6856 [["blockdev_setrw"; "/dev/sda"];
6859 ["part_disk"; "/dev/sda"; "mbr"];
6860 ["mkfs"; "ext2"; "/dev/sda1"];
6861 ["mount_options"; ""; "/dev/sda1"; "/"]]
6862 | InitBasicFSonLVM ->
6863 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6865 List.iter (generate_test_command_call test_name)
6866 [["blockdev_setrw"; "/dev/sda"];
6869 ["part_disk"; "/dev/sda"; "mbr"];
6870 ["pvcreate"; "/dev/sda1"];
6871 ["vgcreate"; "VG"; "/dev/sda1"];
6872 ["lvcreate"; "LV"; "VG"; "8"];
6873 ["mkfs"; "ext2"; "/dev/VG/LV"];
6874 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6876 pr " /* InitISOFS for %s */\n" test_name;
6877 List.iter (generate_test_command_call test_name)
6878 [["blockdev_setrw"; "/dev/sda"];
6881 ["mount_ro"; "/dev/sdd"; "/"]]
6884 let get_seq_last = function
6886 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6889 let seq = List.rev seq in
6890 List.rev (List.tl seq), List.hd seq
6895 pr " /* TestRun for %s (%d) */\n" name i;
6896 List.iter (generate_test_command_call test_name) seq
6897 | TestOutput (seq, expected) ->
6898 pr " /* TestOutput for %s (%d) */\n" name i;
6899 pr " const char *expected = \"%s\";\n" (c_quote expected);
6900 let seq, last = get_seq_last seq in
6902 pr " if (STRNEQ (r, expected)) {\n";
6903 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6907 List.iter (generate_test_command_call test_name) seq;
6908 generate_test_command_call ~test test_name last
6909 | TestOutputList (seq, expected) ->
6910 pr " /* TestOutputList for %s (%d) */\n" name i;
6911 let seq, last = get_seq_last seq in
6915 pr " if (!r[%d]) {\n" i;
6916 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6917 pr " print_strings (r);\n";
6921 pr " const char *expected = \"%s\";\n" (c_quote str);
6922 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6923 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6928 pr " if (r[%d] != NULL) {\n" (List.length expected);
6929 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6931 pr " print_strings (r);\n";
6935 List.iter (generate_test_command_call test_name) seq;
6936 generate_test_command_call ~test test_name last
6937 | TestOutputListOfDevices (seq, expected) ->
6938 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6939 let seq, last = get_seq_last seq in
6943 pr " if (!r[%d]) {\n" i;
6944 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6945 pr " print_strings (r);\n";
6949 pr " const char *expected = \"%s\";\n" (c_quote str);
6950 pr " r[%d][5] = 's';\n" i;
6951 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6952 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6957 pr " if (r[%d] != NULL) {\n" (List.length expected);
6958 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6960 pr " print_strings (r);\n";
6964 List.iter (generate_test_command_call test_name) seq;
6965 generate_test_command_call ~test test_name last
6966 | TestOutputInt (seq, expected) ->
6967 pr " /* TestOutputInt for %s (%d) */\n" name i;
6968 let seq, last = get_seq_last seq in
6970 pr " if (r != %d) {\n" expected;
6971 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6977 List.iter (generate_test_command_call test_name) seq;
6978 generate_test_command_call ~test test_name last
6979 | TestOutputIntOp (seq, op, expected) ->
6980 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6981 let seq, last = get_seq_last seq in
6983 pr " if (! (r %s %d)) {\n" op expected;
6984 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6985 test_name op expected;
6990 List.iter (generate_test_command_call test_name) seq;
6991 generate_test_command_call ~test test_name last
6992 | TestOutputTrue seq ->
6993 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6994 let seq, last = get_seq_last seq in
6997 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7002 List.iter (generate_test_command_call test_name) seq;
7003 generate_test_command_call ~test test_name last
7004 | TestOutputFalse seq ->
7005 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7006 let seq, last = get_seq_last seq in
7009 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7014 List.iter (generate_test_command_call test_name) seq;
7015 generate_test_command_call ~test test_name last
7016 | TestOutputLength (seq, expected) ->
7017 pr " /* TestOutputLength for %s (%d) */\n" name i;
7018 let seq, last = get_seq_last seq in
7021 pr " for (j = 0; j < %d; ++j)\n" expected;
7022 pr " if (r[j] == NULL) {\n";
7023 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7025 pr " print_strings (r);\n";
7028 pr " if (r[j] != NULL) {\n";
7029 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7031 pr " print_strings (r);\n";
7035 List.iter (generate_test_command_call test_name) seq;
7036 generate_test_command_call ~test test_name last
7037 | TestOutputBuffer (seq, expected) ->
7038 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7039 pr " const char *expected = \"%s\";\n" (c_quote expected);
7040 let seq, last = get_seq_last seq in
7041 let len = String.length expected in
7043 pr " if (size != %d) {\n" len;
7044 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7047 pr " if (STRNEQLEN (r, expected, size)) {\n";
7048 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7052 List.iter (generate_test_command_call test_name) seq;
7053 generate_test_command_call ~test test_name last
7054 | TestOutputStruct (seq, checks) ->
7055 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7056 let seq, last = get_seq_last seq in
7060 | CompareWithInt (field, expected) ->
7061 pr " if (r->%s != %d) {\n" field expected;
7062 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7063 test_name field expected;
7064 pr " (int) r->%s);\n" field;
7067 | CompareWithIntOp (field, op, expected) ->
7068 pr " if (!(r->%s %s %d)) {\n" field op expected;
7069 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7070 test_name field op expected;
7071 pr " (int) r->%s);\n" field;
7074 | CompareWithString (field, expected) ->
7075 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7076 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7077 test_name field expected;
7078 pr " r->%s);\n" field;
7081 | CompareFieldsIntEq (field1, field2) ->
7082 pr " if (r->%s != r->%s) {\n" field1 field2;
7083 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7084 test_name field1 field2;
7085 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7088 | CompareFieldsStrEq (field1, field2) ->
7089 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7090 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7091 test_name field1 field2;
7092 pr " r->%s, r->%s);\n" field1 field2;
7097 List.iter (generate_test_command_call test_name) seq;
7098 generate_test_command_call ~test test_name last
7099 | TestLastFail seq ->
7100 pr " /* TestLastFail for %s (%d) */\n" name i;
7101 let seq, last = get_seq_last seq in
7102 List.iter (generate_test_command_call test_name) seq;
7103 generate_test_command_call test_name ~expect_error:true last
7105 (* Generate the code to run a command, leaving the result in 'r'.
7106 * If you expect to get an error then you should set expect_error:true.
7108 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7110 | [] -> assert false
7112 (* Look up the command to find out what args/ret it has. *)
7115 let _, style, _, _, _, _, _ =
7116 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7119 failwithf "%s: in test, command %s was not found" test_name name in
7121 if List.length (snd style) <> List.length args then
7122 failwithf "%s: in test, wrong number of args given to %s"
7129 | OptString n, "NULL" -> ()
7132 | Dev_or_Path n, arg
7134 | OptString n, arg ->
7135 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7139 | FileIn _, _ | FileOut _, _ -> ()
7140 | StringList n, "" | DeviceList n, "" ->
7141 pr " const char *const %s[1] = { NULL };\n" n
7142 | StringList n, arg | DeviceList n, arg ->
7143 let strs = string_split " " arg in
7146 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7148 pr " const char *const %s[] = {\n" n;
7150 fun i _ -> pr " %s_%d,\n" n i
7154 ) (List.combine (snd style) args);
7157 match fst style with
7158 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7159 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7160 | RConstString _ | RConstOptString _ ->
7161 pr " const char *r;\n"; "NULL"
7162 | RString _ -> pr " char *r;\n"; "NULL"
7163 | RStringList _ | RHashtable _ ->
7167 | RStruct (_, typ) ->
7168 pr " struct guestfs_%s *r;\n" typ; "NULL"
7169 | RStructList (_, typ) ->
7170 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7173 pr " size_t size;\n";
7176 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7177 pr " r = guestfs_%s (g" name;
7179 (* Generate the parameters. *)
7182 | OptString _, "NULL" -> pr ", NULL"
7184 | Device n, _ | Dev_or_Path n, _
7188 | FileIn _, arg | FileOut _, arg ->
7189 pr ", \"%s\"" (c_quote arg)
7190 | StringList n, _ | DeviceList n, _ ->
7191 pr ", (char **) %s" n
7194 try int_of_string arg
7195 with Failure "int_of_string" ->
7196 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7200 try Int64.of_string arg
7201 with Failure "int_of_string" ->
7202 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7205 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7206 ) (List.combine (snd style) args);
7208 (match fst style with
7209 | RBufferOut _ -> pr ", &size"
7215 if not expect_error then
7216 pr " if (r == %s)\n" error_code
7218 pr " if (r != %s)\n" error_code;
7221 (* Insert the test code. *)
7227 (match fst style with
7228 | RErr | RInt _ | RInt64 _ | RBool _
7229 | RConstString _ | RConstOptString _ -> ()
7230 | RString _ | RBufferOut _ -> pr " free (r);\n"
7231 | RStringList _ | RHashtable _ ->
7232 pr " for (i = 0; r[i] != NULL; ++i)\n";
7233 pr " free (r[i]);\n";
7235 | RStruct (_, typ) ->
7236 pr " guestfs_free_%s (r);\n" typ
7237 | RStructList (_, typ) ->
7238 pr " guestfs_free_%s_list (r);\n" typ
7244 let str = replace_str str "\r" "\\r" in
7245 let str = replace_str str "\n" "\\n" in
7246 let str = replace_str str "\t" "\\t" in
7247 let str = replace_str str "\000" "\\0" in
7250 (* Generate a lot of different functions for guestfish. *)
7251 and generate_fish_cmds () =
7252 generate_header CStyle GPLv2plus;
7256 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7258 let all_functions_sorted =
7260 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7261 ) all_functions_sorted in
7263 pr "#include <config.h>\n";
7265 pr "#include <stdio.h>\n";
7266 pr "#include <stdlib.h>\n";
7267 pr "#include <string.h>\n";
7268 pr "#include <inttypes.h>\n";
7270 pr "#include <guestfs.h>\n";
7271 pr "#include \"c-ctype.h\"\n";
7272 pr "#include \"full-write.h\"\n";
7273 pr "#include \"xstrtol.h\"\n";
7274 pr "#include \"fish.h\"\n";
7277 (* list_commands function, which implements guestfish -h *)
7278 pr "void list_commands (void)\n";
7280 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7281 pr " list_builtin_commands ();\n";
7283 fun (name, _, _, flags, _, shortdesc, _) ->
7284 let name = replace_char name '_' '-' in
7285 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7287 ) all_functions_sorted;
7288 pr " printf (\" %%s\\n\",";
7289 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7293 (* display_command function, which implements guestfish -h cmd *)
7294 pr "void display_command (const char *cmd)\n";
7297 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7298 let name2 = replace_char name '_' '-' in
7300 try find_map (function FishAlias n -> Some n | _ -> None) flags
7301 with Not_found -> name in
7302 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7304 match snd style with
7308 name2 (String.concat " " (List.map name_of_argt args)) in
7311 if List.mem ProtocolLimitWarning flags then
7312 ("\n\n" ^ protocol_limit_warning)
7315 (* For DangerWillRobinson commands, we should probably have
7316 * guestfish prompt before allowing you to use them (especially
7317 * in interactive mode). XXX
7321 if List.mem DangerWillRobinson flags then
7322 ("\n\n" ^ danger_will_robinson)
7327 match deprecation_notice flags with
7329 | Some txt -> "\n\n" ^ txt in
7331 let describe_alias =
7332 if name <> alias then
7333 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7337 pr "STRCASEEQ (cmd, \"%s\")" name;
7338 if name <> name2 then
7339 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7340 if name <> alias then
7341 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7343 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7345 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7346 "=head1 DESCRIPTION\n\n" ^
7347 longdesc ^ warnings ^ describe_alias);
7350 pr " display_builtin_command (cmd);\n";
7354 let emit_print_list_function typ =
7355 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7358 pr " unsigned int i;\n";
7360 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7361 pr " printf (\"[%%d] = {\\n\", i);\n";
7362 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7363 pr " printf (\"}\\n\");\n";
7369 (* print_* functions *)
7373 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7375 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7378 pr " unsigned int i;\n";
7384 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7386 pr " printf (\"%%s%s: \", indent);\n" name;
7387 pr " for (i = 0; i < 32; ++i)\n";
7388 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7389 pr " printf (\"\\n\");\n"
7391 pr " printf (\"%%s%s: \", indent);\n" name;
7392 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7393 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7394 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7396 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7397 pr " printf (\"\\n\");\n"
7398 | name, (FUInt64|FBytes) ->
7399 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7402 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7405 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7408 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7411 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7413 | name, FOptPercent ->
7414 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7415 typ name name typ name;
7416 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7422 (* Emit a print_TYPE_list function definition only if that function is used. *)
7425 | typ, (RStructListOnly | RStructAndList) ->
7426 (* generate the function for typ *)
7427 emit_print_list_function typ
7428 | typ, _ -> () (* empty *)
7429 ) (rstructs_used_by all_functions);
7431 (* Emit a print_TYPE function definition only if that function is used. *)
7434 | typ, (RStructOnly | RStructAndList) ->
7435 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7437 pr " print_%s_indent (%s, \"\");\n" typ typ;
7440 | typ, _ -> () (* empty *)
7441 ) (rstructs_used_by all_functions);
7443 (* run_<action> actions *)
7445 fun (name, style, _, flags, _, _, _) ->
7446 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7448 (match fst style with
7451 | RBool _ -> pr " int r;\n"
7452 | RInt64 _ -> pr " int64_t r;\n"
7453 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7454 | RString _ -> pr " char *r;\n"
7455 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7456 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7457 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7460 pr " size_t size;\n";
7466 | OptString n -> pr " const char *%s;\n" n
7470 | FileOut n -> pr " char *%s;\n" n
7471 | StringList n | DeviceList n -> pr " char **%s;\n" n
7472 | Bool n -> pr " int %s;\n" n
7473 | Int n -> pr " int %s;\n" n
7474 | Int64 n -> pr " int64_t %s;\n" n
7477 (* Check and convert parameters. *)
7478 let argc_expected = List.length (snd style) in
7479 pr " if (argc != %d) {\n" argc_expected;
7480 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7482 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7486 let parse_integer fn fntyp rtyp range name i =
7488 pr " strtol_error xerr;\n";
7489 pr " %s r;\n" fntyp;
7491 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7492 pr " if (xerr != LONGINT_OK) {\n";
7493 pr " fprintf (stderr,\n";
7494 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7495 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7500 | Some (min, max, comment) ->
7501 pr " /* %s */\n" comment;
7502 pr " if (r < %s || r > %s) {\n" min max;
7503 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7507 pr " /* The check above should ensure this assignment does not overflow. */\n";
7509 pr " %s = r;\n" name;
7518 pr " %s = argv[%d];\n" name i
7520 | Dev_or_Path name ->
7521 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7522 pr " if (%s == NULL) return -1;\n" name
7524 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7527 pr " %s = file_in (argv[%d]);\n" name i;
7528 pr " if (%s == NULL) return -1;\n" name
7530 pr " %s = file_out (argv[%d]);\n" name i;
7531 pr " if (%s == NULL) return -1;\n" name
7532 | StringList name | DeviceList name ->
7533 pr " %s = parse_string_list (argv[%d]);\n" name i;
7534 pr " if (%s == NULL) return -1;\n" name;
7536 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7539 let min = "(-(2LL<<30))"
7540 and max = "((2LL<<30)-1)"
7542 "The Int type in the generator is a signed 31 bit int." in
7543 Some (min, max, comment) in
7544 parse_integer "xstrtoll" "long long" "int" range name i
7546 parse_integer "xstrtoll" "long long" "int64_t" None name i
7549 (* Call C API function. *)
7551 try find_map (function FishAction n -> Some n | _ -> None) flags
7552 with Not_found -> sprintf "guestfs_%s" name in
7554 generate_c_call_args ~handle:"g" style;
7559 | Device name | String name
7560 | OptString name | Bool name
7561 | Int name | Int64 name -> ()
7562 | Pathname name | Dev_or_Path name | FileOut name ->
7563 pr " free (%s);\n" name
7565 pr " free_file_in (%s);\n" name
7566 | StringList name | DeviceList name ->
7567 pr " free_strings (%s);\n" name
7570 (* Any output flags? *)
7572 let flags = filter_map (
7573 function FishOutput flag -> Some flag | _ -> None
7579 failwithf "%s: more than one FishOutput flag is not allowed" name in
7581 (* Check return value for errors and display command results. *)
7582 (match fst style with
7583 | RErr -> pr " return r;\n"
7585 pr " if (r == -1) return -1;\n";
7586 (match fish_output with
7588 pr " printf (\"%%d\\n\", r);\n";
7589 | Some FishOutputOctal ->
7590 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7591 | Some FishOutputHexadecimal ->
7592 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7595 pr " if (r == -1) return -1;\n";
7596 (match fish_output with
7598 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7599 | Some FishOutputOctal ->
7600 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7601 | Some FishOutputHexadecimal ->
7602 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7605 pr " if (r == -1) return -1;\n";
7606 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7609 pr " if (r == NULL) return -1;\n";
7610 pr " printf (\"%%s\\n\", r);\n";
7612 | RConstOptString _ ->
7613 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7616 pr " if (r == NULL) return -1;\n";
7617 pr " printf (\"%%s\\n\", r);\n";
7621 pr " if (r == NULL) return -1;\n";
7622 pr " print_strings (r);\n";
7623 pr " free_strings (r);\n";
7625 | RStruct (_, typ) ->
7626 pr " if (r == NULL) return -1;\n";
7627 pr " print_%s (r);\n" typ;
7628 pr " guestfs_free_%s (r);\n" typ;
7630 | RStructList (_, typ) ->
7631 pr " if (r == NULL) return -1;\n";
7632 pr " print_%s_list (r);\n" typ;
7633 pr " guestfs_free_%s_list (r);\n" typ;
7636 pr " if (r == NULL) return -1;\n";
7637 pr " print_table (r);\n";
7638 pr " free_strings (r);\n";
7641 pr " if (r == NULL) return -1;\n";
7642 pr " if (full_write (1, r, size) != size) {\n";
7643 pr " perror (\"write\");\n";
7654 (* run_action function *)
7655 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7658 fun (name, _, _, flags, _, _, _) ->
7659 let name2 = replace_char name '_' '-' in
7661 try find_map (function FishAlias n -> Some n | _ -> None) flags
7662 with Not_found -> name in
7664 pr "STRCASEEQ (cmd, \"%s\")" name;
7665 if name <> name2 then
7666 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7667 if name <> alias then
7668 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7670 pr " return run_%s (cmd, argc, argv);\n" name;
7674 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7675 pr " if (command_num == 1)\n";
7676 pr " extended_help_message ();\n";
7683 (* Readline completion for guestfish. *)
7684 and generate_fish_completion () =
7685 generate_header CStyle GPLv2plus;
7689 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7699 #ifdef HAVE_LIBREADLINE
7700 #include <readline/readline.h>
7705 #ifdef HAVE_LIBREADLINE
7707 static const char *const commands[] = {
7708 BUILTIN_COMMANDS_FOR_COMPLETION,
7711 (* Get the commands, including the aliases. They don't need to be
7712 * sorted - the generator() function just does a dumb linear search.
7716 fun (name, _, _, flags, _, _, _) ->
7717 let name2 = replace_char name '_' '-' in
7719 try find_map (function FishAlias n -> Some n | _ -> None) flags
7720 with Not_found -> name in
7722 if name <> alias then [name2; alias] else [name2]
7724 let commands = List.flatten commands in
7726 List.iter (pr " \"%s\",\n") commands;
7732 generator (const char *text, int state)
7734 static int index, len;
7739 len = strlen (text);
7742 rl_attempted_completion_over = 1;
7744 while ((name = commands[index]) != NULL) {
7746 if (STRCASEEQLEN (name, text, len))
7747 return strdup (name);
7753 #endif /* HAVE_LIBREADLINE */
7755 #ifdef HAVE_RL_COMPLETION_MATCHES
7756 #define RL_COMPLETION_MATCHES rl_completion_matches
7758 #ifdef HAVE_COMPLETION_MATCHES
7759 #define RL_COMPLETION_MATCHES completion_matches
7761 #endif /* else just fail if we don't have either symbol */
7764 do_completion (const char *text, int start, int end)
7766 char **matches = NULL;
7768 #ifdef HAVE_LIBREADLINE
7769 rl_completion_append_character = ' ';
7772 matches = RL_COMPLETION_MATCHES (text, generator);
7773 else if (complete_dest_paths)
7774 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7781 (* Generate the POD documentation for guestfish. *)
7782 and generate_fish_actions_pod () =
7783 let all_functions_sorted =
7785 fun (_, _, _, flags, _, _, _) ->
7786 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7787 ) all_functions_sorted in
7789 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7792 fun (name, style, _, flags, _, _, longdesc) ->
7794 Str.global_substitute rex (
7797 try Str.matched_group 1 s
7799 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7800 "C<" ^ replace_char sub '_' '-' ^ ">"
7802 let name = replace_char name '_' '-' in
7804 try find_map (function FishAlias n -> Some n | _ -> None) flags
7805 with Not_found -> name in
7807 pr "=head2 %s" name;
7808 if name <> alias then
7815 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7816 | OptString n -> pr " %s" n
7817 | StringList n | DeviceList n -> pr " '%s ...'" n
7818 | Bool _ -> pr " true|false"
7819 | Int n -> pr " %s" n
7820 | Int64 n -> pr " %s" n
7821 | FileIn n | FileOut n -> pr " (%s|-)" n
7825 pr "%s\n\n" longdesc;
7827 if List.exists (function FileIn _ | FileOut _ -> true
7828 | _ -> false) (snd style) then
7829 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7831 if List.mem ProtocolLimitWarning flags then
7832 pr "%s\n\n" protocol_limit_warning;
7834 if List.mem DangerWillRobinson flags then
7835 pr "%s\n\n" danger_will_robinson;
7837 match deprecation_notice flags with
7839 | Some txt -> pr "%s\n\n" txt
7840 ) all_functions_sorted
7842 (* Generate a C function prototype. *)
7843 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7844 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7846 ?handle name style =
7847 if extern then pr "extern ";
7848 if static then pr "static ";
7849 (match fst style with
7851 | RInt _ -> pr "int "
7852 | RInt64 _ -> pr "int64_t "
7853 | RBool _ -> pr "int "
7854 | RConstString _ | RConstOptString _ -> pr "const char *"
7855 | RString _ | RBufferOut _ -> pr "char *"
7856 | RStringList _ | RHashtable _ -> pr "char **"
7857 | RStruct (_, typ) ->
7858 if not in_daemon then pr "struct guestfs_%s *" typ
7859 else pr "guestfs_int_%s *" typ
7860 | RStructList (_, typ) ->
7861 if not in_daemon then pr "struct guestfs_%s_list *" typ
7862 else pr "guestfs_int_%s_list *" typ
7864 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7865 pr "%s%s (" prefix name;
7866 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7869 let comma = ref false in
7872 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7876 if single_line then pr ", " else pr ",\n\t\t"
7883 | Device n | Dev_or_Path n
7887 pr "const char *%s" n
7888 | StringList n | DeviceList n ->
7890 pr "char *const *%s" n
7891 | Bool n -> next (); pr "int %s" n
7892 | Int n -> next (); pr "int %s" n
7893 | Int64 n -> next (); pr "int64_t %s" n
7896 if not in_daemon then (next (); pr "const char *%s" n)
7898 if is_RBufferOut then (next (); pr "size_t *size_r");
7901 if semicolon then pr ";";
7902 if newline then pr "\n"
7904 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7905 and generate_c_call_args ?handle ?(decl = false) style =
7907 let comma = ref false in
7909 if !comma then pr ", ";
7914 | Some handle -> pr "%s" handle; comma := true
7919 pr "%s" (name_of_argt arg)
7921 (* For RBufferOut calls, add implicit &size parameter. *)
7923 match fst style with
7931 (* Generate the OCaml bindings interface. *)
7932 and generate_ocaml_mli () =
7933 generate_header OCamlStyle LGPLv2plus;
7936 (** For API documentation you should refer to the C API
7937 in the guestfs(3) manual page. The OCaml API uses almost
7938 exactly the same calls. *)
7941 (** A [guestfs_h] handle. *)
7943 exception Error of string
7944 (** This exception is raised when there is an error. *)
7946 exception Handle_closed of string
7947 (** This exception is raised if you use a {!Guestfs.t} handle
7948 after calling {!close} on it. The string is the name of
7951 val create : unit -> t
7952 (** Create a {!Guestfs.t} handle. *)
7954 val close : t -> unit
7955 (** Close the {!Guestfs.t} handle and free up all resources used
7958 Handles are closed by the garbage collector when they become
7959 unreferenced, but callers can call this in order to provide
7960 predictable cleanup. *)
7963 generate_ocaml_structure_decls ();
7967 fun (name, style, _, _, _, shortdesc, _) ->
7968 generate_ocaml_prototype name style;
7969 pr "(** %s *)\n" shortdesc;
7971 ) all_functions_sorted
7973 (* Generate the OCaml bindings implementation. *)
7974 and generate_ocaml_ml () =
7975 generate_header OCamlStyle LGPLv2plus;
7980 exception Error of string
7981 exception Handle_closed of string
7983 external create : unit -> t = \"ocaml_guestfs_create\"
7984 external close : t -> unit = \"ocaml_guestfs_close\"
7986 (* Give the exceptions names, so they can be raised from the C code. *)
7988 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7989 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7993 generate_ocaml_structure_decls ();
7997 fun (name, style, _, _, _, shortdesc, _) ->
7998 generate_ocaml_prototype ~is_external:true name style;
7999 ) all_functions_sorted
8001 (* Generate the OCaml bindings C implementation. *)
8002 and generate_ocaml_c () =
8003 generate_header CStyle LGPLv2plus;
8010 #include <caml/config.h>
8011 #include <caml/alloc.h>
8012 #include <caml/callback.h>
8013 #include <caml/fail.h>
8014 #include <caml/memory.h>
8015 #include <caml/mlvalues.h>
8016 #include <caml/signals.h>
8018 #include <guestfs.h>
8020 #include \"guestfs_c.h\"
8022 /* Copy a hashtable of string pairs into an assoc-list. We return
8023 * the list in reverse order, but hashtables aren't supposed to be
8026 static CAMLprim value
8027 copy_table (char * const * argv)
8030 CAMLlocal5 (rv, pairv, kv, vv, cons);
8034 for (i = 0; argv[i] != NULL; i += 2) {
8035 kv = caml_copy_string (argv[i]);
8036 vv = caml_copy_string (argv[i+1]);
8037 pairv = caml_alloc (2, 0);
8038 Store_field (pairv, 0, kv);
8039 Store_field (pairv, 1, vv);
8040 cons = caml_alloc (2, 0);
8041 Store_field (cons, 1, rv);
8043 Store_field (cons, 0, pairv);
8051 (* Struct copy functions. *)
8053 let emit_ocaml_copy_list_function typ =
8054 pr "static CAMLprim value\n";
8055 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8057 pr " CAMLparam0 ();\n";
8058 pr " CAMLlocal2 (rv, v);\n";
8059 pr " unsigned int i;\n";
8061 pr " if (%ss->len == 0)\n" typ;
8062 pr " CAMLreturn (Atom (0));\n";
8064 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8065 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8066 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8067 pr " caml_modify (&Field (rv, i), v);\n";
8069 pr " CAMLreturn (rv);\n";
8077 let has_optpercent_col =
8078 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8080 pr "static CAMLprim value\n";
8081 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8083 pr " CAMLparam0 ();\n";
8084 if has_optpercent_col then
8085 pr " CAMLlocal3 (rv, v, v2);\n"
8087 pr " CAMLlocal2 (rv, v);\n";
8089 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8094 pr " v = caml_copy_string (%s->%s);\n" typ name
8096 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8097 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8100 pr " v = caml_alloc_string (32);\n";
8101 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8102 | name, (FBytes|FInt64|FUInt64) ->
8103 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8104 | name, (FInt32|FUInt32) ->
8105 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8106 | name, FOptPercent ->
8107 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8108 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8109 pr " v = caml_alloc (1, 0);\n";
8110 pr " Store_field (v, 0, v2);\n";
8111 pr " } else /* None */\n";
8112 pr " v = Val_int (0);\n";
8114 pr " v = Val_int (%s->%s);\n" typ name
8116 pr " Store_field (rv, %d, v);\n" i
8118 pr " CAMLreturn (rv);\n";
8123 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8126 | typ, (RStructListOnly | RStructAndList) ->
8127 (* generate the function for typ *)
8128 emit_ocaml_copy_list_function typ
8129 | typ, _ -> () (* empty *)
8130 ) (rstructs_used_by all_functions);
8134 fun (name, style, _, _, _, _, _) ->
8135 pr "/* Automatically generated wrapper for function\n";
8137 generate_ocaml_prototype name style;
8142 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8144 let needs_extra_vs =
8145 match fst style with RConstOptString _ -> true | _ -> false in
8147 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8148 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8149 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8152 pr "CAMLprim value\n";
8153 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8154 List.iter (pr ", value %s") (List.tl params);
8159 | [p1; p2; p3; p4; p5] ->
8160 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8161 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8162 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8163 pr " CAMLxparam%d (%s);\n"
8164 (List.length rest) (String.concat ", " rest)
8166 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8168 if not needs_extra_vs then
8169 pr " CAMLlocal1 (rv);\n"
8171 pr " CAMLlocal3 (rv, v, v2);\n";
8174 pr " guestfs_h *g = Guestfs_val (gv);\n";
8175 pr " if (g == NULL)\n";
8176 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8182 | Device n | Dev_or_Path n
8186 pr " const char *%s = String_val (%sv);\n" n n
8188 pr " const char *%s =\n" n;
8189 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8191 | StringList n | DeviceList n ->
8192 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8194 pr " int %s = Bool_val (%sv);\n" n n
8196 pr " int %s = Int_val (%sv);\n" n n
8198 pr " int64_t %s = Int64_val (%sv);\n" n n
8201 match fst style with
8202 | RErr -> pr " int r;\n"; "-1"
8203 | RInt _ -> pr " int r;\n"; "-1"
8204 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8205 | RBool _ -> pr " int r;\n"; "-1"
8206 | RConstString _ | RConstOptString _ ->
8207 pr " const char *r;\n"; "NULL"
8208 | RString _ -> pr " char *r;\n"; "NULL"
8213 | RStruct (_, typ) ->
8214 pr " struct guestfs_%s *r;\n" typ; "NULL"
8215 | RStructList (_, typ) ->
8216 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8223 pr " size_t size;\n";
8227 pr " caml_enter_blocking_section ();\n";
8228 pr " r = guestfs_%s " name;
8229 generate_c_call_args ~handle:"g" style;
8231 pr " caml_leave_blocking_section ();\n";
8235 | StringList n | DeviceList n ->
8236 pr " ocaml_guestfs_free_strings (%s);\n" n;
8237 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8238 | Bool _ | Int _ | Int64 _
8239 | FileIn _ | FileOut _ -> ()
8242 pr " if (r == %s)\n" error_code;
8243 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8246 (match fst style with
8247 | RErr -> pr " rv = Val_unit;\n"
8248 | RInt _ -> pr " rv = Val_int (r);\n"
8250 pr " rv = caml_copy_int64 (r);\n"
8251 | RBool _ -> pr " rv = Val_bool (r);\n"
8253 pr " rv = caml_copy_string (r);\n"
8254 | RConstOptString _ ->
8255 pr " if (r) { /* Some string */\n";
8256 pr " v = caml_alloc (1, 0);\n";
8257 pr " v2 = caml_copy_string (r);\n";
8258 pr " Store_field (v, 0, v2);\n";
8259 pr " } else /* None */\n";
8260 pr " v = Val_int (0);\n";
8262 pr " rv = caml_copy_string (r);\n";
8265 pr " rv = caml_copy_string_array ((const char **) r);\n";
8266 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8268 | RStruct (_, typ) ->
8269 pr " rv = copy_%s (r);\n" typ;
8270 pr " guestfs_free_%s (r);\n" typ;
8271 | RStructList (_, typ) ->
8272 pr " rv = copy_%s_list (r);\n" typ;
8273 pr " guestfs_free_%s_list (r);\n" typ;
8275 pr " rv = copy_table (r);\n";
8276 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8279 pr " rv = caml_alloc_string (size);\n";
8280 pr " memcpy (String_val (rv), r, size);\n";
8283 pr " CAMLreturn (rv);\n";
8287 if List.length params > 5 then (
8288 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8289 pr "CAMLprim value ";
8290 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8291 pr "CAMLprim value\n";
8292 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8294 pr " return ocaml_guestfs_%s (argv[0]" name;
8295 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8300 ) all_functions_sorted
8302 and generate_ocaml_structure_decls () =
8305 pr "type %s = {\n" typ;
8308 | name, FString -> pr " %s : string;\n" name
8309 | name, FBuffer -> pr " %s : string;\n" name
8310 | name, FUUID -> pr " %s : string;\n" name
8311 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8312 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8313 | name, FChar -> pr " %s : char;\n" name
8314 | name, FOptPercent -> pr " %s : float option;\n" name
8320 and generate_ocaml_prototype ?(is_external = false) name style =
8321 if is_external then pr "external " else pr "val ";
8322 pr "%s : t -> " name;
8325 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8326 | OptString _ -> pr "string option -> "
8327 | StringList _ | DeviceList _ -> pr "string array -> "
8328 | Bool _ -> pr "bool -> "
8329 | Int _ -> pr "int -> "
8330 | Int64 _ -> pr "int64 -> "
8332 (match fst style with
8333 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8334 | RInt _ -> pr "int"
8335 | RInt64 _ -> pr "int64"
8336 | RBool _ -> pr "bool"
8337 | RConstString _ -> pr "string"
8338 | RConstOptString _ -> pr "string option"
8339 | RString _ | RBufferOut _ -> pr "string"
8340 | RStringList _ -> pr "string array"
8341 | RStruct (_, typ) -> pr "%s" typ
8342 | RStructList (_, typ) -> pr "%s array" typ
8343 | RHashtable _ -> pr "(string * string) list"
8345 if is_external then (
8347 if List.length (snd style) + 1 > 5 then
8348 pr "\"ocaml_guestfs_%s_byte\" " name;
8349 pr "\"ocaml_guestfs_%s\"" name
8353 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8354 and generate_perl_xs () =
8355 generate_header CStyle LGPLv2plus;
8358 #include \"EXTERN.h\"
8362 #include <guestfs.h>
8365 #define PRId64 \"lld\"
8369 my_newSVll(long long val) {
8370 #ifdef USE_64_BIT_ALL
8371 return newSViv(val);
8375 len = snprintf(buf, 100, \"%%\" PRId64, val);
8376 return newSVpv(buf, len);
8381 #define PRIu64 \"llu\"
8385 my_newSVull(unsigned long long val) {
8386 #ifdef USE_64_BIT_ALL
8387 return newSVuv(val);
8391 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8392 return newSVpv(buf, len);
8396 /* http://www.perlmonks.org/?node_id=680842 */
8398 XS_unpack_charPtrPtr (SV *arg) {
8403 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8404 croak (\"array reference expected\");
8406 av = (AV *)SvRV (arg);
8407 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8409 croak (\"malloc failed\");
8411 for (i = 0; i <= av_len (av); i++) {
8412 SV **elem = av_fetch (av, i, 0);
8414 if (!elem || !*elem)
8415 croak (\"missing element in list\");
8417 ret[i] = SvPV_nolen (*elem);
8425 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8432 RETVAL = guestfs_create ();
8434 croak (\"could not create guestfs handle\");
8435 guestfs_set_error_handler (RETVAL, NULL, NULL);
8448 fun (name, style, _, _, _, _, _) ->
8449 (match fst style with
8450 | RErr -> pr "void\n"
8451 | RInt _ -> pr "SV *\n"
8452 | RInt64 _ -> pr "SV *\n"
8453 | RBool _ -> pr "SV *\n"
8454 | RConstString _ -> pr "SV *\n"
8455 | RConstOptString _ -> pr "SV *\n"
8456 | RString _ -> pr "SV *\n"
8457 | RBufferOut _ -> pr "SV *\n"
8459 | RStruct _ | RStructList _
8461 pr "void\n" (* all lists returned implictly on the stack *)
8463 (* Call and arguments. *)
8465 generate_c_call_args ~handle:"g" ~decl:true style;
8467 pr " guestfs_h *g;\n";
8471 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8474 (* http://www.perlmonks.org/?node_id=554277
8475 * Note that the implicit handle argument means we have
8476 * to add 1 to the ST(x) operator.
8478 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8479 | StringList n | DeviceList n -> pr " char **%s;\n" n
8480 | Bool n -> pr " int %s;\n" n
8481 | Int n -> pr " int %s;\n" n
8482 | Int64 n -> pr " int64_t %s;\n" n
8485 let do_cleanups () =
8488 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8489 | Bool _ | Int _ | Int64 _
8490 | FileIn _ | FileOut _ -> ()
8491 | StringList n | DeviceList n -> pr " free (%s);\n" n
8496 (match fst style with
8501 pr " r = guestfs_%s " name;
8502 generate_c_call_args ~handle:"g" style;
8505 pr " if (r == -1)\n";
8506 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8512 pr " %s = guestfs_%s " n name;
8513 generate_c_call_args ~handle:"g" style;
8516 pr " if (%s == -1)\n" n;
8517 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8518 pr " RETVAL = newSViv (%s);\n" n;
8523 pr " int64_t %s;\n" n;
8525 pr " %s = guestfs_%s " n name;
8526 generate_c_call_args ~handle:"g" style;
8529 pr " if (%s == -1)\n" n;
8530 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8531 pr " RETVAL = my_newSVll (%s);\n" n;
8536 pr " const char *%s;\n" n;
8538 pr " %s = guestfs_%s " n name;
8539 generate_c_call_args ~handle:"g" style;
8542 pr " if (%s == NULL)\n" n;
8543 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8544 pr " RETVAL = newSVpv (%s, 0);\n" n;
8547 | RConstOptString n ->
8549 pr " const char *%s;\n" n;
8551 pr " %s = guestfs_%s " n name;
8552 generate_c_call_args ~handle:"g" style;
8555 pr " if (%s == NULL)\n" n;
8556 pr " RETVAL = &PL_sv_undef;\n";
8558 pr " RETVAL = newSVpv (%s, 0);\n" n;
8563 pr " char *%s;\n" n;
8565 pr " %s = guestfs_%s " n name;
8566 generate_c_call_args ~handle:"g" style;
8569 pr " if (%s == NULL)\n" n;
8570 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8571 pr " RETVAL = newSVpv (%s, 0);\n" n;
8572 pr " free (%s);\n" n;
8575 | RStringList n | RHashtable n ->
8577 pr " char **%s;\n" n;
8580 pr " %s = guestfs_%s " n name;
8581 generate_c_call_args ~handle:"g" style;
8584 pr " if (%s == NULL)\n" n;
8585 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8586 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8587 pr " EXTEND (SP, n);\n";
8588 pr " for (i = 0; i < n; ++i) {\n";
8589 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8590 pr " free (%s[i]);\n" n;
8592 pr " free (%s);\n" n;
8593 | RStruct (n, typ) ->
8594 let cols = cols_of_struct typ in
8595 generate_perl_struct_code typ cols name style n do_cleanups
8596 | RStructList (n, typ) ->
8597 let cols = cols_of_struct typ in
8598 generate_perl_struct_list_code typ cols name style n do_cleanups
8601 pr " char *%s;\n" n;
8602 pr " size_t size;\n";
8604 pr " %s = guestfs_%s " n name;
8605 generate_c_call_args ~handle:"g" style;
8608 pr " if (%s == NULL)\n" n;
8609 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8610 pr " RETVAL = newSVpvn (%s, size);\n" n;
8611 pr " free (%s);\n" n;
8619 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8621 pr " struct guestfs_%s_list *%s;\n" typ n;
8625 pr " %s = guestfs_%s " n name;
8626 generate_c_call_args ~handle:"g" style;
8629 pr " if (%s == NULL)\n" n;
8630 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8631 pr " EXTEND (SP, %s->len);\n" n;
8632 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8633 pr " hv = newHV ();\n";
8637 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8638 name (String.length name) n name
8640 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8641 name (String.length name) n name
8643 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8644 name (String.length name) n name n name
8645 | name, (FBytes|FUInt64) ->
8646 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8647 name (String.length name) n name
8649 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8650 name (String.length name) n name
8651 | name, (FInt32|FUInt32) ->
8652 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8653 name (String.length name) n name
8655 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8656 name (String.length name) n name
8657 | name, FOptPercent ->
8658 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8659 name (String.length name) n name
8661 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8663 pr " guestfs_free_%s_list (%s);\n" typ n
8665 and generate_perl_struct_code typ cols name style n do_cleanups =
8667 pr " struct guestfs_%s *%s;\n" typ n;
8669 pr " %s = guestfs_%s " n name;
8670 generate_c_call_args ~handle:"g" style;
8673 pr " if (%s == NULL)\n" n;
8674 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8675 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8677 fun ((name, _) as col) ->
8678 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8682 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8685 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8688 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8690 | name, (FBytes|FUInt64) ->
8691 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8694 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8696 | name, (FInt32|FUInt32) ->
8697 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8700 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8702 | name, FOptPercent ->
8703 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8706 pr " free (%s);\n" n
8708 (* Generate Sys/Guestfs.pm. *)
8709 and generate_perl_pm () =
8710 generate_header HashStyle LGPLv2plus;
8717 Sys::Guestfs - Perl bindings for libguestfs
8723 my $h = Sys::Guestfs->new ();
8724 $h->add_drive ('guest.img');
8726 $h->mount ('/dev/sda1', '/');
8727 $h->touch ('/hello');
8732 The C<Sys::Guestfs> module provides a Perl XS binding to the
8733 libguestfs API for examining and modifying virtual machine
8736 Amongst the things this is good for: making batch configuration
8737 changes to guests, getting disk used/free statistics (see also:
8738 virt-df), migrating between virtualization systems (see also:
8739 virt-p2v), performing partial backups, performing partial guest
8740 clones, cloning guests and changing registry/UUID/hostname info, and
8743 Libguestfs uses Linux kernel and qemu code, and can access any type of
8744 guest filesystem that Linux and qemu can, including but not limited
8745 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8746 schemes, qcow, qcow2, vmdk.
8748 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8749 LVs, what filesystem is in each LV, etc.). It can also run commands
8750 in the context of the guest. Also you can access filesystems over
8753 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8754 functions for using libguestfs from Perl, including integration
8759 All errors turn into calls to C<croak> (see L<Carp(3)>).
8767 package Sys::Guestfs;
8773 XSLoader::load ('Sys::Guestfs');
8775 =item $h = Sys::Guestfs->new ();
8777 Create a new guestfs handle.
8783 my $class = ref ($proto) || $proto;
8785 my $self = Sys::Guestfs::_create ();
8786 bless $self, $class;
8792 (* Actions. We only need to print documentation for these as
8793 * they are pulled in from the XS code automatically.
8796 fun (name, style, _, flags, _, _, longdesc) ->
8797 if not (List.mem NotInDocs flags) then (
8798 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8800 generate_perl_prototype name style;
8802 pr "%s\n\n" longdesc;
8803 if List.mem ProtocolLimitWarning flags then
8804 pr "%s\n\n" protocol_limit_warning;
8805 if List.mem DangerWillRobinson flags then
8806 pr "%s\n\n" danger_will_robinson;
8807 match deprecation_notice flags with
8809 | Some txt -> pr "%s\n\n" txt
8811 ) all_functions_sorted;
8823 Copyright (C) %s Red Hat Inc.
8827 Please see the file COPYING.LIB for the full license.
8833 L<http://libguestfs.org>,
8834 L<Sys::Guestfs::Lib(3)>.
8839 and generate_perl_prototype name style =
8840 (match fst style with
8848 | RBufferOut n -> pr "$%s = " n
8850 | RHashtable n -> pr "%%%s = " n
8852 | RStructList (n,_) -> pr "@%s = " n
8855 let comma = ref false in
8858 if !comma then pr ", ";
8861 | Pathname n | Device n | Dev_or_Path n | String n
8862 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8864 | StringList n | DeviceList n ->
8869 (* Generate Python C module. *)
8870 and generate_python_c () =
8871 generate_header CStyle LGPLv2plus;
8880 #include \"guestfs.h\"
8888 get_handle (PyObject *obj)
8891 assert (obj != Py_None);
8892 return ((Pyguestfs_Object *) obj)->g;
8896 put_handle (guestfs_h *g)
8900 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8903 /* This list should be freed (but not the strings) after use. */
8905 get_string_list (PyObject *obj)
8912 if (!PyList_Check (obj)) {
8913 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8917 len = PyList_Size (obj);
8918 r = malloc (sizeof (char *) * (len+1));
8920 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8924 for (i = 0; i < len; ++i)
8925 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8932 put_string_list (char * const * const argv)
8937 for (argc = 0; argv[argc] != NULL; ++argc)
8940 list = PyList_New (argc);
8941 for (i = 0; i < argc; ++i)
8942 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8948 put_table (char * const * const argv)
8950 PyObject *list, *item;
8953 for (argc = 0; argv[argc] != NULL; ++argc)
8956 list = PyList_New (argc >> 1);
8957 for (i = 0; i < argc; i += 2) {
8958 item = PyTuple_New (2);
8959 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8960 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8961 PyList_SetItem (list, i >> 1, item);
8968 free_strings (char **argv)
8972 for (argc = 0; argv[argc] != NULL; ++argc)
8978 py_guestfs_create (PyObject *self, PyObject *args)
8982 g = guestfs_create ();
8984 PyErr_SetString (PyExc_RuntimeError,
8985 \"guestfs.create: failed to allocate handle\");
8988 guestfs_set_error_handler (g, NULL, NULL);
8989 return put_handle (g);
8993 py_guestfs_close (PyObject *self, PyObject *args)
8998 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9000 g = get_handle (py_g);
9004 Py_INCREF (Py_None);
9010 let emit_put_list_function typ =
9011 pr "static PyObject *\n";
9012 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9014 pr " PyObject *list;\n";
9017 pr " list = PyList_New (%ss->len);\n" typ;
9018 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9019 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9020 pr " return list;\n";
9025 (* Structures, turned into Python dictionaries. *)
9028 pr "static PyObject *\n";
9029 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9031 pr " PyObject *dict;\n";
9033 pr " dict = PyDict_New ();\n";
9037 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9038 pr " PyString_FromString (%s->%s));\n"
9041 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9042 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9045 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9046 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9048 | name, (FBytes|FUInt64) ->
9049 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9050 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9053 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9054 pr " PyLong_FromLongLong (%s->%s));\n"
9057 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9058 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9061 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9062 pr " PyLong_FromLong (%s->%s));\n"
9064 | name, FOptPercent ->
9065 pr " if (%s->%s >= 0)\n" typ name;
9066 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9067 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9070 pr " Py_INCREF (Py_None);\n";
9071 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9074 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9075 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9077 pr " return dict;\n";
9083 (* Emit a put_TYPE_list function definition only if that function is used. *)
9086 | typ, (RStructListOnly | RStructAndList) ->
9087 (* generate the function for typ *)
9088 emit_put_list_function typ
9089 | typ, _ -> () (* empty *)
9090 ) (rstructs_used_by all_functions);
9092 (* Python wrapper functions. *)
9094 fun (name, style, _, _, _, _, _) ->
9095 pr "static PyObject *\n";
9096 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9099 pr " PyObject *py_g;\n";
9100 pr " guestfs_h *g;\n";
9101 pr " PyObject *py_r;\n";
9104 match fst style with
9105 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9106 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9107 | RConstString _ | RConstOptString _ ->
9108 pr " const char *r;\n"; "NULL"
9109 | RString _ -> pr " char *r;\n"; "NULL"
9110 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9111 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9112 | RStructList (_, typ) ->
9113 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9116 pr " size_t size;\n";
9121 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9122 pr " const char *%s;\n" n
9123 | OptString n -> pr " const char *%s;\n" n
9124 | StringList n | DeviceList n ->
9125 pr " PyObject *py_%s;\n" n;
9126 pr " char **%s;\n" n
9127 | Bool n -> pr " int %s;\n" n
9128 | Int n -> pr " int %s;\n" n
9129 | Int64 n -> pr " long long %s;\n" n
9134 (* Convert the parameters. *)
9135 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9138 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9139 | OptString _ -> pr "z"
9140 | StringList _ | DeviceList _ -> pr "O"
9141 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9143 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9144 * emulate C's int/long/long long in Python?
9147 pr ":guestfs_%s\",\n" name;
9151 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9152 | OptString n -> pr ", &%s" n
9153 | StringList n | DeviceList n -> pr ", &py_%s" n
9154 | Bool n -> pr ", &%s" n
9155 | Int n -> pr ", &%s" n
9156 | Int64 n -> pr ", &%s" n
9160 pr " return NULL;\n";
9162 pr " g = get_handle (py_g);\n";
9165 | Pathname _ | Device _ | Dev_or_Path _ | String _
9166 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9167 | StringList n | DeviceList n ->
9168 pr " %s = get_string_list (py_%s);\n" n n;
9169 pr " if (!%s) return NULL;\n" n
9174 pr " r = guestfs_%s " name;
9175 generate_c_call_args ~handle:"g" style;
9180 | Pathname _ | Device _ | Dev_or_Path _ | String _
9181 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9182 | StringList n | DeviceList n ->
9183 pr " free (%s);\n" n
9186 pr " if (r == %s) {\n" error_code;
9187 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9188 pr " return NULL;\n";
9192 (match fst style with
9194 pr " Py_INCREF (Py_None);\n";
9195 pr " py_r = Py_None;\n"
9197 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9198 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9199 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9200 | RConstOptString _ ->
9202 pr " py_r = PyString_FromString (r);\n";
9204 pr " Py_INCREF (Py_None);\n";
9205 pr " py_r = Py_None;\n";
9208 pr " py_r = PyString_FromString (r);\n";
9211 pr " py_r = put_string_list (r);\n";
9212 pr " free_strings (r);\n"
9213 | RStruct (_, typ) ->
9214 pr " py_r = put_%s (r);\n" typ;
9215 pr " guestfs_free_%s (r);\n" typ
9216 | RStructList (_, typ) ->
9217 pr " py_r = put_%s_list (r);\n" typ;
9218 pr " guestfs_free_%s_list (r);\n" typ
9220 pr " py_r = put_table (r);\n";
9221 pr " free_strings (r);\n"
9223 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9227 pr " return py_r;\n";
9232 (* Table of functions. *)
9233 pr "static PyMethodDef methods[] = {\n";
9234 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9235 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9237 fun (name, _, _, _, _, _, _) ->
9238 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9241 pr " { NULL, NULL, 0, NULL }\n";
9245 (* Init function. *)
9248 initlibguestfsmod (void)
9250 static int initialized = 0;
9252 if (initialized) return;
9253 Py_InitModule ((char *) \"libguestfsmod\", methods);
9258 (* Generate Python module. *)
9259 and generate_python_py () =
9260 generate_header HashStyle LGPLv2plus;
9263 u\"\"\"Python bindings for libguestfs
9266 g = guestfs.GuestFS ()
9267 g.add_drive (\"guest.img\")
9269 parts = g.list_partitions ()
9271 The guestfs module provides a Python binding to the libguestfs API
9272 for examining and modifying virtual machine disk images.
9274 Amongst the things this is good for: making batch configuration
9275 changes to guests, getting disk used/free statistics (see also:
9276 virt-df), migrating between virtualization systems (see also:
9277 virt-p2v), performing partial backups, performing partial guest
9278 clones, cloning guests and changing registry/UUID/hostname info, and
9281 Libguestfs uses Linux kernel and qemu code, and can access any type of
9282 guest filesystem that Linux and qemu can, including but not limited
9283 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9284 schemes, qcow, qcow2, vmdk.
9286 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9287 LVs, what filesystem is in each LV, etc.). It can also run commands
9288 in the context of the guest. Also you can access filesystems over
9291 Errors which happen while using the API are turned into Python
9292 RuntimeError exceptions.
9294 To create a guestfs handle you usually have to perform the following
9297 # Create the handle, call add_drive at least once, and possibly
9298 # several times if the guest has multiple block devices:
9299 g = guestfs.GuestFS ()
9300 g.add_drive (\"guest.img\")
9302 # Launch the qemu subprocess and wait for it to become ready:
9305 # Now you can issue commands, for example:
9310 import libguestfsmod
9313 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9315 def __init__ (self):
9316 \"\"\"Create a new libguestfs handle.\"\"\"
9317 self._o = libguestfsmod.create ()
9320 libguestfsmod.close (self._o)
9325 fun (name, style, _, flags, _, _, longdesc) ->
9327 generate_py_call_args ~handle:"self" (snd style);
9330 if not (List.mem NotInDocs flags) then (
9331 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9333 match fst style with
9334 | RErr | RInt _ | RInt64 _ | RBool _
9335 | RConstOptString _ | RConstString _
9336 | RString _ | RBufferOut _ -> doc
9338 doc ^ "\n\nThis function returns a list of strings."
9339 | RStruct (_, typ) ->
9340 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9341 | RStructList (_, typ) ->
9342 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9344 doc ^ "\n\nThis function returns a dictionary." in
9346 if List.mem ProtocolLimitWarning flags then
9347 doc ^ "\n\n" ^ protocol_limit_warning
9350 if List.mem DangerWillRobinson flags then
9351 doc ^ "\n\n" ^ danger_will_robinson
9354 match deprecation_notice flags with
9356 | Some txt -> doc ^ "\n\n" ^ txt in
9357 let doc = pod2text ~width:60 name doc in
9358 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9359 let doc = String.concat "\n " doc in
9360 pr " u\"\"\"%s\"\"\"\n" doc;
9362 pr " return libguestfsmod.%s " name;
9363 generate_py_call_args ~handle:"self._o" (snd style);
9368 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9369 and generate_py_call_args ~handle args =
9371 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9374 (* Useful if you need the longdesc POD text as plain text. Returns a
9377 * Because this is very slow (the slowest part of autogeneration),
9378 * we memoize the results.
9380 and pod2text ~width name longdesc =
9381 let key = width, name, longdesc in
9382 try Hashtbl.find pod2text_memo key
9384 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9385 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9387 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9388 let chan = open_process_in cmd in
9389 let lines = ref [] in
9391 let line = input_line chan in
9392 if i = 1 then (* discard the first line of output *)
9395 let line = triml line in
9396 lines := line :: !lines;
9399 let lines = try loop 1 with End_of_file -> List.rev !lines in
9401 (match close_process_in chan with
9404 failwithf "pod2text: process exited with non-zero status (%d)" i
9405 | WSIGNALED i | WSTOPPED i ->
9406 failwithf "pod2text: process signalled or stopped by signal %d" i
9408 Hashtbl.add pod2text_memo key lines;
9409 pod2text_memo_updated ();
9412 (* Generate ruby bindings. *)
9413 and generate_ruby_c () =
9414 generate_header CStyle LGPLv2plus;
9422 #include \"guestfs.h\"
9424 #include \"extconf.h\"
9426 /* For Ruby < 1.9 */
9428 #define RARRAY_LEN(r) (RARRAY((r))->len)
9431 static VALUE m_guestfs; /* guestfs module */
9432 static VALUE c_guestfs; /* guestfs_h handle */
9433 static VALUE e_Error; /* used for all errors */
9435 static void ruby_guestfs_free (void *p)
9438 guestfs_close ((guestfs_h *) p);
9441 static VALUE ruby_guestfs_create (VALUE m)
9445 g = guestfs_create ();
9447 rb_raise (e_Error, \"failed to create guestfs handle\");
9449 /* Don't print error messages to stderr by default. */
9450 guestfs_set_error_handler (g, NULL, NULL);
9452 /* Wrap it, and make sure the close function is called when the
9455 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9458 static VALUE ruby_guestfs_close (VALUE gv)
9461 Data_Get_Struct (gv, guestfs_h, g);
9463 ruby_guestfs_free (g);
9464 DATA_PTR (gv) = NULL;
9472 fun (name, style, _, _, _, _, _) ->
9473 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9474 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9477 pr " guestfs_h *g;\n";
9478 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9480 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9486 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9487 pr " Check_Type (%sv, T_STRING);\n" n;
9488 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9490 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9491 pr " \"%s\", \"%s\");\n" n name
9493 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9494 | StringList n | DeviceList n ->
9495 pr " char **%s;\n" n;
9496 pr " Check_Type (%sv, T_ARRAY);\n" n;
9498 pr " int i, len;\n";
9499 pr " len = RARRAY_LEN (%sv);\n" n;
9500 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9502 pr " for (i = 0; i < len; ++i) {\n";
9503 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9504 pr " %s[i] = StringValueCStr (v);\n" n;
9506 pr " %s[len] = NULL;\n" n;
9509 pr " int %s = RTEST (%sv);\n" n n
9511 pr " int %s = NUM2INT (%sv);\n" n n
9513 pr " long long %s = NUM2LL (%sv);\n" n n
9518 match fst style with
9519 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9520 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9521 | RConstString _ | RConstOptString _ ->
9522 pr " const char *r;\n"; "NULL"
9523 | RString _ -> pr " char *r;\n"; "NULL"
9524 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9525 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9526 | RStructList (_, typ) ->
9527 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9530 pr " size_t size;\n";
9534 pr " r = guestfs_%s " name;
9535 generate_c_call_args ~handle:"g" style;
9540 | Pathname _ | Device _ | Dev_or_Path _ | String _
9541 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9542 | StringList n | DeviceList n ->
9543 pr " free (%s);\n" n
9546 pr " if (r == %s)\n" error_code;
9547 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9550 (match fst style with
9552 pr " return Qnil;\n"
9553 | RInt _ | RBool _ ->
9554 pr " return INT2NUM (r);\n"
9556 pr " return ULL2NUM (r);\n"
9558 pr " return rb_str_new2 (r);\n";
9559 | RConstOptString _ ->
9561 pr " return rb_str_new2 (r);\n";
9563 pr " return Qnil;\n";
9565 pr " VALUE rv = rb_str_new2 (r);\n";
9569 pr " int i, len = 0;\n";
9570 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9571 pr " VALUE rv = rb_ary_new2 (len);\n";
9572 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9573 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9574 pr " free (r[i]);\n";
9578 | RStruct (_, typ) ->
9579 let cols = cols_of_struct typ in
9580 generate_ruby_struct_code typ cols
9581 | RStructList (_, typ) ->
9582 let cols = cols_of_struct typ in
9583 generate_ruby_struct_list_code typ cols
9585 pr " VALUE rv = rb_hash_new ();\n";
9587 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9588 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9589 pr " free (r[i]);\n";
9590 pr " free (r[i+1]);\n";
9595 pr " VALUE rv = rb_str_new (r, size);\n";
9605 /* Initialize the module. */
9606 void Init__guestfs ()
9608 m_guestfs = rb_define_module (\"Guestfs\");
9609 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9610 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9612 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9613 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9616 (* Define the rest of the methods. *)
9618 fun (name, style, _, _, _, _, _) ->
9619 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9620 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9625 (* Ruby code to return a struct. *)
9626 and generate_ruby_struct_code typ cols =
9627 pr " VALUE rv = rb_hash_new ();\n";
9631 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9633 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9635 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9636 | name, (FBytes|FUInt64) ->
9637 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9639 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9641 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9643 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9644 | name, FOptPercent ->
9645 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9646 | name, FChar -> (* XXX wrong? *)
9647 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9649 pr " guestfs_free_%s (r);\n" typ;
9652 (* Ruby code to return a struct list. *)
9653 and generate_ruby_struct_list_code typ cols =
9654 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9656 pr " for (i = 0; i < r->len; ++i) {\n";
9657 pr " VALUE hv = rb_hash_new ();\n";
9661 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9663 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
9665 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9666 | name, (FBytes|FUInt64) ->
9667 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9669 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9671 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9673 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9674 | name, FOptPercent ->
9675 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9676 | name, FChar -> (* XXX wrong? *)
9677 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9679 pr " rb_ary_push (rv, hv);\n";
9681 pr " guestfs_free_%s_list (r);\n" typ;
9684 (* Generate Java bindings GuestFS.java file. *)
9685 and generate_java_java () =
9686 generate_header CStyle LGPLv2plus;
9689 package com.redhat.et.libguestfs;
9691 import java.util.HashMap;
9692 import com.redhat.et.libguestfs.LibGuestFSException;
9693 import com.redhat.et.libguestfs.PV;
9694 import com.redhat.et.libguestfs.VG;
9695 import com.redhat.et.libguestfs.LV;
9696 import com.redhat.et.libguestfs.Stat;
9697 import com.redhat.et.libguestfs.StatVFS;
9698 import com.redhat.et.libguestfs.IntBool;
9699 import com.redhat.et.libguestfs.Dirent;
9702 * The GuestFS object is a libguestfs handle.
9706 public class GuestFS {
9707 // Load the native code.
9709 System.loadLibrary (\"guestfs_jni\");
9713 * The native guestfs_h pointer.
9718 * Create a libguestfs handle.
9720 * @throws LibGuestFSException
9722 public GuestFS () throws LibGuestFSException
9726 private native long _create () throws LibGuestFSException;
9729 * Close a libguestfs handle.
9731 * You can also leave handles to be collected by the garbage
9732 * collector, but this method ensures that the resources used
9733 * by the handle are freed up immediately. If you call any
9734 * other methods after closing the handle, you will get an
9737 * @throws LibGuestFSException
9739 public void close () throws LibGuestFSException
9745 private native void _close (long g) throws LibGuestFSException;
9747 public void finalize () throws LibGuestFSException
9755 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9756 if not (List.mem NotInDocs flags); then (
9757 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9759 if List.mem ProtocolLimitWarning flags then
9760 doc ^ "\n\n" ^ protocol_limit_warning
9763 if List.mem DangerWillRobinson flags then
9764 doc ^ "\n\n" ^ danger_will_robinson
9767 match deprecation_notice flags with
9769 | Some txt -> doc ^ "\n\n" ^ txt in
9770 let doc = pod2text ~width:60 name doc in
9771 let doc = List.map ( (* RHBZ#501883 *)
9774 | nonempty -> nonempty
9776 let doc = String.concat "\n * " doc in
9779 pr " * %s\n" shortdesc;
9782 pr " * @throws LibGuestFSException\n";
9786 generate_java_prototype ~public:true ~semicolon:false name style;
9789 pr " if (g == 0)\n";
9790 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9793 if fst style <> RErr then pr "return ";
9795 generate_java_call_args ~handle:"g" (snd style);
9799 generate_java_prototype ~privat:true ~native:true name style;
9806 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9807 and generate_java_call_args ~handle args =
9809 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9812 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9813 ?(semicolon=true) name style =
9814 if privat then pr "private ";
9815 if public then pr "public ";
9816 if native then pr "native ";
9819 (match fst style with
9820 | RErr -> pr "void ";
9821 | RInt _ -> pr "int ";
9822 | RInt64 _ -> pr "long ";
9823 | RBool _ -> pr "boolean ";
9824 | RConstString _ | RConstOptString _ | RString _
9825 | RBufferOut _ -> pr "String ";
9826 | RStringList _ -> pr "String[] ";
9827 | RStruct (_, typ) ->
9828 let name = java_name_of_struct typ in
9830 | RStructList (_, typ) ->
9831 let name = java_name_of_struct typ in
9833 | RHashtable _ -> pr "HashMap<String,String> ";
9836 if native then pr "_%s " name else pr "%s " name;
9838 let needs_comma = ref false in
9847 if !needs_comma then pr ", ";
9848 needs_comma := true;
9852 | Device n | Dev_or_Path n
9858 | StringList n | DeviceList n ->
9869 pr " throws LibGuestFSException";
9870 if semicolon then pr ";"
9872 and generate_java_struct jtyp cols () =
9873 generate_header CStyle LGPLv2plus;
9876 package com.redhat.et.libguestfs;
9879 * Libguestfs %s structure.
9891 | name, FBuffer -> pr " public String %s;\n" name
9892 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9893 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9894 | name, FChar -> pr " public char %s;\n" name
9895 | name, FOptPercent ->
9896 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9897 pr " public float %s;\n" name
9902 and generate_java_c () =
9903 generate_header CStyle LGPLv2plus;
9910 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9911 #include \"guestfs.h\"
9913 /* Note that this function returns. The exception is not thrown
9914 * until after the wrapper function returns.
9917 throw_exception (JNIEnv *env, const char *msg)
9920 cl = (*env)->FindClass (env,
9921 \"com/redhat/et/libguestfs/LibGuestFSException\");
9922 (*env)->ThrowNew (env, cl, msg);
9925 JNIEXPORT jlong JNICALL
9926 Java_com_redhat_et_libguestfs_GuestFS__1create
9927 (JNIEnv *env, jobject obj)
9931 g = guestfs_create ();
9933 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9936 guestfs_set_error_handler (g, NULL, NULL);
9937 return (jlong) (long) g;
9940 JNIEXPORT void JNICALL
9941 Java_com_redhat_et_libguestfs_GuestFS__1close
9942 (JNIEnv *env, jobject obj, jlong jg)
9944 guestfs_h *g = (guestfs_h *) (long) jg;
9951 fun (name, style, _, _, _, _, _) ->
9953 (match fst style with
9954 | RErr -> pr "void ";
9955 | RInt _ -> pr "jint ";
9956 | RInt64 _ -> pr "jlong ";
9957 | RBool _ -> pr "jboolean ";
9958 | RConstString _ | RConstOptString _ | RString _
9959 | RBufferOut _ -> pr "jstring ";
9960 | RStruct _ | RHashtable _ ->
9962 | RStringList _ | RStructList _ ->
9966 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9967 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9969 pr " (JNIEnv *env, jobject obj, jlong jg";
9973 | Device n | Dev_or_Path n
9978 pr ", jstring j%s" n
9979 | StringList n | DeviceList n ->
9980 pr ", jobjectArray j%s" n
9982 pr ", jboolean j%s" n
9990 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9991 let error_code, no_ret =
9992 match fst style with
9993 | RErr -> pr " int r;\n"; "-1", ""
9995 | RInt _ -> pr " int r;\n"; "-1", "0"
9996 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9997 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9998 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10000 pr " jstring jr;\n";
10001 pr " char *r;\n"; "NULL", "NULL"
10003 pr " jobjectArray jr;\n";
10004 pr " int r_len;\n";
10005 pr " jclass cl;\n";
10006 pr " jstring jstr;\n";
10007 pr " char **r;\n"; "NULL", "NULL"
10008 | RStruct (_, typ) ->
10009 pr " jobject jr;\n";
10010 pr " jclass cl;\n";
10011 pr " jfieldID fl;\n";
10012 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10013 | RStructList (_, typ) ->
10014 pr " jobjectArray jr;\n";
10015 pr " jclass cl;\n";
10016 pr " jfieldID fl;\n";
10017 pr " jobject jfl;\n";
10018 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10019 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10021 pr " jstring jr;\n";
10023 pr " size_t size;\n";
10028 | Device n | Dev_or_Path n
10033 pr " const char *%s;\n" n
10034 | StringList n | DeviceList n ->
10035 pr " int %s_len;\n" n;
10036 pr " const char **%s;\n" n
10041 pr " int64_t %s;\n" n
10045 (match fst style with
10046 | RStringList _ | RStructList _ -> true
10047 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10048 | RConstOptString _
10049 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10050 List.exists (function
10051 | StringList _ -> true
10052 | DeviceList _ -> true
10053 | _ -> false) (snd style) in
10059 (* Get the parameters. *)
10063 | Device n | Dev_or_Path n
10067 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10069 (* This is completely undocumented, but Java null becomes
10070 * a NULL parameter.
10072 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10073 | StringList n | DeviceList n ->
10074 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10075 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10076 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10077 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10079 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10081 pr " %s[%s_len] = NULL;\n" n n;
10085 pr " %s = j%s;\n" n n
10088 (* Make the call. *)
10089 pr " r = guestfs_%s " name;
10090 generate_c_call_args ~handle:"g" style;
10093 (* Release the parameters. *)
10097 | Device n | Dev_or_Path n
10101 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10103 pr " if (j%s)\n" n;
10104 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10105 | StringList n | DeviceList n ->
10106 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10107 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10109 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10111 pr " free (%s);\n" n
10117 (* Check for errors. *)
10118 pr " if (r == %s) {\n" error_code;
10119 pr " throw_exception (env, guestfs_last_error (g));\n";
10120 pr " return %s;\n" no_ret;
10123 (* Return value. *)
10124 (match fst style with
10126 | RInt _ -> pr " return (jint) r;\n"
10127 | RBool _ -> pr " return (jboolean) r;\n"
10128 | RInt64 _ -> pr " return (jlong) r;\n"
10129 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10130 | RConstOptString _ ->
10131 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10133 pr " jr = (*env)->NewStringUTF (env, r);\n";
10137 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10138 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10139 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10140 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10141 pr " for (i = 0; i < r_len; ++i) {\n";
10142 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10143 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10144 pr " free (r[i]);\n";
10148 | RStruct (_, typ) ->
10149 let jtyp = java_name_of_struct typ in
10150 let cols = cols_of_struct typ in
10151 generate_java_struct_return typ jtyp cols
10152 | RStructList (_, typ) ->
10153 let jtyp = java_name_of_struct typ in
10154 let cols = cols_of_struct typ in
10155 generate_java_struct_list_return typ jtyp cols
10158 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10159 pr " return NULL;\n"
10161 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10170 and generate_java_struct_return typ jtyp cols =
10171 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10172 pr " jr = (*env)->AllocObject (env, cl);\n";
10176 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10177 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10180 pr " char s[33];\n";
10181 pr " memcpy (s, r->%s, 32);\n" name;
10182 pr " s[32] = 0;\n";
10183 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10184 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10188 pr " int len = r->%s_len;\n" name;
10189 pr " char s[len+1];\n";
10190 pr " memcpy (s, r->%s, len);\n" name;
10191 pr " s[len] = 0;\n";
10192 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10193 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10195 | name, (FBytes|FUInt64|FInt64) ->
10196 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10197 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10198 | name, (FUInt32|FInt32) ->
10199 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10200 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10201 | name, FOptPercent ->
10202 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10203 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10205 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10206 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10211 and generate_java_struct_list_return typ jtyp cols =
10212 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10213 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10214 pr " for (i = 0; i < r->len; ++i) {\n";
10215 pr " jfl = (*env)->AllocObject (env, cl);\n";
10219 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10220 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10223 pr " char s[33];\n";
10224 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10225 pr " s[32] = 0;\n";
10226 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10227 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10231 pr " int len = r->val[i].%s_len;\n" name;
10232 pr " char s[len+1];\n";
10233 pr " memcpy (s, r->val[i].%s, len);\n" name;
10234 pr " s[len] = 0;\n";
10235 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10236 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10238 | name, (FBytes|FUInt64|FInt64) ->
10239 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10240 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10241 | name, (FUInt32|FInt32) ->
10242 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10243 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10244 | name, FOptPercent ->
10245 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10246 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10248 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10249 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10251 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10253 pr " guestfs_free_%s_list (r);\n" typ;
10256 and generate_java_makefile_inc () =
10257 generate_header HashStyle GPLv2plus;
10259 pr "java_built_sources = \\\n";
10262 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10264 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10266 and generate_haskell_hs () =
10267 generate_header HaskellStyle LGPLv2plus;
10269 (* XXX We only know how to generate partial FFI for Haskell
10270 * at the moment. Please help out!
10272 let can_generate style =
10276 | RInt64 _, _ -> true
10278 | RConstString _, _
10279 | RConstOptString _, _
10285 | RBufferOut _, _ -> false in
10288 {-# INCLUDE <guestfs.h> #-}
10289 {-# LANGUAGE ForeignFunctionInterface #-}
10294 (* List out the names of the actions we want to export. *)
10296 fun (name, style, _, _, _, _, _) ->
10297 if can_generate style then pr ",\n %s" name
10303 -- Unfortunately some symbols duplicate ones already present
10304 -- in Prelude. We don't know which, so we hard-code a list
10306 import Prelude hiding (truncate)
10310 import Foreign.C.Types
10312 import Control.Exception
10313 import Data.Typeable
10315 data GuestfsS = GuestfsS -- represents the opaque C struct
10316 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10317 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10319 -- XXX define properly later XXX
10323 data IntBool = IntBool
10325 data StatVFS = StatVFS
10326 data Hashtable = Hashtable
10328 foreign import ccall unsafe \"guestfs_create\" c_create
10330 foreign import ccall unsafe \"&guestfs_close\" c_close
10331 :: FunPtr (GuestfsP -> IO ())
10332 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10333 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10335 create :: IO GuestfsH
10338 c_set_error_handler p nullPtr nullPtr
10339 h <- newForeignPtr c_close p
10342 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10343 :: GuestfsP -> IO CString
10345 -- last_error :: GuestfsH -> IO (Maybe String)
10346 -- last_error h = do
10347 -- str <- withForeignPtr h (\\p -> c_last_error p)
10348 -- maybePeek peekCString str
10350 last_error :: GuestfsH -> IO (String)
10352 str <- withForeignPtr h (\\p -> c_last_error p)
10353 if (str == nullPtr)
10354 then return \"no error\"
10355 else peekCString str
10359 (* Generate wrappers for each foreign function. *)
10361 fun (name, style, _, _, _, _, _) ->
10362 if can_generate style then (
10363 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10365 generate_haskell_prototype ~handle:"GuestfsP" style;
10369 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10371 pr "%s %s = do\n" name
10372 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10374 (* Convert pointer arguments using with* functions. *)
10379 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10380 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10381 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10382 | Bool _ | Int _ | Int64 _ -> ()
10384 (* Convert integer arguments. *)
10388 | Bool n -> sprintf "(fromBool %s)" n
10389 | Int n -> sprintf "(fromIntegral %s)" n
10390 | Int64 n -> sprintf "(fromIntegral %s)" n
10391 | FileIn n | FileOut n
10392 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10394 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10395 (String.concat " " ("p" :: args));
10396 (match fst style with
10397 | RErr | RInt _ | RInt64 _ | RBool _ ->
10398 pr " if (r == -1)\n";
10400 pr " err <- last_error h\n";
10402 | RConstString _ | RConstOptString _ | RString _
10403 | RStringList _ | RStruct _
10404 | RStructList _ | RHashtable _ | RBufferOut _ ->
10405 pr " if (r == nullPtr)\n";
10407 pr " err <- last_error h\n";
10410 (match fst style with
10412 pr " else return ()\n"
10414 pr " else return (fromIntegral r)\n"
10416 pr " else return (fromIntegral r)\n"
10418 pr " else return (toBool r)\n"
10420 | RConstOptString _
10427 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10433 and generate_haskell_prototype ~handle ?(hs = false) style =
10434 pr "%s -> " handle;
10435 let string = if hs then "String" else "CString" in
10436 let int = if hs then "Int" else "CInt" in
10437 let bool = if hs then "Bool" else "CInt" in
10438 let int64 = if hs then "Integer" else "Int64" in
10442 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10443 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10444 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10445 | Bool _ -> pr "%s" bool
10446 | Int _ -> pr "%s" int
10447 | Int64 _ -> pr "%s" int
10448 | FileIn _ -> pr "%s" string
10449 | FileOut _ -> pr "%s" string
10454 (match fst style with
10455 | RErr -> if not hs then pr "CInt"
10456 | RInt _ -> pr "%s" int
10457 | RInt64 _ -> pr "%s" int64
10458 | RBool _ -> pr "%s" bool
10459 | RConstString _ -> pr "%s" string
10460 | RConstOptString _ -> pr "Maybe %s" string
10461 | RString _ -> pr "%s" string
10462 | RStringList _ -> pr "[%s]" string
10463 | RStruct (_, typ) ->
10464 let name = java_name_of_struct typ in
10466 | RStructList (_, typ) ->
10467 let name = java_name_of_struct typ in
10469 | RHashtable _ -> pr "Hashtable"
10470 | RBufferOut _ -> pr "%s" string
10474 and generate_csharp () =
10475 generate_header CPlusPlusStyle LGPLv2plus;
10477 (* XXX Make this configurable by the C# assembly users. *)
10478 let library = "libguestfs.so.0" in
10481 // These C# bindings are highly experimental at present.
10483 // Firstly they only work on Linux (ie. Mono). In order to get them
10484 // to work on Windows (ie. .Net) you would need to port the library
10485 // itself to Windows first.
10487 // The second issue is that some calls are known to be incorrect and
10488 // can cause Mono to segfault. Particularly: calls which pass or
10489 // return string[], or return any structure value. This is because
10490 // we haven't worked out the correct way to do this from C#.
10492 // The third issue is that when compiling you get a lot of warnings.
10493 // We are not sure whether the warnings are important or not.
10495 // Fourthly we do not routinely build or test these bindings as part
10496 // of the make && make check cycle, which means that regressions might
10499 // Suggestions and patches are welcome.
10503 // gmcs Libguestfs.cs
10504 // mono Libguestfs.exe
10506 // (You'll probably want to add a Test class / static main function
10507 // otherwise this won't do anything useful).
10511 using System.Runtime.InteropServices;
10512 using System.Runtime.Serialization;
10513 using System.Collections;
10517 class Error : System.ApplicationException
10519 public Error (string message) : base (message) {}
10520 protected Error (SerializationInfo info, StreamingContext context) {}
10527 [DllImport (\"%s\")]
10528 static extern IntPtr guestfs_create ();
10532 _handle = guestfs_create ();
10533 if (_handle == IntPtr.Zero)
10534 throw new Error (\"could not create guestfs handle\");
10537 [DllImport (\"%s\")]
10538 static extern void guestfs_close (IntPtr h);
10542 guestfs_close (_handle);
10545 [DllImport (\"%s\")]
10546 static extern string guestfs_last_error (IntPtr h);
10548 " library library library;
10550 (* Generate C# structure bindings. We prefix struct names with
10551 * underscore because C# cannot have conflicting struct names and
10552 * method names (eg. "class stat" and "stat").
10556 pr " [StructLayout (LayoutKind.Sequential)]\n";
10557 pr " public class _%s {\n" typ;
10560 | name, FChar -> pr " char %s;\n" name
10561 | name, FString -> pr " string %s;\n" name
10563 pr " uint %s_len;\n" name;
10564 pr " string %s;\n" name
10566 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10567 pr " string %s;\n" name
10568 | name, FUInt32 -> pr " uint %s;\n" name
10569 | name, FInt32 -> pr " int %s;\n" name
10570 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10571 | name, FInt64 -> pr " long %s;\n" name
10572 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10578 (* Generate C# function bindings. *)
10580 fun (name, style, _, _, _, shortdesc, _) ->
10581 let rec csharp_return_type () =
10582 match fst style with
10584 | RBool n -> "bool"
10586 | RInt64 n -> "long"
10588 | RConstOptString n
10590 | RBufferOut n -> "string"
10591 | RStruct (_,n) -> "_" ^ n
10592 | RHashtable n -> "Hashtable"
10593 | RStringList n -> "string[]"
10594 | RStructList (_,n) -> sprintf "_%s[]" n
10596 and c_return_type () =
10597 match fst style with
10601 | RInt64 _ -> "long"
10603 | RConstOptString _
10605 | RBufferOut _ -> "string"
10606 | RStruct (_,n) -> "_" ^ n
10608 | RStringList _ -> "string[]"
10609 | RStructList (_,n) -> sprintf "_%s[]" n
10611 and c_error_comparison () =
10612 match fst style with
10616 | RInt64 _ -> "== -1"
10618 | RConstOptString _
10624 | RStructList (_,_) -> "== null"
10626 and generate_extern_prototype () =
10627 pr " static extern %s guestfs_%s (IntPtr h"
10628 (c_return_type ()) name;
10631 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10632 | FileIn n | FileOut n ->
10633 pr ", [In] string %s" n
10634 | StringList n | DeviceList n ->
10635 pr ", [In] string[] %s" n
10645 and generate_public_prototype () =
10646 pr " public %s %s (" (csharp_return_type ()) name;
10647 let comma = ref false in
10649 if !comma then pr ", ";
10654 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10655 | FileIn n | FileOut n ->
10656 next (); pr "string %s" n
10657 | StringList n | DeviceList n ->
10658 next (); pr "string[] %s" n
10660 next (); pr "bool %s" n
10662 next (); pr "int %s" n
10664 next (); pr "long %s" n
10668 and generate_call () =
10669 pr "guestfs_%s (_handle" name;
10670 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10674 pr " [DllImport (\"%s\")]\n" library;
10675 generate_extern_prototype ();
10677 pr " /// <summary>\n";
10678 pr " /// %s\n" shortdesc;
10679 pr " /// </summary>\n";
10680 generate_public_prototype ();
10682 pr " %s r;\n" (c_return_type ());
10685 pr " if (r %s)\n" (c_error_comparison ());
10686 pr " throw new Error (guestfs_last_error (_handle));\n";
10687 (match fst style with
10690 pr " return r != 0 ? true : false;\n"
10692 pr " Hashtable rr = new Hashtable ();\n";
10693 pr " for (int i = 0; i < r.Length; i += 2)\n";
10694 pr " rr.Add (r[i], r[i+1]);\n";
10696 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10697 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10703 ) all_functions_sorted;
10709 and generate_bindtests () =
10710 generate_header CStyle LGPLv2plus;
10714 #include <stdlib.h>
10715 #include <inttypes.h>
10716 #include <string.h>
10718 #include \"guestfs.h\"
10719 #include \"guestfs-internal.h\"
10720 #include \"guestfs-internal-actions.h\"
10721 #include \"guestfs_protocol.h\"
10723 #define error guestfs_error
10724 #define safe_calloc guestfs_safe_calloc
10725 #define safe_malloc guestfs_safe_malloc
10728 print_strings (char *const *argv)
10733 for (argc = 0; argv[argc] != NULL; ++argc) {
10734 if (argc > 0) printf (\", \");
10735 printf (\"\\\"%%s\\\"\", argv[argc]);
10740 /* The test0 function prints its parameters to stdout. */
10744 match test_functions with
10745 | [] -> assert false
10746 | test0 :: tests -> test0, tests in
10749 let (name, style, _, _, _, _, _) = test0 in
10750 generate_prototype ~extern:false ~semicolon:false ~newline:true
10751 ~handle:"g" ~prefix:"guestfs__" name style;
10756 | Device n | Dev_or_Path n
10759 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10760 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10761 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10762 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10763 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10764 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10766 pr " /* Java changes stdout line buffering so we need this: */\n";
10767 pr " fflush (stdout);\n";
10773 fun (name, style, _, _, _, _, _) ->
10774 if String.sub name (String.length name - 3) 3 <> "err" then (
10775 pr "/* Test normal return. */\n";
10776 generate_prototype ~extern:false ~semicolon:false ~newline:true
10777 ~handle:"g" ~prefix:"guestfs__" name style;
10779 (match fst style with
10784 pr " sscanf (val, \"%%d\", &r);\n";
10787 pr " int64_t r;\n";
10788 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10791 pr " return STREQ (val, \"true\");\n"
10793 | RConstOptString _ ->
10794 (* Can't return the input string here. Return a static
10795 * string so we ensure we get a segfault if the caller
10796 * tries to free it.
10798 pr " return \"static string\";\n"
10800 pr " return strdup (val);\n"
10802 pr " char **strs;\n";
10804 pr " sscanf (val, \"%%d\", &n);\n";
10805 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10806 pr " for (i = 0; i < n; ++i) {\n";
10807 pr " strs[i] = safe_malloc (g, 16);\n";
10808 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10810 pr " strs[n] = NULL;\n";
10811 pr " return strs;\n"
10812 | RStruct (_, typ) ->
10813 pr " struct guestfs_%s *r;\n" typ;
10814 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10816 | RStructList (_, typ) ->
10817 pr " struct guestfs_%s_list *r;\n" typ;
10818 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10819 pr " sscanf (val, \"%%d\", &r->len);\n";
10820 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10823 pr " char **strs;\n";
10825 pr " sscanf (val, \"%%d\", &n);\n";
10826 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10827 pr " for (i = 0; i < n; ++i) {\n";
10828 pr " strs[i*2] = safe_malloc (g, 16);\n";
10829 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10830 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10831 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10833 pr " strs[n*2] = NULL;\n";
10834 pr " return strs;\n"
10836 pr " return strdup (val);\n"
10841 pr "/* Test error return. */\n";
10842 generate_prototype ~extern:false ~semicolon:false ~newline:true
10843 ~handle:"g" ~prefix:"guestfs__" name style;
10845 pr " error (g, \"error\");\n";
10846 (match fst style with
10847 | RErr | RInt _ | RInt64 _ | RBool _ ->
10849 | RConstString _ | RConstOptString _
10850 | RString _ | RStringList _ | RStruct _
10854 pr " return NULL;\n"
10861 and generate_ocaml_bindtests () =
10862 generate_header OCamlStyle GPLv2plus;
10866 let g = Guestfs.create () in
10870 String.concat " " (
10873 | CallString s -> "\"" ^ s ^ "\""
10874 | CallOptString None -> "None"
10875 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10876 | CallStringList xs ->
10877 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10878 | CallInt i when i >= 0 -> string_of_int i
10879 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10880 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10881 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10882 | CallBool b -> string_of_bool b
10887 generate_lang_bindtests (
10888 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10891 pr "print_endline \"EOF\"\n"
10893 and generate_perl_bindtests () =
10894 pr "#!/usr/bin/perl -w\n";
10895 generate_header HashStyle GPLv2plus;
10902 my $g = Sys::Guestfs->new ();
10906 String.concat ", " (
10909 | CallString s -> "\"" ^ s ^ "\""
10910 | CallOptString None -> "undef"
10911 | CallOptString (Some s) -> sprintf "\"%s\"" s
10912 | CallStringList xs ->
10913 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10914 | CallInt i -> string_of_int i
10915 | CallInt64 i -> Int64.to_string i
10916 | CallBool b -> if b then "1" else "0"
10921 generate_lang_bindtests (
10922 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10925 pr "print \"EOF\\n\"\n"
10927 and generate_python_bindtests () =
10928 generate_header HashStyle GPLv2plus;
10933 g = guestfs.GuestFS ()
10937 String.concat ", " (
10940 | CallString s -> "\"" ^ s ^ "\""
10941 | CallOptString None -> "None"
10942 | CallOptString (Some s) -> sprintf "\"%s\"" s
10943 | CallStringList xs ->
10944 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10945 | CallInt i -> string_of_int i
10946 | CallInt64 i -> Int64.to_string i
10947 | CallBool b -> if b then "1" else "0"
10952 generate_lang_bindtests (
10953 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10956 pr "print \"EOF\"\n"
10958 and generate_ruby_bindtests () =
10959 generate_header HashStyle GPLv2plus;
10964 g = Guestfs::create()
10968 String.concat ", " (
10971 | CallString s -> "\"" ^ s ^ "\""
10972 | CallOptString None -> "nil"
10973 | CallOptString (Some s) -> sprintf "\"%s\"" s
10974 | CallStringList xs ->
10975 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10976 | CallInt i -> string_of_int i
10977 | CallInt64 i -> Int64.to_string i
10978 | CallBool b -> string_of_bool b
10983 generate_lang_bindtests (
10984 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10987 pr "print \"EOF\\n\"\n"
10989 and generate_java_bindtests () =
10990 generate_header CStyle GPLv2plus;
10993 import com.redhat.et.libguestfs.*;
10995 public class Bindtests {
10996 public static void main (String[] argv)
10999 GuestFS g = new GuestFS ();
11003 String.concat ", " (
11006 | CallString s -> "\"" ^ s ^ "\""
11007 | CallOptString None -> "null"
11008 | CallOptString (Some s) -> sprintf "\"%s\"" s
11009 | CallStringList xs ->
11011 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11012 | CallInt i -> string_of_int i
11013 | CallInt64 i -> Int64.to_string i
11014 | CallBool b -> string_of_bool b
11019 generate_lang_bindtests (
11020 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11024 System.out.println (\"EOF\");
11026 catch (Exception exn) {
11027 System.err.println (exn);
11034 and generate_haskell_bindtests () =
11035 generate_header HaskellStyle GPLv2plus;
11038 module Bindtests where
11039 import qualified Guestfs
11042 g <- Guestfs.create
11046 String.concat " " (
11049 | CallString s -> "\"" ^ s ^ "\""
11050 | CallOptString None -> "Nothing"
11051 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11052 | CallStringList xs ->
11053 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11054 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11055 | CallInt i -> string_of_int i
11056 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11057 | CallInt64 i -> Int64.to_string i
11058 | CallBool true -> "True"
11059 | CallBool false -> "False"
11064 generate_lang_bindtests (
11065 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11068 pr " putStrLn \"EOF\"\n"
11070 (* Language-independent bindings tests - we do it this way to
11071 * ensure there is parity in testing bindings across all languages.
11073 and generate_lang_bindtests call =
11074 call "test0" [CallString "abc"; CallOptString (Some "def");
11075 CallStringList []; CallBool false;
11076 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11077 call "test0" [CallString "abc"; CallOptString None;
11078 CallStringList []; CallBool false;
11079 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11080 call "test0" [CallString ""; CallOptString (Some "def");
11081 CallStringList []; CallBool false;
11082 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083 call "test0" [CallString ""; CallOptString (Some "");
11084 CallStringList []; CallBool false;
11085 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086 call "test0" [CallString "abc"; CallOptString (Some "def");
11087 CallStringList ["1"]; CallBool false;
11088 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089 call "test0" [CallString "abc"; CallOptString (Some "def");
11090 CallStringList ["1"; "2"]; CallBool false;
11091 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092 call "test0" [CallString "abc"; CallOptString (Some "def");
11093 CallStringList ["1"]; CallBool true;
11094 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095 call "test0" [CallString "abc"; CallOptString (Some "def");
11096 CallStringList ["1"]; CallBool false;
11097 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11098 call "test0" [CallString "abc"; CallOptString (Some "def");
11099 CallStringList ["1"]; CallBool false;
11100 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11101 call "test0" [CallString "abc"; CallOptString (Some "def");
11102 CallStringList ["1"]; CallBool false;
11103 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11104 call "test0" [CallString "abc"; CallOptString (Some "def");
11105 CallStringList ["1"]; CallBool false;
11106 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11107 call "test0" [CallString "abc"; CallOptString (Some "def");
11108 CallStringList ["1"]; CallBool false;
11109 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11110 call "test0" [CallString "abc"; CallOptString (Some "def");
11111 CallStringList ["1"]; CallBool false;
11112 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11114 (* XXX Add here tests of the return and error functions. *)
11116 (* Code to generator bindings for virt-inspector. Currently only
11117 * implemented for OCaml code (for virt-p2v 2.0).
11119 let rng_input = "inspector/virt-inspector.rng"
11121 (* Read the input file and parse it into internal structures. This is
11122 * by no means a complete RELAX NG parser, but is just enough to be
11123 * able to parse the specific input file.
11126 | Element of string * rng list (* <element name=name/> *)
11127 | Attribute of string * rng list (* <attribute name=name/> *)
11128 | Interleave of rng list (* <interleave/> *)
11129 | ZeroOrMore of rng (* <zeroOrMore/> *)
11130 | OneOrMore of rng (* <oneOrMore/> *)
11131 | Optional of rng (* <optional/> *)
11132 | Choice of string list (* <choice><value/>*</choice> *)
11133 | Value of string (* <value>str</value> *)
11134 | Text (* <text/> *)
11136 let rec string_of_rng = function
11137 | Element (name, xs) ->
11138 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11139 | Attribute (name, xs) ->
11140 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11141 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11142 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11143 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11144 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11145 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11146 | Value value -> "Value \"" ^ value ^ "\""
11149 and string_of_rng_list xs =
11150 String.concat ", " (List.map string_of_rng xs)
11152 let rec parse_rng ?defines context = function
11154 | Xml.Element ("element", ["name", name], children) :: rest ->
11155 Element (name, parse_rng ?defines context children)
11156 :: parse_rng ?defines context rest
11157 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11158 Attribute (name, parse_rng ?defines context children)
11159 :: parse_rng ?defines context rest
11160 | Xml.Element ("interleave", [], children) :: rest ->
11161 Interleave (parse_rng ?defines context children)
11162 :: parse_rng ?defines context rest
11163 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11164 let rng = parse_rng ?defines context [child] in
11166 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11168 failwithf "%s: <zeroOrMore> contains more than one child element"
11171 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11172 let rng = parse_rng ?defines context [child] in
11174 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11176 failwithf "%s: <oneOrMore> contains more than one child element"
11179 | Xml.Element ("optional", [], [child]) :: rest ->
11180 let rng = parse_rng ?defines context [child] in
11182 | [child] -> Optional child :: parse_rng ?defines context rest
11184 failwithf "%s: <optional> contains more than one child element"
11187 | Xml.Element ("choice", [], children) :: rest ->
11188 let values = List.map (
11189 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11191 failwithf "%s: can't handle anything except <value> in <choice>"
11195 :: parse_rng ?defines context rest
11196 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11197 Value value :: parse_rng ?defines context rest
11198 | Xml.Element ("text", [], []) :: rest ->
11199 Text :: parse_rng ?defines context rest
11200 | Xml.Element ("ref", ["name", name], []) :: rest ->
11201 (* Look up the reference. Because of limitations in this parser,
11202 * we can't handle arbitrarily nested <ref> yet. You can only
11203 * use <ref> from inside <start>.
11205 (match defines with
11207 failwithf "%s: contains <ref>, but no refs are defined yet" context
11209 let rng = StringMap.find name map in
11210 rng @ parse_rng ?defines context rest
11213 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11216 let xml = Xml.parse_file rng_input in
11218 | Xml.Element ("grammar", _,
11219 Xml.Element ("start", _, gram) :: defines) ->
11220 (* The <define/> elements are referenced in the <start> section,
11221 * so build a map of those first.
11223 let defines = List.fold_left (
11225 function Xml.Element ("define", ["name", name], defn) ->
11226 StringMap.add name defn map
11228 failwithf "%s: expected <define name=name/>" rng_input
11229 ) StringMap.empty defines in
11230 let defines = StringMap.mapi parse_rng defines in
11232 (* Parse the <start> clause, passing the defines. *)
11233 parse_rng ~defines "<start>" gram
11235 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11238 let name_of_field = function
11239 | Element (name, _) | Attribute (name, _)
11240 | ZeroOrMore (Element (name, _))
11241 | OneOrMore (Element (name, _))
11242 | Optional (Element (name, _)) -> name
11243 | Optional (Attribute (name, _)) -> name
11244 | Text -> (* an unnamed field in an element *)
11247 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11249 (* At the moment this function only generates OCaml types. However we
11250 * should parameterize it later so it can generate types/structs in a
11251 * variety of languages.
11253 let generate_types xs =
11254 (* A simple type is one that can be printed out directly, eg.
11255 * "string option". A complex type is one which has a name and has
11256 * to be defined via another toplevel definition, eg. a struct.
11258 * generate_type generates code for either simple or complex types.
11259 * In the simple case, it returns the string ("string option"). In
11260 * the complex case, it returns the name ("mountpoint"). In the
11261 * complex case it has to print out the definition before returning,
11262 * so it should only be called when we are at the beginning of a
11263 * new line (BOL context).
11265 let rec generate_type = function
11266 | Text -> (* string *)
11268 | Choice values -> (* [`val1|`val2|...] *)
11269 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11270 | ZeroOrMore rng -> (* <rng> list *)
11271 let t, is_simple = generate_type rng in
11272 t ^ " list (* 0 or more *)", is_simple
11273 | OneOrMore rng -> (* <rng> list *)
11274 let t, is_simple = generate_type rng in
11275 t ^ " list (* 1 or more *)", is_simple
11276 (* virt-inspector hack: bool *)
11277 | Optional (Attribute (name, [Value "1"])) ->
11279 | Optional rng -> (* <rng> list *)
11280 let t, is_simple = generate_type rng in
11281 t ^ " option", is_simple
11282 (* type name = { fields ... } *)
11283 | Element (name, fields) when is_attrs_interleave fields ->
11284 generate_type_struct name (get_attrs_interleave fields)
11285 | Element (name, [field]) (* type name = field *)
11286 | Attribute (name, [field]) ->
11287 let t, is_simple = generate_type field in
11288 if is_simple then (t, true)
11290 pr "type %s = %s\n" name t;
11293 | Element (name, fields) -> (* type name = { fields ... } *)
11294 generate_type_struct name fields
11296 failwithf "generate_type failed at: %s" (string_of_rng rng)
11298 and is_attrs_interleave = function
11299 | [Interleave _] -> true
11300 | Attribute _ :: fields -> is_attrs_interleave fields
11301 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11304 and get_attrs_interleave = function
11305 | [Interleave fields] -> fields
11306 | ((Attribute _) as field) :: fields
11307 | ((Optional (Attribute _)) as field) :: fields ->
11308 field :: get_attrs_interleave fields
11309 | _ -> assert false
11311 and generate_types xs =
11312 List.iter (fun x -> ignore (generate_type x)) xs
11314 and generate_type_struct name fields =
11315 (* Calculate the types of the fields first. We have to do this
11316 * before printing anything so we are still in BOL context.
11318 let types = List.map fst (List.map generate_type fields) in
11320 (* Special case of a struct containing just a string and another
11321 * field. Turn it into an assoc list.
11324 | ["string"; other] ->
11325 let fname1, fname2 =
11327 | [f1; f2] -> name_of_field f1, name_of_field f2
11328 | _ -> assert false in
11329 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11333 pr "type %s = {\n" name;
11335 fun (field, ftype) ->
11336 let fname = name_of_field field in
11337 pr " %s_%s : %s;\n" name fname ftype
11338 ) (List.combine fields types);
11340 (* Return the name of this type, and
11341 * false because it's not a simple type.
11348 let generate_parsers xs =
11349 (* As for generate_type above, generate_parser makes a parser for
11350 * some type, and returns the name of the parser it has generated.
11351 * Because it (may) need to print something, it should always be
11352 * called in BOL context.
11354 let rec generate_parser = function
11355 | Text -> (* string *)
11356 "string_child_or_empty"
11357 | Choice values -> (* [`val1|`val2|...] *)
11358 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11360 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11361 | ZeroOrMore rng -> (* <rng> list *)
11362 let pa = generate_parser rng in
11363 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11364 | OneOrMore rng -> (* <rng> list *)
11365 let pa = generate_parser rng in
11366 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11367 (* virt-inspector hack: bool *)
11368 | Optional (Attribute (name, [Value "1"])) ->
11369 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11370 | Optional rng -> (* <rng> list *)
11371 let pa = generate_parser rng in
11372 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11373 (* type name = { fields ... } *)
11374 | Element (name, fields) when is_attrs_interleave fields ->
11375 generate_parser_struct name (get_attrs_interleave fields)
11376 | Element (name, [field]) -> (* type name = field *)
11377 let pa = generate_parser field in
11378 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11379 pr "let %s =\n" parser_name;
11381 pr "let parse_%s = %s\n" name parser_name;
11383 | Attribute (name, [field]) ->
11384 let pa = generate_parser field in
11385 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11386 pr "let %s =\n" parser_name;
11388 pr "let parse_%s = %s\n" name parser_name;
11390 | Element (name, fields) -> (* type name = { fields ... } *)
11391 generate_parser_struct name ([], fields)
11393 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11395 and is_attrs_interleave = function
11396 | [Interleave _] -> true
11397 | Attribute _ :: fields -> is_attrs_interleave fields
11398 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11401 and get_attrs_interleave = function
11402 | [Interleave fields] -> [], fields
11403 | ((Attribute _) as field) :: fields
11404 | ((Optional (Attribute _)) as field) :: fields ->
11405 let attrs, interleaves = get_attrs_interleave fields in
11406 (field :: attrs), interleaves
11407 | _ -> assert false
11409 and generate_parsers xs =
11410 List.iter (fun x -> ignore (generate_parser x)) xs
11412 and generate_parser_struct name (attrs, interleaves) =
11413 (* Generate parsers for the fields first. We have to do this
11414 * before printing anything so we are still in BOL context.
11416 let fields = attrs @ interleaves in
11417 let pas = List.map generate_parser fields in
11419 (* Generate an intermediate tuple from all the fields first.
11420 * If the type is just a string + another field, then we will
11421 * return this directly, otherwise it is turned into a record.
11423 * RELAX NG note: This code treats <interleave> and plain lists of
11424 * fields the same. In other words, it doesn't bother enforcing
11425 * any ordering of fields in the XML.
11427 pr "let parse_%s x =\n" name;
11428 pr " let t = (\n ";
11429 let comma = ref false in
11432 if !comma then pr ",\n ";
11435 | Optional (Attribute (fname, [field])), pa ->
11437 | Optional (Element (fname, [field])), pa ->
11438 pr "%s (optional_child %S x)" pa fname
11439 | Attribute (fname, [Text]), _ ->
11440 pr "attribute %S x" fname
11441 | (ZeroOrMore _ | OneOrMore _), pa ->
11446 let fname = name_of_field field in
11447 pr "%s (child %S x)" pa fname
11448 ) (List.combine fields pas);
11452 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11456 pr " (Obj.magic t : %s)\n" name
11460 | (Optional (Attribute (fname, [field])), pa) ->
11461 pr " %s_%s =\n" name fname;
11463 | (Optional (Element (fname, [field])), pa) ->
11464 pr " %s_%s =\n" name fname;
11465 pr " (let x = optional_child %S x in\n" fname;
11468 let fname = name_of_field field in
11469 pr " %s_%s =\n" name fname;
11470 pr " (let x = child %S x in\n" fname;
11472 ) (List.combine fields pas);
11476 sprintf "parse_%s" name
11479 generate_parsers xs
11481 (* Generate ocaml/guestfs_inspector.mli. *)
11482 let generate_ocaml_inspector_mli () =
11483 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11486 (** This is an OCaml language binding to the external [virt-inspector]
11489 For more information, please read the man page [virt-inspector(1)].
11494 generate_types grammar;
11495 pr "(** The nested information returned from the {!inspect} function. *)\n";
11499 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11500 (** To inspect a libvirt domain called [name], pass a singleton
11501 list: [inspect [name]]. When using libvirt only, you may
11502 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11504 To inspect a disk image or images, pass a list of the filenames
11505 of the disk images: [inspect filenames]
11507 This function inspects the given guest or disk images and
11508 returns a list of operating system(s) found and a large amount
11509 of information about them. In the vast majority of cases,
11510 a virtual machine only contains a single operating system.
11512 If the optional [~xml] parameter is given, then this function
11513 skips running the external virt-inspector program and just
11514 parses the given XML directly (which is expected to be XML
11515 produced from a previous run of virt-inspector). The list of
11516 names and connect URI are ignored in this case.
11518 This function can throw a wide variety of exceptions, for example
11519 if the external virt-inspector program cannot be found, or if
11520 it doesn't generate valid XML.
11524 (* Generate ocaml/guestfs_inspector.ml. *)
11525 let generate_ocaml_inspector_ml () =
11526 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11531 generate_types grammar;
11535 (* Misc functions which are used by the parser code below. *)
11536 let first_child = function
11537 | Xml.Element (_, _, c::_) -> c
11538 | Xml.Element (name, _, []) ->
11539 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11540 | Xml.PCData str ->
11541 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11543 let string_child_or_empty = function
11544 | Xml.Element (_, _, [Xml.PCData s]) -> s
11545 | Xml.Element (_, _, []) -> \"\"
11546 | Xml.Element (x, _, _) ->
11547 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11549 | Xml.PCData str ->
11550 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11552 let optional_child name xml =
11553 let children = Xml.children xml in
11555 Some (List.find (function
11556 | Xml.Element (n, _, _) when n = name -> true
11557 | _ -> false) children)
11561 let child name xml =
11562 match optional_child name xml with
11565 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11567 let attribute name xml =
11568 try Xml.attrib xml name
11569 with Xml.No_attribute _ ->
11570 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11574 generate_parsers grammar;
11578 (* Run external virt-inspector, then use parser to parse the XML. *)
11579 let inspect ?connect ?xml names =
11583 if names = [] then invalid_arg \"inspect: no names given\";
11584 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11585 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11587 let cmd = List.map Filename.quote cmd in
11588 let cmd = String.concat \" \" cmd in
11589 let chan = open_process_in cmd in
11590 let xml = Xml.parse_in chan in
11591 (match close_process_in chan with
11593 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11594 | WSIGNALED i | WSTOPPED i ->
11595 failwith (\"external virt-inspector command died or stopped on sig \" ^
11600 Xml.parse_string doc in
11601 parse_operatingsystems xml
11604 (* This is used to generate the src/MAX_PROC_NR file which
11605 * contains the maximum procedure number, a surrogate for the
11606 * ABI version number. See src/Makefile.am for the details.
11608 and generate_max_proc_nr () =
11609 let proc_nrs = List.map (
11610 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11611 ) daemon_functions in
11613 let max_proc_nr = List.fold_left max 0 proc_nrs in
11615 pr "%d\n" max_proc_nr
11617 let output_to filename k =
11618 let filename_new = filename ^ ".new" in
11619 chan := open_out filename_new;
11622 chan := Pervasives.stdout;
11624 (* Is the new file different from the current file? *)
11625 if Sys.file_exists filename && files_equal filename filename_new then
11626 unlink filename_new (* same, so skip it *)
11628 (* different, overwrite old one *)
11629 (try chmod filename 0o644 with Unix_error _ -> ());
11630 rename filename_new filename;
11631 chmod filename 0o444;
11632 printf "written %s\n%!" filename;
11635 let perror msg = function
11636 | Unix_error (err, _, _) ->
11637 eprintf "%s: %s\n" msg (error_message err)
11639 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11641 (* Main program. *)
11644 try openfile "HACKING" [O_RDWR] 0
11646 | Unix_error (ENOENT, _, _) ->
11648 You are probably running this from the wrong directory.
11649 Run it from the top source directory using the command
11654 perror "open: HACKING" exn;
11657 (* Acquire a lock so parallel builds won't try to run the generator
11658 * twice at the same time. Subsequent builds will wait for the first
11659 * one to finish. Note the lock is released implicitly when the
11662 (try lockf lock_fd F_LOCK 1
11664 perror "lock: HACKING" exn;
11667 check_functions ();
11669 output_to "src/guestfs_protocol.x" generate_xdr;
11670 output_to "src/guestfs-structs.h" generate_structs_h;
11671 output_to "src/guestfs-actions.h" generate_actions_h;
11672 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11673 output_to "src/guestfs-actions.c" generate_client_actions;
11674 output_to "src/guestfs-bindtests.c" generate_bindtests;
11675 output_to "src/guestfs-structs.pod" generate_structs_pod;
11676 output_to "src/guestfs-actions.pod" generate_actions_pod;
11677 output_to "src/guestfs-availability.pod" generate_availability_pod;
11678 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11679 output_to "src/libguestfs.syms" generate_linker_script;
11680 output_to "daemon/actions.h" generate_daemon_actions_h;
11681 output_to "daemon/stubs.c" generate_daemon_actions;
11682 output_to "daemon/names.c" generate_daemon_names;
11683 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11684 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11685 output_to "capitests/tests.c" generate_tests;
11686 output_to "fish/cmds.c" generate_fish_cmds;
11687 output_to "fish/completion.c" generate_fish_completion;
11688 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11689 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11690 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11691 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11692 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11693 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11694 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11695 output_to "perl/Guestfs.xs" generate_perl_xs;
11696 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11697 output_to "perl/bindtests.pl" generate_perl_bindtests;
11698 output_to "python/guestfs-py.c" generate_python_c;
11699 output_to "python/guestfs.py" generate_python_py;
11700 output_to "python/bindtests.py" generate_python_bindtests;
11701 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11702 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11703 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11707 let cols = cols_of_struct typ in
11708 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11709 output_to filename (generate_java_struct jtyp cols);
11712 output_to "java/Makefile.inc" generate_java_makefile_inc;
11713 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11714 output_to "java/Bindtests.java" generate_java_bindtests;
11715 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11716 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11717 output_to "csharp/Libguestfs.cs" generate_csharp;
11719 (* Always generate this file last, and unconditionally. It's used
11720 * by the Makefile to know when we must re-run the generator.
11722 let chan = open_out "src/stamp-generator" in
11723 fprintf chan "1\n";
11726 printf "generated %d lines of code\n" !lines