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 | NotInFish (* do not export via guestfish *)
186 | NotInDocs (* do not add this function to documentation *)
187 | DeprecatedBy of string (* function is deprecated, use .. instead *)
188 | Optional of string (* function is part of an optional group *)
190 (* You can supply zero or as many tests as you want per API call.
192 * Note that the test environment has 3 block devices, of size 500MB,
193 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194 * a fourth ISO block device with some known files on it (/dev/sdd).
196 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197 * Number of cylinders was 63 for IDE emulated disks with precisely
198 * the same size. How exactly this is calculated is a mystery.
200 * The ISO block device (/dev/sdd) comes from images/test.iso.
202 * To be able to run the tests in a reasonable amount of time,
203 * the virtual machine and block devices are reused between tests.
204 * So don't try testing kill_subprocess :-x
206 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
208 * Don't assume anything about the previous contents of the block
209 * devices. Use 'Init*' to create some initial scenarios.
211 * You can add a prerequisite clause to any individual test. This
212 * is a run-time check, which, if it fails, causes the test to be
213 * skipped. Useful if testing a command which might not work on
214 * all variations of libguestfs builds. A test that has prerequisite
215 * of 'Always' is run unconditionally.
217 * In addition, packagers can skip individual tests by setting the
218 * environment variables: eg:
219 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
220 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
222 type tests = (test_init * test_prereq * test) list
224 (* Run the command sequence and just expect nothing to fail. *)
227 (* Run the command sequence and expect the output of the final
228 * command to be the string.
230 | TestOutput of seq * string
232 (* Run the command sequence and expect the output of the final
233 * command to be the list of strings.
235 | TestOutputList of seq * string list
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of block devices (could be either
239 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240 * character of each string).
242 | TestOutputListOfDevices of seq * string list
244 (* Run the command sequence and expect the output of the final
245 * command to be the integer.
247 | TestOutputInt of seq * int
249 (* Run the command sequence and expect the output of the final
250 * command to be <op> <int>, eg. ">=", "1".
252 | TestOutputIntOp of seq * string * int
254 (* Run the command sequence and expect the output of the final
255 * command to be a true value (!= 0 or != NULL).
257 | TestOutputTrue of seq
259 (* Run the command sequence and expect the output of the final
260 * command to be a false value (== 0 or == NULL, but not an error).
262 | TestOutputFalse of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a list of the given length (but don't care about
268 | TestOutputLength of seq * int
270 (* Run the command sequence and expect the output of the final
271 * command to be a buffer (RBufferOut), ie. string + size.
273 | TestOutputBuffer of seq * string
275 (* Run the command sequence and expect the output of the final
276 * command to be a structure.
278 | TestOutputStruct of seq * test_field_compare list
280 (* Run the command sequence and expect the final command (only)
283 | TestLastFail of seq
285 and test_field_compare =
286 | CompareWithInt of string * int
287 | CompareWithIntOp of string * string * int
288 | CompareWithString of string * string
289 | CompareFieldsIntEq of string * string
290 | CompareFieldsStrEq of string * string
292 (* Test prerequisites. *)
294 (* Test always runs. *)
297 (* Test is currently disabled - eg. it fails, or it tests some
298 * unimplemented feature.
302 (* 'string' is some C code (a function body) that should return
303 * true or false. The test will run if the code returns true.
307 (* As for 'If' but the test runs _unless_ the code returns true. *)
310 (* Some initial scenarios for testing. *)
312 (* Do nothing, block devices could contain random stuff including
313 * LVM PVs, and some filesystems might be mounted. This is usually
318 (* Block devices are empty and no filesystems are mounted. *)
321 (* /dev/sda contains a single partition /dev/sda1, with random
322 * content. /dev/sdb and /dev/sdc may have random content.
327 (* /dev/sda contains a single partition /dev/sda1, which is formatted
328 * as ext2, empty [except for lost+found] and mounted on /.
329 * /dev/sdb and /dev/sdc may have random content.
335 * /dev/sda1 (is a PV):
336 * /dev/VG/LV (size 8MB):
337 * formatted as ext2, empty [except for lost+found], mounted on /
338 * /dev/sdb and /dev/sdc may have random content.
342 (* /dev/sdd (the ISO, see images/ directory in source)
347 (* Sequence of commands for testing. *)
349 and cmd = string list
351 (* Note about long descriptions: When referring to another
352 * action, use the format C<guestfs_other> (ie. the full name of
353 * the C function). This will be replaced as appropriate in other
356 * Apart from that, long descriptions are just perldoc paragraphs.
359 (* Generate a random UUID (used in tests). *)
361 let chan = open_process_in "uuidgen" in
362 let uuid = input_line chan in
363 (match close_process_in chan with
366 failwith "uuidgen: process exited with non-zero status"
367 | WSIGNALED _ | WSTOPPED _ ->
368 failwith "uuidgen: process signalled or stopped by signal"
372 (* These test functions are used in the language binding tests. *)
374 let test_all_args = [
377 StringList "strlist";
385 let test_all_rets = [
386 (* except for RErr, which is tested thoroughly elsewhere *)
387 "test0rint", RInt "valout";
388 "test0rint64", RInt64 "valout";
389 "test0rbool", RBool "valout";
390 "test0rconststring", RConstString "valout";
391 "test0rconstoptstring", RConstOptString "valout";
392 "test0rstring", RString "valout";
393 "test0rstringlist", RStringList "valout";
394 "test0rstruct", RStruct ("valout", "lvm_pv");
395 "test0rstructlist", RStructList ("valout", "lvm_pv");
396 "test0rhashtable", RHashtable "valout";
399 let test_functions = [
400 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
402 "internal test function - do not use",
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
408 It echos the contents of each parameter to stdout.
410 You probably don't want to call this function.");
414 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
416 "internal test function - do not use",
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
422 It converts string C<val> to the return type.
424 You probably don't want to call this function.");
425 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
427 "internal test function - do not use",
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
433 This function always returns an error.
435 You probably don't want to call this function.")]
439 (* non_daemon_functions are any functions which don't get processed
440 * in the daemon, eg. functions for setting and getting local
441 * configuration values.
444 let non_daemon_functions = test_functions @ [
445 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
447 "launch the qemu subprocess",
449 Internally libguestfs is implemented by running a virtual machine
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
455 ("wait_ready", (RErr, []), -1, [NotInFish],
457 "wait until the qemu subprocess launches (no op)",
459 This function is a no op.
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete. However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
470 ("kill_subprocess", (RErr, []), -1, [],
472 "kill the qemu subprocess",
474 This kills the qemu subprocess. You should never need to call this.");
476 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
478 "add an image to examine or modify",
480 This function adds a virtual machine disk image C<filename> to the
481 guest. The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
485 You don't necessarily need to be root when using libguestfs. However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>. In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
502 Note that this call checks for the existence of C<filename>. This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
505 the general C<guestfs_config> call instead.");
507 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
509 "add a CD-ROM disk image to examine",
511 This function adds a virtual CD-ROM disk image to the guest.
513 This is equivalent to the qemu parameter C<-cdrom filename>.
521 This call checks for the existence of C<filename>. This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
524 the general C<guestfs_config> call instead.
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
534 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
536 "add a drive in snapshot mode (read-only)",
538 This adds a drive in snapshot mode, making it effectively
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed. We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>. In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
555 C<readonly=on> is only added where qemu supports this option.
557 Note that this call checks for the existence of C<filename>. This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
560 the general C<guestfs_config> call instead.");
562 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
564 "add qemu parameters",
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>. Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
571 The first character of C<param> string must be a C<-> (dash).
573 C<value> can be NULL.");
575 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
577 "set the qemu binary",
579 Set the qemu binary that we will use.
581 The default is chosen when the library was compiled by the
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
589 Note that you should call this function as early as possible
590 after creating the handle. This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results. Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
597 ("get_qemu", (RConstString "qemu", []), -1, [],
598 [InitNone, Always, TestRun (
600 "get the qemu binary",
602 Return the current qemu binary.
604 This is always non-NULL. If it wasn't set already, then this will
605 return the default qemu binary name.");
607 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
609 "set the search path",
611 Set the path that libguestfs searches for kernel and initrd.img.
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
616 Setting C<path> to C<NULL> restores the default path.");
618 ("get_path", (RConstString "path", []), -1, [],
619 [InitNone, Always, TestRun (
621 "get the search path",
623 Return the current search path.
625 This is always non-NULL. If it wasn't set already, then this will
626 return the default path.");
628 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
630 "add options to kernel command line",
632 This function is used to add additional options to the
633 guest kernel command line.
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
641 ("get_append", (RConstOptString "append", []), -1, [],
642 (* This cannot be tested with the current framework. The
643 * function can return NULL in normal operations, which the
644 * test framework interprets as an error.
647 "get the additional kernel options",
649 Return the additional kernel options which are added to the
650 guest kernel command line.
652 If C<NULL> then no options are added.");
654 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658 If C<autosync> is true, this enables autosync. Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
666 ("get_autosync", (RBool "autosync", []), -1, [],
667 [InitNone, Always, TestRun (
668 [["get_autosync"]])],
671 Get the autosync flag.");
673 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
682 ("get_verbose", (RBool "verbose", []), -1, [],
686 This returns the verbose messages flag.");
688 ("is_ready", (RBool "ready", []), -1, [],
689 [InitNone, Always, TestOutputTrue (
691 "is ready to accept commands",
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
696 For more information on states, see L<guestfs(3)>.");
698 ("is_config", (RBool "config", []), -1, [],
699 [InitNone, Always, TestOutputFalse (
701 "is in configuration state",
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
706 For more information on states, see L<guestfs(3)>.");
708 ("is_launching", (RBool "launching", []), -1, [],
709 [InitNone, Always, TestOutputFalse (
710 [["is_launching"]])],
711 "is launching subprocess",
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
716 For more information on states, see L<guestfs(3)>.");
718 ("is_busy", (RBool "busy", []), -1, [],
719 [InitNone, Always, TestOutputFalse (
721 "is busy processing a command",
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
726 For more information on states, see L<guestfs(3)>.");
728 ("get_state", (RInt "state", []), -1, [],
730 "get the current state",
732 This returns the current state as an opaque integer. This is
733 only useful for printing debug and internal error messages.
735 For more information on states, see L<guestfs(3)>.");
737 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738 [InitNone, Always, TestOutputInt (
739 [["set_memsize"; "500"];
740 ["get_memsize"]], 500)],
741 "set memory allocated to the qemu subprocess",
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess. This only has any effect if called before
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
754 ("get_memsize", (RInt "memsize", []), -1, [],
755 [InitNone, Always, TestOutputIntOp (
756 [["get_memsize"]], ">=", 256)],
757 "get memory allocated to the qemu subprocess",
759 This gets the memory size in megabytes allocated to the
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
769 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770 [InitNone, Always, TestOutputIntOp (
771 [["get_pid"]], ">=", 1)],
772 "get PID of qemu subprocess",
774 Return the process ID of the qemu subprocess. If there is no
775 qemu subprocess, then this will return an error.
777 This is an internal call used for debugging and testing.");
779 ("version", (RStruct ("version", "version"), []), -1, [],
780 [InitNone, Always, TestOutputStruct (
781 [["version"]], [CompareWithInt ("major", 1)])],
782 "get the library version number",
784 Return the libguestfs version number that the program is linked
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against. You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
792 This call was added in version C<1.0.58>. In previous
793 versions of libguestfs there was no way to get the version
794 number. From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
797 The call returns a structure with four elements. The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet. The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
806 I<Note:> Don't use this call to test for availability
807 of features. Distro backports makes this unreliable. Use
808 C<guestfs_available> instead.");
810 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811 [InitNone, Always, TestOutputTrue (
812 [["set_selinux"; "true"];
814 "set SELinux enabled or disabled at appliance boot",
816 This sets the selinux flag that is passed to the appliance
817 at boot time. The default is C<selinux=0> (disabled).
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
825 ("get_selinux", (RBool "selinux", []), -1, [],
827 "get SELinux enabled flag",
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
835 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836 [InitNone, Always, TestOutputFalse (
837 [["set_trace"; "false"];
839 "enable or disable command traces",
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish. In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
855 ("get_trace", (RBool "trace", []), -1, [],
857 "get command trace enabled flag",
859 Return the command trace flag.");
861 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862 [InitNone, Always, TestOutputFalse (
863 [["set_direct"; "false"];
865 "enable or disable direct appliance mode",
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
875 You probably don't want to use this unless you know what you
878 The default is disabled.");
880 ("get_direct", (RBool "direct", []), -1, [],
882 "get direct appliance mode flag",
884 Return the direct appliance mode flag.");
886 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887 [InitNone, Always, TestOutputTrue (
888 [["set_recovery_proc"; "true"];
889 ["get_recovery_proc"]])],
890 "enable or disable the recovery process",
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process. The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself). In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
906 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
908 "get recovery process enabled flag",
910 Return the recovery process enabled flag.");
912 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
914 "add a drive specifying the QEMU block emulation to use",
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
919 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921 "add a drive read-only specifying the QEMU block emulation to use",
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
928 (* daemon_functions are any functions which cause some action
929 * to take place in the daemon.
932 let daemon_functions = [
933 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934 [InitEmpty, Always, TestOutput (
935 [["part_disk"; "/dev/sda"; "mbr"];
936 ["mkfs"; "ext2"; "/dev/sda1"];
937 ["mount"; "/dev/sda1"; "/"];
938 ["write_file"; "/new"; "new file contents"; "0"];
939 ["cat"; "/new"]], "new file contents")],
940 "mount a guest disk at a position in the filesystem",
942 Mount a guest disk at a position in the filesystem. Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest. If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
948 The rules are the same as for L<mount(2)>: A filesystem must
949 first be mounted on C</> before others can be mounted. Other
950 filesystems can only be mounted on directories which already
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
959 ("sync", (RErr, []), 2, [],
960 [ InitEmpty, Always, TestRun [["sync"]]],
961 "sync disks, writes are flushed through to the disk image",
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
969 ("touch", (RErr, [Pathname "path"]), 3, [],
970 [InitBasicFS, Always, TestOutputTrue (
972 ["exists"; "/new"]])],
973 "update file timestamps or create a new file",
975 Touch acts like the L<touch(1)> command. It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
979 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980 [InitISOFS, Always, TestOutput (
981 [["cat"; "/known-2"]], "abcdef\n")],
982 "list the contents of a file",
984 Return the contents of the file named C<path>.
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string). For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
991 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992 [], (* XXX Tricky to test because it depends on the exact format
993 * of the 'ls -l' command, which changes between F10 and F11.
995 "list the files in a directory (long format)",
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
1000 This command is mostly useful for interactive sessions. It
1001 is I<not> intended that you try to parse the output string.");
1003 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004 [InitBasicFS, Always, TestOutputList (
1006 ["touch"; "/newer"];
1007 ["touch"; "/newest"];
1008 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009 "list the files in a directory",
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd). The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1015 This command is mostly useful for interactive sessions. Programs
1016 should probably use C<guestfs_readdir> instead.");
1018 ("list_devices", (RStringList "devices", []), 7, [],
1019 [InitEmpty, Always, TestOutputListOfDevices (
1020 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021 "list the block devices",
1023 List all the block devices.
1025 The full block device names are returned, eg. C</dev/sda>");
1027 ("list_partitions", (RStringList "partitions", []), 8, [],
1028 [InitBasicFS, Always, TestOutputListOfDevices (
1029 [["list_partitions"]], ["/dev/sda1"]);
1030 InitEmpty, Always, TestOutputListOfDevices (
1031 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033 "list the partitions",
1035 List all the partitions detected on all block devices.
1037 The full partition device names are returned, eg. C</dev/sda1>
1039 This does not return logical volumes. For that you will need to
1040 call C<guestfs_lvs>.");
1042 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044 [["pvs"]], ["/dev/sda1"]);
1045 InitEmpty, Always, TestOutputListOfDevices (
1046 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047 ["pvcreate"; "/dev/sda1"];
1048 ["pvcreate"; "/dev/sda2"];
1049 ["pvcreate"; "/dev/sda3"];
1050 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051 "list the LVM physical volumes (PVs)",
1053 List all the physical volumes detected. This is the equivalent
1054 of the L<pvs(8)> command.
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1059 See also C<guestfs_pvs_full>.");
1061 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062 [InitBasicFSonLVM, Always, TestOutputList (
1064 InitEmpty, Always, TestOutputList (
1065 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066 ["pvcreate"; "/dev/sda1"];
1067 ["pvcreate"; "/dev/sda2"];
1068 ["pvcreate"; "/dev/sda3"];
1069 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070 ["vgcreate"; "VG2"; "/dev/sda3"];
1071 ["vgs"]], ["VG1"; "VG2"])],
1072 "list the LVM volume groups (VGs)",
1074 List all the volumes groups detected. This is the equivalent
1075 of the L<vgs(8)> command.
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1080 See also C<guestfs_vgs_full>.");
1082 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083 [InitBasicFSonLVM, Always, TestOutputList (
1084 [["lvs"]], ["/dev/VG/LV"]);
1085 InitEmpty, Always, TestOutputList (
1086 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087 ["pvcreate"; "/dev/sda1"];
1088 ["pvcreate"; "/dev/sda2"];
1089 ["pvcreate"; "/dev/sda3"];
1090 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091 ["vgcreate"; "VG2"; "/dev/sda3"];
1092 ["lvcreate"; "LV1"; "VG1"; "50"];
1093 ["lvcreate"; "LV2"; "VG1"; "50"];
1094 ["lvcreate"; "LV3"; "VG2"; "50"];
1095 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096 "list the LVM logical volumes (LVs)",
1098 List all the logical volumes detected. This is the equivalent
1099 of the L<lvs(8)> command.
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1104 See also C<guestfs_lvs_full>.");
1106 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107 [], (* XXX how to test? *)
1108 "list the LVM physical volumes (PVs)",
1110 List all the physical volumes detected. This is the equivalent
1111 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1113 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114 [], (* XXX how to test? *)
1115 "list the LVM volume groups (VGs)",
1117 List all the volumes groups detected. This is the equivalent
1118 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1120 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121 [], (* XXX how to test? *)
1122 "list the LVM logical volumes (LVs)",
1124 List all the logical volumes detected. This is the equivalent
1125 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1127 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128 [InitISOFS, Always, TestOutputList (
1129 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130 InitISOFS, Always, TestOutputList (
1131 [["read_lines"; "/empty"]], [])],
1132 "read file as lines",
1134 Return the contents of the file named C<path>.
1136 The file contents are returned as a list of lines. Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line). For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1144 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145 [], (* XXX Augeas code needs tests. *)
1146 "create a new Augeas handle",
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1152 You must call this before using any other C<guestfs_aug_*>
1155 C<root> is the filesystem root. C<root> must not be NULL,
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1164 =item C<AUG_SAVE_BACKUP> = 1
1166 Keep the original file with a C<.augsave> extension.
1168 =item C<AUG_SAVE_NEWFILE> = 2
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1173 =item C<AUG_TYPE_CHECK> = 4
1175 Typecheck lenses (can be expensive).
1177 =item C<AUG_NO_STDINC> = 8
1179 Do not use standard load path for modules.
1181 =item C<AUG_SAVE_NOOP> = 16
1183 Make save a no-op, just record what would have been changed.
1185 =item C<AUG_NO_LOAD> = 32
1187 Do not load the tree in C<guestfs_aug_init>.
1191 To close the handle, you can call C<guestfs_aug_close>.
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1195 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196 [], (* XXX Augeas code needs tests. *)
1197 "close the current Augeas handle",
1199 Close the current Augeas handle and free up any resources
1200 used by it. After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1204 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205 [], (* XXX Augeas code needs tests. *)
1206 "define an Augeas variable",
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1215 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216 [], (* XXX Augeas code needs tests. *)
1217 "define an Augeas node",
1219 Defines a variable C<name> whose value is the result of
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1230 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231 [], (* XXX Augeas code needs tests. *)
1232 "look up the value of an Augeas path",
1234 Look up the value associated with C<path>. If C<path>
1235 matches exactly one node, the C<value> is returned.");
1237 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238 [], (* XXX Augeas code needs tests. *)
1239 "set Augeas path to value",
1241 Set the value associated with C<path> to C<val>.
1243 In the Augeas API, it is possible to clear a node by setting
1244 the value to NULL. Due to an oversight in the libguestfs API
1245 you cannot do that with this call. Instead you must use the
1246 C<guestfs_aug_clear> call.");
1248 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1249 [], (* XXX Augeas code needs tests. *)
1250 "insert a sibling Augeas node",
1252 Create a new sibling C<label> for C<path>, inserting it into
1253 the tree before or after C<path> (depending on the boolean
1256 C<path> must match exactly one existing node in the tree, and
1257 C<label> must be a label, ie. not contain C</>, C<*> or end
1258 with a bracketed index C<[N]>.");
1260 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1261 [], (* XXX Augeas code needs tests. *)
1262 "remove an Augeas path",
1264 Remove C<path> and all of its children.
1266 On success this returns the number of entries which were removed.");
1268 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1269 [], (* XXX Augeas code needs tests. *)
1272 Move the node C<src> to C<dest>. C<src> must match exactly
1273 one node. C<dest> is overwritten if it exists.");
1275 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1276 [], (* XXX Augeas code needs tests. *)
1277 "return Augeas nodes which match augpath",
1279 Returns a list of paths which match the path expression C<path>.
1280 The returned paths are sufficiently qualified so that they match
1281 exactly one node in the current tree.");
1283 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1284 [], (* XXX Augeas code needs tests. *)
1285 "write all pending Augeas changes to disk",
1287 This writes all pending changes to disk.
1289 The flags which were passed to C<guestfs_aug_init> affect exactly
1290 how files are saved.");
1292 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1293 [], (* XXX Augeas code needs tests. *)
1294 "load files into the tree",
1296 Load files into the tree.
1298 See C<aug_load> in the Augeas documentation for the full gory
1301 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1302 [], (* XXX Augeas code needs tests. *)
1303 "list Augeas nodes under augpath",
1305 This is just a shortcut for listing C<guestfs_aug_match>
1306 C<path/*> and sorting the resulting nodes into alphabetical order.");
1308 ("rm", (RErr, [Pathname "path"]), 29, [],
1309 [InitBasicFS, Always, TestRun
1312 InitBasicFS, Always, TestLastFail
1314 InitBasicFS, Always, TestLastFail
1319 Remove the single file C<path>.");
1321 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1322 [InitBasicFS, Always, TestRun
1325 InitBasicFS, Always, TestLastFail
1326 [["rmdir"; "/new"]];
1327 InitBasicFS, Always, TestLastFail
1329 ["rmdir"; "/new"]]],
1330 "remove a directory",
1332 Remove the single directory C<path>.");
1334 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1335 [InitBasicFS, Always, TestOutputFalse
1337 ["mkdir"; "/new/foo"];
1338 ["touch"; "/new/foo/bar"];
1340 ["exists"; "/new"]]],
1341 "remove a file or directory recursively",
1343 Remove the file or directory C<path>, recursively removing the
1344 contents if its a directory. This is like the C<rm -rf> shell
1347 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1348 [InitBasicFS, Always, TestOutputTrue
1350 ["is_dir"; "/new"]];
1351 InitBasicFS, Always, TestLastFail
1352 [["mkdir"; "/new/foo/bar"]]],
1353 "create a directory",
1355 Create a directory named C<path>.");
1357 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1358 [InitBasicFS, Always, TestOutputTrue
1359 [["mkdir_p"; "/new/foo/bar"];
1360 ["is_dir"; "/new/foo/bar"]];
1361 InitBasicFS, Always, TestOutputTrue
1362 [["mkdir_p"; "/new/foo/bar"];
1363 ["is_dir"; "/new/foo"]];
1364 InitBasicFS, Always, TestOutputTrue
1365 [["mkdir_p"; "/new/foo/bar"];
1366 ["is_dir"; "/new"]];
1367 (* Regression tests for RHBZ#503133: *)
1368 InitBasicFS, Always, TestRun
1370 ["mkdir_p"; "/new"]];
1371 InitBasicFS, Always, TestLastFail
1373 ["mkdir_p"; "/new"]]],
1374 "create a directory and parents",
1376 Create a directory named C<path>, creating any parent directories
1377 as necessary. This is like the C<mkdir -p> shell command.");
1379 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1380 [], (* XXX Need stat command to test *)
1383 Change the mode (permissions) of C<path> to C<mode>. Only
1384 numeric modes are supported.
1386 I<Note>: When using this command from guestfish, C<mode>
1387 by default would be decimal, unless you prefix it with
1388 C<0> to get octal, ie. use C<0700> not C<700>.");
1390 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1391 [], (* XXX Need stat command to test *)
1392 "change file owner and group",
1394 Change the file owner to C<owner> and group to C<group>.
1396 Only numeric uid and gid are supported. If you want to use
1397 names, you will need to locate and parse the password file
1398 yourself (Augeas support makes this relatively easy).");
1400 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1401 [InitISOFS, Always, TestOutputTrue (
1402 [["exists"; "/empty"]]);
1403 InitISOFS, Always, TestOutputTrue (
1404 [["exists"; "/directory"]])],
1405 "test if file or directory exists",
1407 This returns C<true> if and only if there is a file, directory
1408 (or anything) with the given C<path> name.
1410 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1412 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1413 [InitISOFS, Always, TestOutputTrue (
1414 [["is_file"; "/known-1"]]);
1415 InitISOFS, Always, TestOutputFalse (
1416 [["is_file"; "/directory"]])],
1417 "test if file exists",
1419 This returns C<true> if and only if there is a file
1420 with the given C<path> name. Note that it returns false for
1421 other objects like directories.
1423 See also C<guestfs_stat>.");
1425 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1426 [InitISOFS, Always, TestOutputFalse (
1427 [["is_dir"; "/known-3"]]);
1428 InitISOFS, Always, TestOutputTrue (
1429 [["is_dir"; "/directory"]])],
1430 "test if file exists",
1432 This returns C<true> if and only if there is a directory
1433 with the given C<path> name. Note that it returns false for
1434 other objects like files.
1436 See also C<guestfs_stat>.");
1438 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1439 [InitEmpty, Always, TestOutputListOfDevices (
1440 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1441 ["pvcreate"; "/dev/sda1"];
1442 ["pvcreate"; "/dev/sda2"];
1443 ["pvcreate"; "/dev/sda3"];
1444 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1445 "create an LVM physical volume",
1447 This creates an LVM physical volume on the named C<device>,
1448 where C<device> should usually be a partition name such
1451 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1452 [InitEmpty, Always, TestOutputList (
1453 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454 ["pvcreate"; "/dev/sda1"];
1455 ["pvcreate"; "/dev/sda2"];
1456 ["pvcreate"; "/dev/sda3"];
1457 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1458 ["vgcreate"; "VG2"; "/dev/sda3"];
1459 ["vgs"]], ["VG1"; "VG2"])],
1460 "create an LVM volume group",
1462 This creates an LVM volume group called C<volgroup>
1463 from the non-empty list of physical volumes C<physvols>.");
1465 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [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 ["lvcreate"; "LV1"; "VG1"; "50"];
1474 ["lvcreate"; "LV2"; "VG1"; "50"];
1475 ["lvcreate"; "LV3"; "VG2"; "50"];
1476 ["lvcreate"; "LV4"; "VG2"; "50"];
1477 ["lvcreate"; "LV5"; "VG2"; "50"];
1479 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1480 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1481 "create an LVM volume group",
1483 This creates an LVM volume group called C<logvol>
1484 on the volume group C<volgroup>, with C<size> megabytes.");
1486 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1487 [InitEmpty, Always, TestOutput (
1488 [["part_disk"; "/dev/sda"; "mbr"];
1489 ["mkfs"; "ext2"; "/dev/sda1"];
1490 ["mount_options"; ""; "/dev/sda1"; "/"];
1491 ["write_file"; "/new"; "new file contents"; "0"];
1492 ["cat"; "/new"]], "new file contents")],
1493 "make a filesystem",
1495 This creates a filesystem on C<device> (usually a partition
1496 or LVM logical volume). The filesystem type is C<fstype>, for
1499 ("sfdisk", (RErr, [Device "device";
1500 Int "cyls"; Int "heads"; Int "sectors";
1501 StringList "lines"]), 43, [DangerWillRobinson],
1503 "create partitions on a block device",
1505 This is a direct interface to the L<sfdisk(8)> program for creating
1506 partitions on block devices.
1508 C<device> should be a block device, for example C</dev/sda>.
1510 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1511 and sectors on the device, which are passed directly to sfdisk as
1512 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1513 of these, then the corresponding parameter is omitted. Usually for
1514 'large' disks, you can just pass C<0> for these, but for small
1515 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1516 out the right geometry and you will need to tell it.
1518 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1519 information refer to the L<sfdisk(8)> manpage.
1521 To create a single partition occupying the whole disk, you would
1522 pass C<lines> as a single element list, when the single element being
1523 the string C<,> (comma).
1525 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1526 C<guestfs_part_init>");
1528 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1529 [InitBasicFS, Always, TestOutput (
1530 [["write_file"; "/new"; "new file contents"; "0"];
1531 ["cat"; "/new"]], "new file contents");
1532 InitBasicFS, Always, TestOutput (
1533 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1534 ["cat"; "/new"]], "\nnew file contents\n");
1535 InitBasicFS, Always, TestOutput (
1536 [["write_file"; "/new"; "\n\n"; "0"];
1537 ["cat"; "/new"]], "\n\n");
1538 InitBasicFS, Always, TestOutput (
1539 [["write_file"; "/new"; ""; "0"];
1540 ["cat"; "/new"]], "");
1541 InitBasicFS, Always, TestOutput (
1542 [["write_file"; "/new"; "\n\n\n"; "0"];
1543 ["cat"; "/new"]], "\n\n\n");
1544 InitBasicFS, Always, TestOutput (
1545 [["write_file"; "/new"; "\n"; "0"];
1546 ["cat"; "/new"]], "\n")],
1549 This call creates a file called C<path>. The contents of the
1550 file is the string C<content> (which can contain any 8 bit data),
1551 with length C<size>.
1553 As a special case, if C<size> is C<0>
1554 then the length is calculated using C<strlen> (so in this case
1555 the content cannot contain embedded ASCII NULs).
1557 I<NB.> Owing to a bug, writing content containing ASCII NUL
1558 characters does I<not> work, even if the length is specified.
1559 We hope to resolve this bug in a future version. In the meantime
1560 use C<guestfs_upload>.");
1562 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1563 [InitEmpty, Always, TestOutputListOfDevices (
1564 [["part_disk"; "/dev/sda"; "mbr"];
1565 ["mkfs"; "ext2"; "/dev/sda1"];
1566 ["mount_options"; ""; "/dev/sda1"; "/"];
1567 ["mounts"]], ["/dev/sda1"]);
1568 InitEmpty, Always, TestOutputList (
1569 [["part_disk"; "/dev/sda"; "mbr"];
1570 ["mkfs"; "ext2"; "/dev/sda1"];
1571 ["mount_options"; ""; "/dev/sda1"; "/"];
1574 "unmount a filesystem",
1576 This unmounts the given filesystem. The filesystem may be
1577 specified either by its mountpoint (path) or the device which
1578 contains the filesystem.");
1580 ("mounts", (RStringList "devices", []), 46, [],
1581 [InitBasicFS, Always, TestOutputListOfDevices (
1582 [["mounts"]], ["/dev/sda1"])],
1583 "show mounted filesystems",
1585 This returns the list of currently mounted filesystems. It returns
1586 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1588 Some internal mounts are not shown.
1590 See also: C<guestfs_mountpoints>");
1592 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1593 [InitBasicFS, Always, TestOutputList (
1596 (* check that umount_all can unmount nested mounts correctly: *)
1597 InitEmpty, Always, TestOutputList (
1598 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1599 ["mkfs"; "ext2"; "/dev/sda1"];
1600 ["mkfs"; "ext2"; "/dev/sda2"];
1601 ["mkfs"; "ext2"; "/dev/sda3"];
1602 ["mount_options"; ""; "/dev/sda1"; "/"];
1604 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1605 ["mkdir"; "/mp1/mp2"];
1606 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1607 ["mkdir"; "/mp1/mp2/mp3"];
1610 "unmount all filesystems",
1612 This unmounts all mounted filesystems.
1614 Some internal mounts are not unmounted by this call.");
1616 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1618 "remove all LVM LVs, VGs and PVs",
1620 This command removes all LVM logical volumes, volume groups
1621 and physical volumes.");
1623 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1624 [InitISOFS, Always, TestOutput (
1625 [["file"; "/empty"]], "empty");
1626 InitISOFS, Always, TestOutput (
1627 [["file"; "/known-1"]], "ASCII text");
1628 InitISOFS, Always, TestLastFail (
1629 [["file"; "/notexists"]])],
1630 "determine file type",
1632 This call uses the standard L<file(1)> command to determine
1633 the type or contents of the file. This also works on devices,
1634 for example to find out whether a partition contains a filesystem.
1636 This call will also transparently look inside various types
1639 The exact command which runs is C<file -zbsL path>. Note in
1640 particular that the filename is not prepended to the output
1641 (the C<-b> option).");
1643 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1644 [InitBasicFS, Always, TestOutput (
1645 [["upload"; "test-command"; "/test-command"];
1646 ["chmod"; "0o755"; "/test-command"];
1647 ["command"; "/test-command 1"]], "Result1");
1648 InitBasicFS, Always, TestOutput (
1649 [["upload"; "test-command"; "/test-command"];
1650 ["chmod"; "0o755"; "/test-command"];
1651 ["command"; "/test-command 2"]], "Result2\n");
1652 InitBasicFS, Always, TestOutput (
1653 [["upload"; "test-command"; "/test-command"];
1654 ["chmod"; "0o755"; "/test-command"];
1655 ["command"; "/test-command 3"]], "\nResult3");
1656 InitBasicFS, Always, TestOutput (
1657 [["upload"; "test-command"; "/test-command"];
1658 ["chmod"; "0o755"; "/test-command"];
1659 ["command"; "/test-command 4"]], "\nResult4\n");
1660 InitBasicFS, Always, TestOutput (
1661 [["upload"; "test-command"; "/test-command"];
1662 ["chmod"; "0o755"; "/test-command"];
1663 ["command"; "/test-command 5"]], "\nResult5\n\n");
1664 InitBasicFS, Always, TestOutput (
1665 [["upload"; "test-command"; "/test-command"];
1666 ["chmod"; "0o755"; "/test-command"];
1667 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1668 InitBasicFS, Always, TestOutput (
1669 [["upload"; "test-command"; "/test-command"];
1670 ["chmod"; "0o755"; "/test-command"];
1671 ["command"; "/test-command 7"]], "");
1672 InitBasicFS, Always, TestOutput (
1673 [["upload"; "test-command"; "/test-command"];
1674 ["chmod"; "0o755"; "/test-command"];
1675 ["command"; "/test-command 8"]], "\n");
1676 InitBasicFS, Always, TestOutput (
1677 [["upload"; "test-command"; "/test-command"];
1678 ["chmod"; "0o755"; "/test-command"];
1679 ["command"; "/test-command 9"]], "\n\n");
1680 InitBasicFS, Always, TestOutput (
1681 [["upload"; "test-command"; "/test-command"];
1682 ["chmod"; "0o755"; "/test-command"];
1683 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1684 InitBasicFS, Always, TestOutput (
1685 [["upload"; "test-command"; "/test-command"];
1686 ["chmod"; "0o755"; "/test-command"];
1687 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1688 InitBasicFS, Always, TestLastFail (
1689 [["upload"; "test-command"; "/test-command"];
1690 ["chmod"; "0o755"; "/test-command"];
1691 ["command"; "/test-command"]])],
1692 "run a command from the guest filesystem",
1694 This call runs a command from the guest filesystem. The
1695 filesystem must be mounted, and must contain a compatible
1696 operating system (ie. something Linux, with the same
1697 or compatible processor architecture).
1699 The single parameter is an argv-style list of arguments.
1700 The first element is the name of the program to run.
1701 Subsequent elements are parameters. The list must be
1702 non-empty (ie. must contain a program name). Note that
1703 the command runs directly, and is I<not> invoked via
1704 the shell (see C<guestfs_sh>).
1706 The return value is anything printed to I<stdout> by
1709 If the command returns a non-zero exit status, then
1710 this function returns an error message. The error message
1711 string is the content of I<stderr> from the command.
1713 The C<$PATH> environment variable will contain at least
1714 C</usr/bin> and C</bin>. If you require a program from
1715 another location, you should provide the full path in the
1718 Shared libraries and data files required by the program
1719 must be available on filesystems which are mounted in the
1720 correct places. It is the caller's responsibility to ensure
1721 all filesystems that are needed are mounted at the right
1724 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1725 [InitBasicFS, Always, TestOutputList (
1726 [["upload"; "test-command"; "/test-command"];
1727 ["chmod"; "0o755"; "/test-command"];
1728 ["command_lines"; "/test-command 1"]], ["Result1"]);
1729 InitBasicFS, Always, TestOutputList (
1730 [["upload"; "test-command"; "/test-command"];
1731 ["chmod"; "0o755"; "/test-command"];
1732 ["command_lines"; "/test-command 2"]], ["Result2"]);
1733 InitBasicFS, Always, TestOutputList (
1734 [["upload"; "test-command"; "/test-command"];
1735 ["chmod"; "0o755"; "/test-command"];
1736 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1737 InitBasicFS, Always, TestOutputList (
1738 [["upload"; "test-command"; "/test-command"];
1739 ["chmod"; "0o755"; "/test-command"];
1740 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1741 InitBasicFS, Always, TestOutputList (
1742 [["upload"; "test-command"; "/test-command"];
1743 ["chmod"; "0o755"; "/test-command"];
1744 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1745 InitBasicFS, Always, TestOutputList (
1746 [["upload"; "test-command"; "/test-command"];
1747 ["chmod"; "0o755"; "/test-command"];
1748 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1749 InitBasicFS, Always, TestOutputList (
1750 [["upload"; "test-command"; "/test-command"];
1751 ["chmod"; "0o755"; "/test-command"];
1752 ["command_lines"; "/test-command 7"]], []);
1753 InitBasicFS, Always, TestOutputList (
1754 [["upload"; "test-command"; "/test-command"];
1755 ["chmod"; "0o755"; "/test-command"];
1756 ["command_lines"; "/test-command 8"]], [""]);
1757 InitBasicFS, Always, TestOutputList (
1758 [["upload"; "test-command"; "/test-command"];
1759 ["chmod"; "0o755"; "/test-command"];
1760 ["command_lines"; "/test-command 9"]], ["";""]);
1761 InitBasicFS, Always, TestOutputList (
1762 [["upload"; "test-command"; "/test-command"];
1763 ["chmod"; "0o755"; "/test-command"];
1764 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1765 InitBasicFS, Always, TestOutputList (
1766 [["upload"; "test-command"; "/test-command"];
1767 ["chmod"; "0o755"; "/test-command"];
1768 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1769 "run a command, returning lines",
1771 This is the same as C<guestfs_command>, but splits the
1772 result into a list of lines.
1774 See also: C<guestfs_sh_lines>");
1776 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1777 [InitISOFS, Always, TestOutputStruct (
1778 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1779 "get file information",
1781 Returns file information for the given C<path>.
1783 This is the same as the C<stat(2)> system call.");
1785 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1786 [InitISOFS, Always, TestOutputStruct (
1787 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1788 "get file information for a symbolic link",
1790 Returns file information for the given C<path>.
1792 This is the same as C<guestfs_stat> except that if C<path>
1793 is a symbolic link, then the link is stat-ed, not the file it
1796 This is the same as the C<lstat(2)> system call.");
1798 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1799 [InitISOFS, Always, TestOutputStruct (
1800 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1801 "get file system statistics",
1803 Returns file system statistics for any mounted file system.
1804 C<path> should be a file or directory in the mounted file system
1805 (typically it is the mount point itself, but it doesn't need to be).
1807 This is the same as the C<statvfs(2)> system call.");
1809 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1811 "get ext2/ext3/ext4 superblock details",
1813 This returns the contents of the ext2, ext3 or ext4 filesystem
1814 superblock on C<device>.
1816 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1817 manpage for more details. The list of fields returned isn't
1818 clearly defined, and depends on both the version of C<tune2fs>
1819 that libguestfs was built against, and the filesystem itself.");
1821 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1822 [InitEmpty, Always, TestOutputTrue (
1823 [["blockdev_setro"; "/dev/sda"];
1824 ["blockdev_getro"; "/dev/sda"]])],
1825 "set block device to read-only",
1827 Sets the block device named C<device> to read-only.
1829 This uses the L<blockdev(8)> command.");
1831 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1832 [InitEmpty, Always, TestOutputFalse (
1833 [["blockdev_setrw"; "/dev/sda"];
1834 ["blockdev_getro"; "/dev/sda"]])],
1835 "set block device to read-write",
1837 Sets the block device named C<device> to read-write.
1839 This uses the L<blockdev(8)> command.");
1841 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1842 [InitEmpty, Always, TestOutputTrue (
1843 [["blockdev_setro"; "/dev/sda"];
1844 ["blockdev_getro"; "/dev/sda"]])],
1845 "is block device set to read-only",
1847 Returns a boolean indicating if the block device is read-only
1848 (true if read-only, false if not).
1850 This uses the L<blockdev(8)> command.");
1852 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1853 [InitEmpty, Always, TestOutputInt (
1854 [["blockdev_getss"; "/dev/sda"]], 512)],
1855 "get sectorsize of block device",
1857 This returns the size of sectors on a block device.
1858 Usually 512, but can be larger for modern devices.
1860 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1863 This uses the L<blockdev(8)> command.");
1865 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1866 [InitEmpty, Always, TestOutputInt (
1867 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1868 "get blocksize of block device",
1870 This returns the block size of a device.
1872 (Note this is different from both I<size in blocks> and
1873 I<filesystem block size>).
1875 This uses the L<blockdev(8)> command.");
1877 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1879 "set blocksize of block device",
1881 This sets the block size of a device.
1883 (Note this is different from both I<size in blocks> and
1884 I<filesystem block size>).
1886 This uses the L<blockdev(8)> command.");
1888 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1889 [InitEmpty, Always, TestOutputInt (
1890 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1891 "get total size of device in 512-byte sectors",
1893 This returns the size of the device in units of 512-byte sectors
1894 (even if the sectorsize isn't 512 bytes ... weird).
1896 See also C<guestfs_blockdev_getss> for the real sector size of
1897 the device, and C<guestfs_blockdev_getsize64> for the more
1898 useful I<size in bytes>.
1900 This uses the L<blockdev(8)> command.");
1902 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1903 [InitEmpty, Always, TestOutputInt (
1904 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1905 "get total size of device in bytes",
1907 This returns the size of the device in bytes.
1909 See also C<guestfs_blockdev_getsz>.
1911 This uses the L<blockdev(8)> command.");
1913 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1914 [InitEmpty, Always, TestRun
1915 [["blockdev_flushbufs"; "/dev/sda"]]],
1916 "flush device buffers",
1918 This tells the kernel to flush internal buffers associated
1921 This uses the L<blockdev(8)> command.");
1923 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1924 [InitEmpty, Always, TestRun
1925 [["blockdev_rereadpt"; "/dev/sda"]]],
1926 "reread partition table",
1928 Reread the partition table on C<device>.
1930 This uses the L<blockdev(8)> command.");
1932 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1933 [InitBasicFS, Always, TestOutput (
1934 (* Pick a file from cwd which isn't likely to change. *)
1935 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1936 ["checksum"; "md5"; "/COPYING.LIB"]],
1937 Digest.to_hex (Digest.file "COPYING.LIB"))],
1938 "upload a file from the local machine",
1940 Upload local file C<filename> to C<remotefilename> on the
1943 C<filename> can also be a named pipe.
1945 See also C<guestfs_download>.");
1947 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1948 [InitBasicFS, Always, TestOutput (
1949 (* Pick a file from cwd which isn't likely to change. *)
1950 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1951 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1952 ["upload"; "testdownload.tmp"; "/upload"];
1953 ["checksum"; "md5"; "/upload"]],
1954 Digest.to_hex (Digest.file "COPYING.LIB"))],
1955 "download a file to the local machine",
1957 Download file C<remotefilename> and save it as C<filename>
1958 on the local machine.
1960 C<filename> can also be a named pipe.
1962 See also C<guestfs_upload>, C<guestfs_cat>.");
1964 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1965 [InitISOFS, Always, TestOutput (
1966 [["checksum"; "crc"; "/known-3"]], "2891671662");
1967 InitISOFS, Always, TestLastFail (
1968 [["checksum"; "crc"; "/notexists"]]);
1969 InitISOFS, Always, TestOutput (
1970 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1971 InitISOFS, Always, TestOutput (
1972 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1973 InitISOFS, Always, TestOutput (
1974 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1975 InitISOFS, Always, TestOutput (
1976 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1977 InitISOFS, Always, TestOutput (
1978 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1979 InitISOFS, Always, TestOutput (
1980 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1981 "compute MD5, SHAx or CRC checksum of file",
1983 This call computes the MD5, SHAx or CRC checksum of the
1986 The type of checksum to compute is given by the C<csumtype>
1987 parameter which must have one of the following values:
1993 Compute the cyclic redundancy check (CRC) specified by POSIX
1994 for the C<cksum> command.
1998 Compute the MD5 hash (using the C<md5sum> program).
2002 Compute the SHA1 hash (using the C<sha1sum> program).
2006 Compute the SHA224 hash (using the C<sha224sum> program).
2010 Compute the SHA256 hash (using the C<sha256sum> program).
2014 Compute the SHA384 hash (using the C<sha384sum> program).
2018 Compute the SHA512 hash (using the C<sha512sum> program).
2022 The checksum is returned as a printable string.");
2024 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2025 [InitBasicFS, Always, TestOutput (
2026 [["tar_in"; "../images/helloworld.tar"; "/"];
2027 ["cat"; "/hello"]], "hello\n")],
2028 "unpack tarfile to directory",
2030 This command uploads and unpacks local file C<tarfile> (an
2031 I<uncompressed> tar file) into C<directory>.
2033 To upload a compressed tarball, use C<guestfs_tgz_in>
2034 or C<guestfs_txz_in>.");
2036 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2038 "pack directory into tarfile",
2040 This command packs the contents of C<directory> and downloads
2041 it to local file C<tarfile>.
2043 To download a compressed tarball, use C<guestfs_tgz_out>
2044 or C<guestfs_txz_out>.");
2046 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2047 [InitBasicFS, Always, TestOutput (
2048 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2049 ["cat"; "/hello"]], "hello\n")],
2050 "unpack compressed tarball to directory",
2052 This command uploads and unpacks local file C<tarball> (a
2053 I<gzip compressed> tar file) into C<directory>.
2055 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2057 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2059 "pack directory into compressed tarball",
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarball>.
2064 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2066 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2067 [InitBasicFS, Always, TestLastFail (
2069 ["mount_ro"; "/dev/sda1"; "/"];
2070 ["touch"; "/new"]]);
2071 InitBasicFS, Always, TestOutput (
2072 [["write_file"; "/new"; "data"; "0"];
2074 ["mount_ro"; "/dev/sda1"; "/"];
2075 ["cat"; "/new"]], "data")],
2076 "mount a guest disk, read-only",
2078 This is the same as the C<guestfs_mount> command, but it
2079 mounts the filesystem with the read-only (I<-o ro>) flag.");
2081 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2083 "mount a guest disk with mount options",
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set the mount options as for the
2087 L<mount(8)> I<-o> flag.");
2089 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2091 "mount a guest disk with mount options and vfstype",
2093 This is the same as the C<guestfs_mount> command, but it
2094 allows you to set both the mount options and the vfstype
2095 as for the L<mount(8)> I<-o> and I<-t> flags.");
2097 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2099 "debugging and internals",
2101 The C<guestfs_debug> command exposes some internals of
2102 C<guestfsd> (the guestfs daemon) that runs inside the
2105 There is no comprehensive help for this command. You have
2106 to look at the file C<daemon/debug.c> in the libguestfs source
2107 to find out what you can do.");
2109 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2110 [InitEmpty, Always, TestOutputList (
2111 [["part_disk"; "/dev/sda"; "mbr"];
2112 ["pvcreate"; "/dev/sda1"];
2113 ["vgcreate"; "VG"; "/dev/sda1"];
2114 ["lvcreate"; "LV1"; "VG"; "50"];
2115 ["lvcreate"; "LV2"; "VG"; "50"];
2116 ["lvremove"; "/dev/VG/LV1"];
2117 ["lvs"]], ["/dev/VG/LV2"]);
2118 InitEmpty, Always, TestOutputList (
2119 [["part_disk"; "/dev/sda"; "mbr"];
2120 ["pvcreate"; "/dev/sda1"];
2121 ["vgcreate"; "VG"; "/dev/sda1"];
2122 ["lvcreate"; "LV1"; "VG"; "50"];
2123 ["lvcreate"; "LV2"; "VG"; "50"];
2124 ["lvremove"; "/dev/VG"];
2126 InitEmpty, Always, TestOutputList (
2127 [["part_disk"; "/dev/sda"; "mbr"];
2128 ["pvcreate"; "/dev/sda1"];
2129 ["vgcreate"; "VG"; "/dev/sda1"];
2130 ["lvcreate"; "LV1"; "VG"; "50"];
2131 ["lvcreate"; "LV2"; "VG"; "50"];
2132 ["lvremove"; "/dev/VG"];
2134 "remove an LVM logical volume",
2136 Remove an LVM logical volume C<device>, where C<device> is
2137 the path to the LV, such as C</dev/VG/LV>.
2139 You can also remove all LVs in a volume group by specifying
2140 the VG name, C</dev/VG>.");
2142 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2143 [InitEmpty, Always, TestOutputList (
2144 [["part_disk"; "/dev/sda"; "mbr"];
2145 ["pvcreate"; "/dev/sda1"];
2146 ["vgcreate"; "VG"; "/dev/sda1"];
2147 ["lvcreate"; "LV1"; "VG"; "50"];
2148 ["lvcreate"; "LV2"; "VG"; "50"];
2151 InitEmpty, Always, TestOutputList (
2152 [["part_disk"; "/dev/sda"; "mbr"];
2153 ["pvcreate"; "/dev/sda1"];
2154 ["vgcreate"; "VG"; "/dev/sda1"];
2155 ["lvcreate"; "LV1"; "VG"; "50"];
2156 ["lvcreate"; "LV2"; "VG"; "50"];
2159 "remove an LVM volume group",
2161 Remove an LVM volume group C<vgname>, (for example C<VG>).
2163 This also forcibly removes all logical volumes in the volume
2166 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2167 [InitEmpty, Always, TestOutputListOfDevices (
2168 [["part_disk"; "/dev/sda"; "mbr"];
2169 ["pvcreate"; "/dev/sda1"];
2170 ["vgcreate"; "VG"; "/dev/sda1"];
2171 ["lvcreate"; "LV1"; "VG"; "50"];
2172 ["lvcreate"; "LV2"; "VG"; "50"];
2174 ["pvremove"; "/dev/sda1"];
2176 InitEmpty, Always, TestOutputListOfDevices (
2177 [["part_disk"; "/dev/sda"; "mbr"];
2178 ["pvcreate"; "/dev/sda1"];
2179 ["vgcreate"; "VG"; "/dev/sda1"];
2180 ["lvcreate"; "LV1"; "VG"; "50"];
2181 ["lvcreate"; "LV2"; "VG"; "50"];
2183 ["pvremove"; "/dev/sda1"];
2185 InitEmpty, Always, TestOutputListOfDevices (
2186 [["part_disk"; "/dev/sda"; "mbr"];
2187 ["pvcreate"; "/dev/sda1"];
2188 ["vgcreate"; "VG"; "/dev/sda1"];
2189 ["lvcreate"; "LV1"; "VG"; "50"];
2190 ["lvcreate"; "LV2"; "VG"; "50"];
2192 ["pvremove"; "/dev/sda1"];
2194 "remove an LVM physical volume",
2196 This wipes a physical volume C<device> so that LVM will no longer
2199 The implementation uses the C<pvremove> command which refuses to
2200 wipe physical volumes that contain any volume groups, so you have
2201 to remove those first.");
2203 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2204 [InitBasicFS, Always, TestOutput (
2205 [["set_e2label"; "/dev/sda1"; "testlabel"];
2206 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2207 "set the ext2/3/4 filesystem label",
2209 This sets the ext2/3/4 filesystem label of the filesystem on
2210 C<device> to C<label>. Filesystem labels are limited to
2213 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2214 to return the existing label on a filesystem.");
2216 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2218 "get the ext2/3/4 filesystem label",
2220 This returns the ext2/3/4 filesystem label of the filesystem on
2223 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2224 (let uuid = uuidgen () in
2225 [InitBasicFS, Always, TestOutput (
2226 [["set_e2uuid"; "/dev/sda1"; uuid];
2227 ["get_e2uuid"; "/dev/sda1"]], uuid);
2228 InitBasicFS, Always, TestOutput (
2229 [["set_e2uuid"; "/dev/sda1"; "clear"];
2230 ["get_e2uuid"; "/dev/sda1"]], "");
2231 (* We can't predict what UUIDs will be, so just check the commands run. *)
2232 InitBasicFS, Always, TestRun (
2233 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2234 InitBasicFS, Always, TestRun (
2235 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2236 "set the ext2/3/4 filesystem UUID",
2238 This sets the ext2/3/4 filesystem UUID of the filesystem on
2239 C<device> to C<uuid>. The format of the UUID and alternatives
2240 such as C<clear>, C<random> and C<time> are described in the
2241 L<tune2fs(8)> manpage.
2243 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2244 to return the existing UUID of a filesystem.");
2246 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2248 "get the ext2/3/4 filesystem UUID",
2250 This returns the ext2/3/4 filesystem UUID of the filesystem on
2253 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2254 [InitBasicFS, Always, TestOutputInt (
2255 [["umount"; "/dev/sda1"];
2256 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2257 InitBasicFS, Always, TestOutputInt (
2258 [["umount"; "/dev/sda1"];
2259 ["zero"; "/dev/sda1"];
2260 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2261 "run the filesystem checker",
2263 This runs the filesystem checker (fsck) on C<device> which
2264 should have filesystem type C<fstype>.
2266 The returned integer is the status. See L<fsck(8)> for the
2267 list of status codes from C<fsck>.
2275 Multiple status codes can be summed together.
2279 A non-zero return code can mean \"success\", for example if
2280 errors have been corrected on the filesystem.
2284 Checking or repairing NTFS volumes is not supported
2289 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2291 ("zero", (RErr, [Device "device"]), 85, [],
2292 [InitBasicFS, Always, TestOutput (
2293 [["umount"; "/dev/sda1"];
2294 ["zero"; "/dev/sda1"];
2295 ["file"; "/dev/sda1"]], "data")],
2296 "write zeroes to the device",
2298 This command writes zeroes over the first few blocks of C<device>.
2300 How many blocks are zeroed isn't specified (but it's I<not> enough
2301 to securely wipe the device). It should be sufficient to remove
2302 any partition tables, filesystem superblocks and so on.
2304 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2306 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2307 (* Test disabled because grub-install incompatible with virtio-blk driver.
2308 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2310 [InitBasicFS, Disabled, TestOutputTrue (
2311 [["grub_install"; "/"; "/dev/sda1"];
2312 ["is_dir"; "/boot"]])],
2315 This command installs GRUB (the Grand Unified Bootloader) on
2316 C<device>, with the root directory being C<root>.");
2318 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2319 [InitBasicFS, Always, TestOutput (
2320 [["write_file"; "/old"; "file content"; "0"];
2321 ["cp"; "/old"; "/new"];
2322 ["cat"; "/new"]], "file content");
2323 InitBasicFS, Always, TestOutputTrue (
2324 [["write_file"; "/old"; "file content"; "0"];
2325 ["cp"; "/old"; "/new"];
2326 ["is_file"; "/old"]]);
2327 InitBasicFS, Always, TestOutput (
2328 [["write_file"; "/old"; "file content"; "0"];
2330 ["cp"; "/old"; "/dir/new"];
2331 ["cat"; "/dir/new"]], "file content")],
2334 This copies a file from C<src> to C<dest> where C<dest> is
2335 either a destination filename or destination directory.");
2337 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2338 [InitBasicFS, Always, TestOutput (
2339 [["mkdir"; "/olddir"];
2340 ["mkdir"; "/newdir"];
2341 ["write_file"; "/olddir/file"; "file content"; "0"];
2342 ["cp_a"; "/olddir"; "/newdir"];
2343 ["cat"; "/newdir/olddir/file"]], "file content")],
2344 "copy a file or directory recursively",
2346 This copies a file or directory from C<src> to C<dest>
2347 recursively using the C<cp -a> command.");
2349 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2350 [InitBasicFS, Always, TestOutput (
2351 [["write_file"; "/old"; "file content"; "0"];
2352 ["mv"; "/old"; "/new"];
2353 ["cat"; "/new"]], "file content");
2354 InitBasicFS, Always, TestOutputFalse (
2355 [["write_file"; "/old"; "file content"; "0"];
2356 ["mv"; "/old"; "/new"];
2357 ["is_file"; "/old"]])],
2360 This moves a file from C<src> to C<dest> where C<dest> is
2361 either a destination filename or destination directory.");
2363 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2364 [InitEmpty, Always, TestRun (
2365 [["drop_caches"; "3"]])],
2366 "drop kernel page cache, dentries and inodes",
2368 This instructs the guest kernel to drop its page cache,
2369 and/or dentries and inode caches. The parameter C<whattodrop>
2370 tells the kernel what precisely to drop, see
2371 L<http://linux-mm.org/Drop_Caches>
2373 Setting C<whattodrop> to 3 should drop everything.
2375 This automatically calls L<sync(2)> before the operation,
2376 so that the maximum guest memory is freed.");
2378 ("dmesg", (RString "kmsgs", []), 91, [],
2379 [InitEmpty, Always, TestRun (
2381 "return kernel messages",
2383 This returns the kernel messages (C<dmesg> output) from
2384 the guest kernel. This is sometimes useful for extended
2385 debugging of problems.
2387 Another way to get the same information is to enable
2388 verbose messages with C<guestfs_set_verbose> or by setting
2389 the environment variable C<LIBGUESTFS_DEBUG=1> before
2390 running the program.");
2392 ("ping_daemon", (RErr, []), 92, [],
2393 [InitEmpty, Always, TestRun (
2394 [["ping_daemon"]])],
2395 "ping the guest daemon",
2397 This is a test probe into the guestfs daemon running inside
2398 the qemu subprocess. Calling this function checks that the
2399 daemon responds to the ping message, without affecting the daemon
2400 or attached block device(s) in any other way.");
2402 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2403 [InitBasicFS, Always, TestOutputTrue (
2404 [["write_file"; "/file1"; "contents of a file"; "0"];
2405 ["cp"; "/file1"; "/file2"];
2406 ["equal"; "/file1"; "/file2"]]);
2407 InitBasicFS, Always, TestOutputFalse (
2408 [["write_file"; "/file1"; "contents of a file"; "0"];
2409 ["write_file"; "/file2"; "contents of another file"; "0"];
2410 ["equal"; "/file1"; "/file2"]]);
2411 InitBasicFS, Always, TestLastFail (
2412 [["equal"; "/file1"; "/file2"]])],
2413 "test if two files have equal contents",
2415 This compares the two files C<file1> and C<file2> and returns
2416 true if their content is exactly equal, or false otherwise.
2418 The external L<cmp(1)> program is used for the comparison.");
2420 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2421 [InitISOFS, Always, TestOutputList (
2422 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2423 InitISOFS, Always, TestOutputList (
2424 [["strings"; "/empty"]], [])],
2425 "print the printable strings in a file",
2427 This runs the L<strings(1)> command on a file and returns
2428 the list of printable strings found.");
2430 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2431 [InitISOFS, Always, TestOutputList (
2432 [["strings_e"; "b"; "/known-5"]], []);
2433 InitBasicFS, Disabled, TestOutputList (
2434 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2435 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2436 "print the printable strings in a file",
2438 This is like the C<guestfs_strings> command, but allows you to
2439 specify the encoding.
2441 See the L<strings(1)> manpage for the full list of encodings.
2443 Commonly useful encodings are C<l> (lower case L) which will
2444 show strings inside Windows/x86 files.
2446 The returned strings are transcoded to UTF-8.");
2448 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2449 [InitISOFS, Always, TestOutput (
2450 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2451 (* Test for RHBZ#501888c2 regression which caused large hexdump
2452 * commands to segfault.
2454 InitISOFS, Always, TestRun (
2455 [["hexdump"; "/100krandom"]])],
2456 "dump a file in hexadecimal",
2458 This runs C<hexdump -C> on the given C<path>. The result is
2459 the human-readable, canonical hex dump of the file.");
2461 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2462 [InitNone, Always, TestOutput (
2463 [["part_disk"; "/dev/sda"; "mbr"];
2464 ["mkfs"; "ext3"; "/dev/sda1"];
2465 ["mount_options"; ""; "/dev/sda1"; "/"];
2466 ["write_file"; "/new"; "test file"; "0"];
2467 ["umount"; "/dev/sda1"];
2468 ["zerofree"; "/dev/sda1"];
2469 ["mount_options"; ""; "/dev/sda1"; "/"];
2470 ["cat"; "/new"]], "test file")],
2471 "zero unused inodes and disk blocks on ext2/3 filesystem",
2473 This runs the I<zerofree> program on C<device>. This program
2474 claims to zero unused inodes and disk blocks on an ext2/3
2475 filesystem, thus making it possible to compress the filesystem
2478 You should B<not> run this program if the filesystem is
2481 It is possible that using this program can damage the filesystem
2482 or data on the filesystem.");
2484 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2486 "resize an LVM physical volume",
2488 This resizes (expands or shrinks) an existing LVM physical
2489 volume to match the new size of the underlying device.");
2491 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2492 Int "cyls"; Int "heads"; Int "sectors";
2493 String "line"]), 99, [DangerWillRobinson],
2495 "modify a single partition on a block device",
2497 This runs L<sfdisk(8)> option to modify just the single
2498 partition C<n> (note: C<n> counts from 1).
2500 For other parameters, see C<guestfs_sfdisk>. You should usually
2501 pass C<0> for the cyls/heads/sectors parameters.
2503 See also: C<guestfs_part_add>");
2505 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2507 "display the partition table",
2509 This displays the partition table on C<device>, in the
2510 human-readable output of the L<sfdisk(8)> command. It is
2511 not intended to be parsed.
2513 See also: C<guestfs_part_list>");
2515 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2517 "display the kernel geometry",
2519 This displays the kernel's idea of the geometry of C<device>.
2521 The result is in human-readable format, and not designed to
2524 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2526 "display the disk geometry from the partition table",
2528 This displays the disk geometry of C<device> read from the
2529 partition table. Especially in the case where the underlying
2530 block device has been resized, this can be different from the
2531 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2533 The result is in human-readable format, and not designed to
2536 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2538 "activate or deactivate all volume groups",
2540 This command activates or (if C<activate> is false) deactivates
2541 all logical volumes in all volume groups.
2542 If activated, then they are made known to the
2543 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2544 then those devices disappear.
2546 This command is the same as running C<vgchange -a y|n>");
2548 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2550 "activate or deactivate some volume groups",
2552 This command activates or (if C<activate> is false) deactivates
2553 all logical volumes in the listed volume groups C<volgroups>.
2554 If activated, then they are made known to the
2555 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2556 then those devices disappear.
2558 This command is the same as running C<vgchange -a y|n volgroups...>
2560 Note that if C<volgroups> is an empty list then B<all> volume groups
2561 are activated or deactivated.");
2563 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2564 [InitNone, Always, TestOutput (
2565 [["part_disk"; "/dev/sda"; "mbr"];
2566 ["pvcreate"; "/dev/sda1"];
2567 ["vgcreate"; "VG"; "/dev/sda1"];
2568 ["lvcreate"; "LV"; "VG"; "10"];
2569 ["mkfs"; "ext2"; "/dev/VG/LV"];
2570 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2571 ["write_file"; "/new"; "test content"; "0"];
2573 ["lvresize"; "/dev/VG/LV"; "20"];
2574 ["e2fsck_f"; "/dev/VG/LV"];
2575 ["resize2fs"; "/dev/VG/LV"];
2576 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2577 ["cat"; "/new"]], "test content")],
2578 "resize an LVM logical volume",
2580 This resizes (expands or shrinks) an existing LVM logical
2581 volume to C<mbytes>. When reducing, data in the reduced part
2584 ("resize2fs", (RErr, [Device "device"]), 106, [],
2585 [], (* lvresize tests this *)
2586 "resize an ext2/ext3 filesystem",
2588 This resizes an ext2 or ext3 filesystem to match the size of
2589 the underlying device.
2591 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2592 on the C<device> before calling this command. For unknown reasons
2593 C<resize2fs> sometimes gives an error about this and sometimes not.
2594 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2595 calling this function.");
2597 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2598 [InitBasicFS, Always, TestOutputList (
2599 [["find"; "/"]], ["lost+found"]);
2600 InitBasicFS, Always, TestOutputList (
2604 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2605 InitBasicFS, Always, TestOutputList (
2606 [["mkdir_p"; "/a/b/c"];
2607 ["touch"; "/a/b/c/d"];
2608 ["find"; "/a/b/"]], ["c"; "c/d"])],
2609 "find all files and directories",
2611 This command lists out all files and directories, recursively,
2612 starting at C<directory>. It is essentially equivalent to
2613 running the shell command C<find directory -print> but some
2614 post-processing happens on the output, described below.
2616 This returns a list of strings I<without any prefix>. Thus
2617 if the directory structure was:
2623 then the returned list from C<guestfs_find> C</tmp> would be
2631 If C<directory> is not a directory, then this command returns
2634 The returned list is sorted.
2636 See also C<guestfs_find0>.");
2638 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2639 [], (* lvresize tests this *)
2640 "check an ext2/ext3 filesystem",
2642 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2643 filesystem checker on C<device>, noninteractively (C<-p>),
2644 even if the filesystem appears to be clean (C<-f>).
2646 This command is only needed because of C<guestfs_resize2fs>
2647 (q.v.). Normally you should use C<guestfs_fsck>.");
2649 ("sleep", (RErr, [Int "secs"]), 109, [],
2650 [InitNone, Always, TestRun (
2652 "sleep for some seconds",
2654 Sleep for C<secs> seconds.");
2656 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2657 [InitNone, Always, TestOutputInt (
2658 [["part_disk"; "/dev/sda"; "mbr"];
2659 ["mkfs"; "ntfs"; "/dev/sda1"];
2660 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2661 InitNone, Always, TestOutputInt (
2662 [["part_disk"; "/dev/sda"; "mbr"];
2663 ["mkfs"; "ext2"; "/dev/sda1"];
2664 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2665 "probe NTFS volume",
2667 This command runs the L<ntfs-3g.probe(8)> command which probes
2668 an NTFS C<device> for mountability. (Not all NTFS volumes can
2669 be mounted read-write, and some cannot be mounted at all).
2671 C<rw> is a boolean flag. Set it to true if you want to test
2672 if the volume can be mounted read-write. Set it to false if
2673 you want to test if the volume can be mounted read-only.
2675 The return value is an integer which C<0> if the operation
2676 would succeed, or some non-zero value documented in the
2677 L<ntfs-3g.probe(8)> manual page.");
2679 ("sh", (RString "output", [String "command"]), 111, [],
2680 [], (* XXX needs tests *)
2681 "run a command via the shell",
2683 This call runs a command from the guest filesystem via the
2686 This is like C<guestfs_command>, but passes the command to:
2688 /bin/sh -c \"command\"
2690 Depending on the guest's shell, this usually results in
2691 wildcards being expanded, shell expressions being interpolated
2694 All the provisos about C<guestfs_command> apply to this call.");
2696 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2697 [], (* XXX needs tests *)
2698 "run a command via the shell returning lines",
2700 This is the same as C<guestfs_sh>, but splits the result
2701 into a list of lines.
2703 See also: C<guestfs_command_lines>");
2705 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2706 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2707 * code in stubs.c, since all valid glob patterns must start with "/".
2708 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2710 [InitBasicFS, Always, TestOutputList (
2711 [["mkdir_p"; "/a/b/c"];
2712 ["touch"; "/a/b/c/d"];
2713 ["touch"; "/a/b/c/e"];
2714 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715 InitBasicFS, Always, TestOutputList (
2716 [["mkdir_p"; "/a/b/c"];
2717 ["touch"; "/a/b/c/d"];
2718 ["touch"; "/a/b/c/e"];
2719 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2720 InitBasicFS, Always, TestOutputList (
2721 [["mkdir_p"; "/a/b/c"];
2722 ["touch"; "/a/b/c/d"];
2723 ["touch"; "/a/b/c/e"];
2724 ["glob_expand"; "/a/*/x/*"]], [])],
2725 "expand a wildcard path",
2727 This command searches for all the pathnames matching
2728 C<pattern> according to the wildcard expansion rules
2731 If no paths match, then this returns an empty list
2732 (note: not an error).
2734 It is just a wrapper around the C L<glob(3)> function
2735 with flags C<GLOB_MARK|GLOB_BRACE>.
2736 See that manual page for more details.");
2738 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2739 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2740 [["scrub_device"; "/dev/sdc"]])],
2741 "scrub (securely wipe) a device",
2743 This command writes patterns over C<device> to make data retrieval
2746 It is an interface to the L<scrub(1)> program. See that
2747 manual page for more details.");
2749 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2750 [InitBasicFS, Always, TestRun (
2751 [["write_file"; "/file"; "content"; "0"];
2752 ["scrub_file"; "/file"]])],
2753 "scrub (securely wipe) a file",
2755 This command writes patterns over a file to make data retrieval
2758 The file is I<removed> after scrubbing.
2760 It is an interface to the L<scrub(1)> program. See that
2761 manual page for more details.");
2763 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2764 [], (* XXX needs testing *)
2765 "scrub (securely wipe) free space",
2767 This command creates the directory C<dir> and then fills it
2768 with files until the filesystem is full, and scrubs the files
2769 as for C<guestfs_scrub_file>, and deletes them.
2770 The intention is to scrub any free space on the partition
2773 It is an interface to the L<scrub(1)> program. See that
2774 manual page for more details.");
2776 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2777 [InitBasicFS, Always, TestRun (
2779 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2780 "create a temporary directory",
2782 This command creates a temporary directory. The
2783 C<template> parameter should be a full pathname for the
2784 temporary directory name with the final six characters being
2787 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2788 the second one being suitable for Windows filesystems.
2790 The name of the temporary directory that was created
2793 The temporary directory is created with mode 0700
2794 and is owned by root.
2796 The caller is responsible for deleting the temporary
2797 directory and its contents after use.
2799 See also: L<mkdtemp(3)>");
2801 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2802 [InitISOFS, Always, TestOutputInt (
2803 [["wc_l"; "/10klines"]], 10000)],
2804 "count lines in a file",
2806 This command counts the lines in a file, using the
2807 C<wc -l> external command.");
2809 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2810 [InitISOFS, Always, TestOutputInt (
2811 [["wc_w"; "/10klines"]], 10000)],
2812 "count words in a file",
2814 This command counts the words in a file, using the
2815 C<wc -w> external command.");
2817 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2818 [InitISOFS, Always, TestOutputInt (
2819 [["wc_c"; "/100kallspaces"]], 102400)],
2820 "count characters in a file",
2822 This command counts the characters in a file, using the
2823 C<wc -c> external command.");
2825 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2826 [InitISOFS, Always, TestOutputList (
2827 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2828 "return first 10 lines of a file",
2830 This command returns up to the first 10 lines of a file as
2831 a list of strings.");
2833 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2834 [InitISOFS, Always, TestOutputList (
2835 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2836 InitISOFS, Always, TestOutputList (
2837 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2838 InitISOFS, Always, TestOutputList (
2839 [["head_n"; "0"; "/10klines"]], [])],
2840 "return first N lines of a file",
2842 If the parameter C<nrlines> is a positive number, this returns the first
2843 C<nrlines> lines of the file C<path>.
2845 If the parameter C<nrlines> is a negative number, this returns lines
2846 from the file C<path>, excluding the last C<nrlines> lines.
2848 If the parameter C<nrlines> is zero, this returns an empty list.");
2850 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2851 [InitISOFS, Always, TestOutputList (
2852 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2853 "return last 10 lines of a file",
2855 This command returns up to the last 10 lines of a file as
2856 a list of strings.");
2858 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2859 [InitISOFS, Always, TestOutputList (
2860 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2861 InitISOFS, Always, TestOutputList (
2862 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2863 InitISOFS, Always, TestOutputList (
2864 [["tail_n"; "0"; "/10klines"]], [])],
2865 "return last N lines of a file",
2867 If the parameter C<nrlines> is a positive number, this returns the last
2868 C<nrlines> lines of the file C<path>.
2870 If the parameter C<nrlines> is a negative number, this returns lines
2871 from the file C<path>, starting with the C<-nrlines>th line.
2873 If the parameter C<nrlines> is zero, this returns an empty list.");
2875 ("df", (RString "output", []), 125, [],
2876 [], (* XXX Tricky to test because it depends on the exact format
2877 * of the 'df' command and other imponderables.
2879 "report file system disk space usage",
2881 This command runs the C<df> command to report disk space used.
2883 This command is mostly useful for interactive sessions. It
2884 is I<not> intended that you try to parse the output string.
2885 Use C<statvfs> from programs.");
2887 ("df_h", (RString "output", []), 126, [],
2888 [], (* XXX Tricky to test because it depends on the exact format
2889 * of the 'df' command and other imponderables.
2891 "report file system disk space usage (human readable)",
2893 This command runs the C<df -h> command to report disk space used
2894 in human-readable format.
2896 This command is mostly useful for interactive sessions. It
2897 is I<not> intended that you try to parse the output string.
2898 Use C<statvfs> from programs.");
2900 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2901 [InitISOFS, Always, TestOutputInt (
2902 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2903 "estimate file space usage",
2905 This command runs the C<du -s> command to estimate file space
2908 C<path> can be a file or a directory. If C<path> is a directory
2909 then the estimate includes the contents of the directory and all
2910 subdirectories (recursively).
2912 The result is the estimated size in I<kilobytes>
2913 (ie. units of 1024 bytes).");
2915 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2916 [InitISOFS, Always, TestOutputList (
2917 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2918 "list files in an initrd",
2920 This command lists out files contained in an initrd.
2922 The files are listed without any initial C</> character. The
2923 files are listed in the order they appear (not necessarily
2924 alphabetical). Directory names are listed as separate items.
2926 Old Linux kernels (2.4 and earlier) used a compressed ext2
2927 filesystem as initrd. We I<only> support the newer initramfs
2928 format (compressed cpio files).");
2930 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2932 "mount a file using the loop device",
2934 This command lets you mount C<file> (a filesystem image
2935 in a file) on a mount point. It is entirely equivalent to
2936 the command C<mount -o loop file mountpoint>.");
2938 ("mkswap", (RErr, [Device "device"]), 130, [],
2939 [InitEmpty, Always, TestRun (
2940 [["part_disk"; "/dev/sda"; "mbr"];
2941 ["mkswap"; "/dev/sda1"]])],
2942 "create a swap partition",
2944 Create a swap partition on C<device>.");
2946 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2947 [InitEmpty, Always, TestRun (
2948 [["part_disk"; "/dev/sda"; "mbr"];
2949 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2950 "create a swap partition with a label",
2952 Create a swap partition on C<device> with label C<label>.
2954 Note that you cannot attach a swap label to a block device
2955 (eg. C</dev/sda>), just to a partition. This appears to be
2956 a limitation of the kernel or swap tools.");
2958 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2959 (let uuid = uuidgen () in
2960 [InitEmpty, Always, TestRun (
2961 [["part_disk"; "/dev/sda"; "mbr"];
2962 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2963 "create a swap partition with an explicit UUID",
2965 Create a swap partition on C<device> with UUID C<uuid>.");
2967 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2968 [InitBasicFS, Always, TestOutputStruct (
2969 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2970 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2971 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2972 InitBasicFS, Always, TestOutputStruct (
2973 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2974 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2975 "make block, character or FIFO devices",
2977 This call creates block or character special devices, or
2978 named pipes (FIFOs).
2980 The C<mode> parameter should be the mode, using the standard
2981 constants. C<devmajor> and C<devminor> are the
2982 device major and minor numbers, only used when creating block
2983 and character special devices.");
2985 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2986 [InitBasicFS, Always, TestOutputStruct (
2987 [["mkfifo"; "0o777"; "/node"];
2988 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2989 "make FIFO (named pipe)",
2991 This call creates a FIFO (named pipe) called C<path> with
2992 mode C<mode>. It is just a convenient wrapper around
2993 C<guestfs_mknod>.");
2995 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2996 [InitBasicFS, Always, TestOutputStruct (
2997 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2998 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2999 "make block device node",
3001 This call creates a block device node called C<path> with
3002 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3003 It is just a convenient wrapper around C<guestfs_mknod>.");
3005 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3006 [InitBasicFS, Always, TestOutputStruct (
3007 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3008 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3009 "make char device node",
3011 This call creates a char device node called C<path> with
3012 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3013 It is just a convenient wrapper around C<guestfs_mknod>.");
3015 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3016 [], (* XXX umask is one of those stateful things that we should
3017 * reset between each test.
3019 "set file mode creation mask (umask)",
3021 This function sets the mask used for creating new files and
3022 device nodes to C<mask & 0777>.
3024 Typical umask values would be C<022> which creates new files
3025 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3026 C<002> which creates new files with permissions like
3027 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3029 The default umask is C<022>. This is important because it
3030 means that directories and device nodes will be created with
3031 C<0644> or C<0755> mode even if you specify C<0777>.
3033 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3035 This call returns the previous umask.");
3037 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3039 "read directories entries",
3041 This returns the list of directory entries in directory C<dir>.
3043 All entries in the directory are returned, including C<.> and
3044 C<..>. The entries are I<not> sorted, but returned in the same
3045 order as the underlying filesystem.
3047 Also this call returns basic file type information about each
3048 file. The C<ftyp> field will contain one of the following characters:
3086 The L<readdir(3)> returned a C<d_type> field with an
3091 This function is primarily intended for use by programs. To
3092 get a simple list of names, use C<guestfs_ls>. To get a printable
3093 directory for human consumption, use C<guestfs_ll>.");
3095 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3097 "create partitions on a block device",
3099 This is a simplified interface to the C<guestfs_sfdisk>
3100 command, where partition sizes are specified in megabytes
3101 only (rounded to the nearest cylinder) and you don't need
3102 to specify the cyls, heads and sectors parameters which
3103 were rarely if ever used anyway.
3105 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3106 and C<guestfs_part_disk>");
3108 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3110 "determine file type inside a compressed file",
3112 This command runs C<file> after first decompressing C<path>
3115 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3117 Since 1.0.63, use C<guestfs_file> instead which can now
3118 process compressed files.");
3120 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3122 "list extended attributes of a file or directory",
3124 This call lists the extended attributes of the file or directory
3127 At the system call level, this is a combination of the
3128 L<listxattr(2)> and L<getxattr(2)> calls.
3130 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3132 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3134 "list extended attributes of a file or directory",
3136 This is the same as C<guestfs_getxattrs>, but if C<path>
3137 is a symbolic link, then it returns the extended attributes
3138 of the link itself.");
3140 ("setxattr", (RErr, [String "xattr";
3141 String "val"; Int "vallen"; (* will be BufferIn *)
3142 Pathname "path"]), 143, [Optional "linuxxattrs"],
3144 "set extended attribute of a file or directory",
3146 This call sets the extended attribute named C<xattr>
3147 of the file C<path> to the value C<val> (of length C<vallen>).
3148 The value is arbitrary 8 bit data.
3150 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3152 ("lsetxattr", (RErr, [String "xattr";
3153 String "val"; Int "vallen"; (* will be BufferIn *)
3154 Pathname "path"]), 144, [Optional "linuxxattrs"],
3156 "set extended attribute of a file or directory",
3158 This is the same as C<guestfs_setxattr>, but if C<path>
3159 is a symbolic link, then it sets an extended attribute
3160 of the link itself.");
3162 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3164 "remove extended attribute of a file or directory",
3166 This call removes the extended attribute named C<xattr>
3167 of the file C<path>.
3169 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3171 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3173 "remove extended attribute of a file or directory",
3175 This is the same as C<guestfs_removexattr>, but if C<path>
3176 is a symbolic link, then it removes an extended attribute
3177 of the link itself.");
3179 ("mountpoints", (RHashtable "mps", []), 147, [],
3183 This call is similar to C<guestfs_mounts>. That call returns
3184 a list of devices. This one returns a hash table (map) of
3185 device name to directory where the device is mounted.");
3187 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3188 (* This is a special case: while you would expect a parameter
3189 * of type "Pathname", that doesn't work, because it implies
3190 * NEED_ROOT in the generated calling code in stubs.c, and
3191 * this function cannot use NEED_ROOT.
3194 "create a mountpoint",
3196 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3197 specialized calls that can be used to create extra mountpoints
3198 before mounting the first filesystem.
3200 These calls are I<only> necessary in some very limited circumstances,
3201 mainly the case where you want to mount a mix of unrelated and/or
3202 read-only filesystems together.
3204 For example, live CDs often contain a \"Russian doll\" nest of
3205 filesystems, an ISO outer layer, with a squashfs image inside, with
3206 an ext2/3 image inside that. You can unpack this as follows
3209 add-ro Fedora-11-i686-Live.iso
3212 mkmountpoint /squash
3215 mount-loop /cd/LiveOS/squashfs.img /squash
3216 mount-loop /squash/LiveOS/ext3fs.img /ext3
3218 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3220 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3222 "remove a mountpoint",
3224 This calls removes a mountpoint that was previously created
3225 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3226 for full details.");
3228 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3229 [InitISOFS, Always, TestOutputBuffer (
3230 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3233 This calls returns the contents of the file C<path> as a
3236 Unlike C<guestfs_cat>, this function can correctly
3237 handle files that contain embedded ASCII NUL characters.
3238 However unlike C<guestfs_download>, this function is limited
3239 in the total size of file that can be handled.");
3241 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3242 [InitISOFS, Always, TestOutputList (
3243 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3244 InitISOFS, Always, TestOutputList (
3245 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3246 "return lines matching a pattern",
3248 This calls the external C<grep> program and returns the
3251 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3252 [InitISOFS, Always, TestOutputList (
3253 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254 "return lines matching a pattern",
3256 This calls the external C<egrep> program and returns the
3259 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3260 [InitISOFS, Always, TestOutputList (
3261 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3262 "return lines matching a pattern",
3264 This calls the external C<fgrep> program and returns the
3267 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3268 [InitISOFS, Always, TestOutputList (
3269 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270 "return lines matching a pattern",
3272 This calls the external C<grep -i> program and returns the
3275 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3276 [InitISOFS, Always, TestOutputList (
3277 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278 "return lines matching a pattern",
3280 This calls the external C<egrep -i> program and returns the
3283 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3284 [InitISOFS, Always, TestOutputList (
3285 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3286 "return lines matching a pattern",
3288 This calls the external C<fgrep -i> program and returns the
3291 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3292 [InitISOFS, Always, TestOutputList (
3293 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294 "return lines matching a pattern",
3296 This calls the external C<zgrep> program and returns the
3299 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3300 [InitISOFS, Always, TestOutputList (
3301 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302 "return lines matching a pattern",
3304 This calls the external C<zegrep> program and returns the
3307 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3308 [InitISOFS, Always, TestOutputList (
3309 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3310 "return lines matching a pattern",
3312 This calls the external C<zfgrep> program and returns the
3315 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3316 [InitISOFS, Always, TestOutputList (
3317 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318 "return lines matching a pattern",
3320 This calls the external C<zgrep -i> program and returns the
3323 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3324 [InitISOFS, Always, TestOutputList (
3325 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326 "return lines matching a pattern",
3328 This calls the external C<zegrep -i> program and returns the
3331 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3332 [InitISOFS, Always, TestOutputList (
3333 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3334 "return lines matching a pattern",
3336 This calls the external C<zfgrep -i> program and returns the
3339 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3340 [InitISOFS, Always, TestOutput (
3341 [["realpath"; "/../directory"]], "/directory")],
3342 "canonicalized absolute pathname",
3344 Return the canonicalized absolute pathname of C<path>. The
3345 returned path has no C<.>, C<..> or symbolic link path elements.");
3347 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3348 [InitBasicFS, Always, TestOutputStruct (
3351 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3352 "create a hard link",
3354 This command creates a hard link using the C<ln> command.");
3356 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3357 [InitBasicFS, Always, TestOutputStruct (
3360 ["ln_f"; "/a"; "/b"];
3361 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3362 "create a hard link",
3364 This command creates a hard link using the C<ln -f> command.
3365 The C<-f> option removes the link (C<linkname>) if it exists already.");
3367 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3368 [InitBasicFS, Always, TestOutputStruct (
3370 ["ln_s"; "a"; "/b"];
3371 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3372 "create a symbolic link",
3374 This command creates a symbolic link using the C<ln -s> command.");
3376 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3377 [InitBasicFS, Always, TestOutput (
3378 [["mkdir_p"; "/a/b"];
3379 ["touch"; "/a/b/c"];
3380 ["ln_sf"; "../d"; "/a/b/c"];
3381 ["readlink"; "/a/b/c"]], "../d")],
3382 "create a symbolic link",
3384 This command creates a symbolic link using the C<ln -sf> command,
3385 The C<-f> option removes the link (C<linkname>) if it exists already.");
3387 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3388 [] (* XXX tested above *),
3389 "read the target of a symbolic link",
3391 This command reads the target of a symbolic link.");
3393 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3394 [InitBasicFS, Always, TestOutputStruct (
3395 [["fallocate"; "/a"; "1000000"];
3396 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3397 "preallocate a file in the guest filesystem",
3399 This command preallocates a file (containing zero bytes) named
3400 C<path> of size C<len> bytes. If the file exists already, it
3403 Do not confuse this with the guestfish-specific
3404 C<alloc> command which allocates a file in the host and
3405 attaches it as a device.");
3407 ("swapon_device", (RErr, [Device "device"]), 170, [],
3408 [InitPartition, Always, TestRun (
3409 [["mkswap"; "/dev/sda1"];
3410 ["swapon_device"; "/dev/sda1"];
3411 ["swapoff_device"; "/dev/sda1"]])],
3412 "enable swap on device",
3414 This command enables the libguestfs appliance to use the
3415 swap device or partition named C<device>. The increased
3416 memory is made available for all commands, for example
3417 those run using C<guestfs_command> or C<guestfs_sh>.
3419 Note that you should not swap to existing guest swap
3420 partitions unless you know what you are doing. They may
3421 contain hibernation information, or other information that
3422 the guest doesn't want you to trash. You also risk leaking
3423 information about the host to the guest this way. Instead,
3424 attach a new host device to the guest and swap on that.");
3426 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3427 [], (* XXX tested by swapon_device *)
3428 "disable swap on device",
3430 This command disables the libguestfs appliance swap
3431 device or partition named C<device>.
3432 See C<guestfs_swapon_device>.");
3434 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3435 [InitBasicFS, Always, TestRun (
3436 [["fallocate"; "/swap"; "8388608"];
3437 ["mkswap_file"; "/swap"];
3438 ["swapon_file"; "/swap"];
3439 ["swapoff_file"; "/swap"]])],
3440 "enable swap on file",
3442 This command enables swap to a file.
3443 See C<guestfs_swapon_device> for other notes.");
3445 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3446 [], (* XXX tested by swapon_file *)
3447 "disable swap on file",
3449 This command disables the libguestfs appliance swap on file.");
3451 ("swapon_label", (RErr, [String "label"]), 174, [],
3452 [InitEmpty, Always, TestRun (
3453 [["part_disk"; "/dev/sdb"; "mbr"];
3454 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3455 ["swapon_label"; "swapit"];
3456 ["swapoff_label"; "swapit"];
3457 ["zero"; "/dev/sdb"];
3458 ["blockdev_rereadpt"; "/dev/sdb"]])],
3459 "enable swap on labeled swap partition",
3461 This command enables swap to a labeled swap partition.
3462 See C<guestfs_swapon_device> for other notes.");
3464 ("swapoff_label", (RErr, [String "label"]), 175, [],
3465 [], (* XXX tested by swapon_label *)
3466 "disable swap on labeled swap partition",
3468 This command disables the libguestfs appliance swap on
3469 labeled swap partition.");
3471 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3472 (let uuid = uuidgen () in
3473 [InitEmpty, Always, TestRun (
3474 [["mkswap_U"; uuid; "/dev/sdb"];
3475 ["swapon_uuid"; uuid];
3476 ["swapoff_uuid"; uuid]])]),
3477 "enable swap on swap partition by UUID",
3479 This command enables swap to a swap partition with the given UUID.
3480 See C<guestfs_swapon_device> for other notes.");
3482 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3483 [], (* XXX tested by swapon_uuid *)
3484 "disable swap on swap partition by UUID",
3486 This command disables the libguestfs appliance swap partition
3487 with the given UUID.");
3489 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3490 [InitBasicFS, Always, TestRun (
3491 [["fallocate"; "/swap"; "8388608"];
3492 ["mkswap_file"; "/swap"]])],
3493 "create a swap file",
3497 This command just writes a swap file signature to an existing
3498 file. To create the file itself, use something like C<guestfs_fallocate>.");
3500 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3501 [InitISOFS, Always, TestRun (
3502 [["inotify_init"; "0"]])],
3503 "create an inotify handle",
3505 This command creates a new inotify handle.
3506 The inotify subsystem can be used to notify events which happen to
3507 objects in the guest filesystem.
3509 C<maxevents> is the maximum number of events which will be
3510 queued up between calls to C<guestfs_inotify_read> or
3511 C<guestfs_inotify_files>.
3512 If this is passed as C<0>, then the kernel (or previously set)
3513 default is used. For Linux 2.6.29 the default was 16384 events.
3514 Beyond this limit, the kernel throws away events, but records
3515 the fact that it threw them away by setting a flag
3516 C<IN_Q_OVERFLOW> in the returned structure list (see
3517 C<guestfs_inotify_read>).
3519 Before any events are generated, you have to add some
3520 watches to the internal watch list. See:
3521 C<guestfs_inotify_add_watch>,
3522 C<guestfs_inotify_rm_watch> and
3523 C<guestfs_inotify_watch_all>.
3525 Queued up events should be read periodically by calling
3526 C<guestfs_inotify_read>
3527 (or C<guestfs_inotify_files> which is just a helpful
3528 wrapper around C<guestfs_inotify_read>). If you don't
3529 read the events out often enough then you risk the internal
3532 The handle should be closed after use by calling
3533 C<guestfs_inotify_close>. This also removes any
3534 watches automatically.
3536 See also L<inotify(7)> for an overview of the inotify interface
3537 as exposed by the Linux kernel, which is roughly what we expose
3538 via libguestfs. Note that there is one global inotify handle
3539 per libguestfs instance.");
3541 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3542 [InitBasicFS, Always, TestOutputList (
3543 [["inotify_init"; "0"];
3544 ["inotify_add_watch"; "/"; "1073741823"];
3547 ["inotify_files"]], ["a"; "b"])],
3548 "add an inotify watch",
3550 Watch C<path> for the events listed in C<mask>.
3552 Note that if C<path> is a directory then events within that
3553 directory are watched, but this does I<not> happen recursively
3554 (in subdirectories).
3556 Note for non-C or non-Linux callers: the inotify events are
3557 defined by the Linux kernel ABI and are listed in
3558 C</usr/include/sys/inotify.h>.");
3560 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3562 "remove an inotify watch",
3564 Remove a previously defined inotify watch.
3565 See C<guestfs_inotify_add_watch>.");
3567 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3569 "return list of inotify events",
3571 Return the complete queue of events that have happened
3572 since the previous read call.
3574 If no events have happened, this returns an empty list.
3576 I<Note>: In order to make sure that all events have been
3577 read, you must call this function repeatedly until it
3578 returns an empty list. The reason is that the call will
3579 read events up to the maximum appliance-to-host message
3580 size and leave remaining events in the queue.");
3582 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3584 "return list of watched files that had events",
3586 This function is a helpful wrapper around C<guestfs_inotify_read>
3587 which just returns a list of pathnames of objects that were
3588 touched. The returned pathnames are sorted and deduplicated.");
3590 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3592 "close the inotify handle",
3594 This closes the inotify handle which was previously
3595 opened by inotify_init. It removes all watches, throws
3596 away any pending events, and deallocates all resources.");
3598 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3600 "set SELinux security context",
3602 This sets the SELinux security context of the daemon
3603 to the string C<context>.
3605 See the documentation about SELINUX in L<guestfs(3)>.");
3607 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3609 "get SELinux security context",
3611 This gets the SELinux security context of the daemon.
3613 See the documentation about SELINUX in L<guestfs(3)>,
3614 and C<guestfs_setcon>");
3616 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3617 [InitEmpty, Always, TestOutput (
3618 [["part_disk"; "/dev/sda"; "mbr"];
3619 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3620 ["mount_options"; ""; "/dev/sda1"; "/"];
3621 ["write_file"; "/new"; "new file contents"; "0"];
3622 ["cat"; "/new"]], "new file contents")],
3623 "make a filesystem with block size",
3625 This call is similar to C<guestfs_mkfs>, but it allows you to
3626 control the block size of the resulting filesystem. Supported
3627 block sizes depend on the filesystem type, but typically they
3628 are C<1024>, C<2048> or C<4096> only.");
3630 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3631 [InitEmpty, Always, TestOutput (
3632 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3633 ["mke2journal"; "4096"; "/dev/sda1"];
3634 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3635 ["mount_options"; ""; "/dev/sda2"; "/"];
3636 ["write_file"; "/new"; "new file contents"; "0"];
3637 ["cat"; "/new"]], "new file contents")],
3638 "make ext2/3/4 external journal",
3640 This creates an ext2 external journal on C<device>. It is equivalent
3643 mke2fs -O journal_dev -b blocksize device");
3645 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3646 [InitEmpty, Always, TestOutput (
3647 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3648 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3649 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3650 ["mount_options"; ""; "/dev/sda2"; "/"];
3651 ["write_file"; "/new"; "new file contents"; "0"];
3652 ["cat"; "/new"]], "new file contents")],
3653 "make ext2/3/4 external journal with label",
3655 This creates an ext2 external journal on C<device> with label C<label>.");
3657 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3658 (let uuid = uuidgen () in
3659 [InitEmpty, Always, TestOutput (
3660 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3661 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3662 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3663 ["mount_options"; ""; "/dev/sda2"; "/"];
3664 ["write_file"; "/new"; "new file contents"; "0"];
3665 ["cat"; "/new"]], "new file contents")]),
3666 "make ext2/3/4 external journal with UUID",
3668 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3670 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3672 "make ext2/3/4 filesystem with external journal",
3674 This creates an ext2/3/4 filesystem on C<device> with
3675 an external journal on C<journal>. It is equivalent
3678 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3680 See also C<guestfs_mke2journal>.");
3682 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3684 "make ext2/3/4 filesystem with external journal",
3686 This creates an ext2/3/4 filesystem on C<device> with
3687 an external journal on the journal labeled C<label>.
3689 See also C<guestfs_mke2journal_L>.");
3691 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3693 "make ext2/3/4 filesystem with external journal",
3695 This creates an ext2/3/4 filesystem on C<device> with
3696 an external journal on the journal with UUID C<uuid>.
3698 See also C<guestfs_mke2journal_U>.");
3700 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3701 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3702 "load a kernel module",
3704 This loads a kernel module in the appliance.
3706 The kernel module must have been whitelisted when libguestfs
3707 was built (see C<appliance/kmod.whitelist.in> in the source).");
3709 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3710 [InitNone, Always, TestOutput (
3711 [["echo_daemon"; "This is a test"]], "This is a test"
3713 "echo arguments back to the client",
3715 This command concatenate the list of C<words> passed with single spaces between
3716 them and returns the resulting string.
3718 You can use this command to test the connection through to the daemon.
3720 See also C<guestfs_ping_daemon>.");
3722 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3723 [], (* There is a regression test for this. *)
3724 "find all files and directories, returning NUL-separated list",
3726 This command lists out all files and directories, recursively,
3727 starting at C<directory>, placing the resulting list in the
3728 external file called C<files>.
3730 This command works the same way as C<guestfs_find> with the
3731 following exceptions:
3737 The resulting list is written to an external file.
3741 Items (filenames) in the result are separated
3742 by C<\\0> characters. See L<find(1)> option I<-print0>.
3746 This command is not limited in the number of names that it
3751 The result list is not sorted.
3755 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3756 [InitISOFS, Always, TestOutput (
3757 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3758 InitISOFS, Always, TestOutput (
3759 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3760 InitISOFS, Always, TestOutput (
3761 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3762 InitISOFS, Always, TestLastFail (
3763 [["case_sensitive_path"; "/Known-1/"]]);
3764 InitBasicFS, Always, TestOutput (
3766 ["mkdir"; "/a/bbb"];
3767 ["touch"; "/a/bbb/c"];
3768 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3769 InitBasicFS, Always, TestOutput (
3771 ["mkdir"; "/a/bbb"];
3772 ["touch"; "/a/bbb/c"];
3773 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3774 InitBasicFS, Always, TestLastFail (
3776 ["mkdir"; "/a/bbb"];
3777 ["touch"; "/a/bbb/c"];
3778 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3779 "return true path on case-insensitive filesystem",
3781 This can be used to resolve case insensitive paths on
3782 a filesystem which is case sensitive. The use case is
3783 to resolve paths which you have read from Windows configuration
3784 files or the Windows Registry, to the true path.
3786 The command handles a peculiarity of the Linux ntfs-3g
3787 filesystem driver (and probably others), which is that although
3788 the underlying filesystem is case-insensitive, the driver
3789 exports the filesystem to Linux as case-sensitive.
3791 One consequence of this is that special directories such
3792 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3793 (or other things) depending on the precise details of how
3794 they were created. In Windows itself this would not be
3797 Bug or feature? You decide:
3798 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3800 This function resolves the true case of each element in the
3801 path and returns the case-sensitive path.
3803 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3804 might return C<\"/WINDOWS/system32\"> (the exact return value
3805 would depend on details of how the directories were originally
3806 created under Windows).
3809 This function does not handle drive names, backslashes etc.
3811 See also C<guestfs_realpath>.");
3813 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3814 [InitBasicFS, Always, TestOutput (
3815 [["vfs_type"; "/dev/sda1"]], "ext2")],
3816 "get the Linux VFS type corresponding to a mounted device",
3818 This command gets the block device type corresponding to
3819 a mounted device called C<device>.
3821 Usually the result is the name of the Linux VFS module that
3822 is used to mount this device (probably determined automatically
3823 if you used the C<guestfs_mount> call).");
3825 ("truncate", (RErr, [Pathname "path"]), 199, [],
3826 [InitBasicFS, Always, TestOutputStruct (
3827 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3828 ["truncate"; "/test"];
3829 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3830 "truncate a file to zero size",
3832 This command truncates C<path> to a zero-length file. The
3833 file must exist already.");
3835 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3836 [InitBasicFS, Always, TestOutputStruct (
3837 [["touch"; "/test"];
3838 ["truncate_size"; "/test"; "1000"];
3839 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3840 "truncate a file to a particular size",
3842 This command truncates C<path> to size C<size> bytes. The file
3843 must exist already. If the file is smaller than C<size> then
3844 the file is extended to the required size with null bytes.");
3846 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3847 [InitBasicFS, Always, TestOutputStruct (
3848 [["touch"; "/test"];
3849 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3850 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3851 "set timestamp of a file with nanosecond precision",
3853 This command sets the timestamps of a file with nanosecond
3856 C<atsecs, atnsecs> are the last access time (atime) in secs and
3857 nanoseconds from the epoch.
3859 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3860 secs and nanoseconds from the epoch.
3862 If the C<*nsecs> field contains the special value C<-1> then
3863 the corresponding timestamp is set to the current time. (The
3864 C<*secs> field is ignored in this case).
3866 If the C<*nsecs> field contains the special value C<-2> then
3867 the corresponding timestamp is left unchanged. (The
3868 C<*secs> field is ignored in this case).");
3870 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3871 [InitBasicFS, Always, TestOutputStruct (
3872 [["mkdir_mode"; "/test"; "0o111"];
3873 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3874 "create a directory with a particular mode",
3876 This command creates a directory, setting the initial permissions
3877 of the directory to C<mode>. See also C<guestfs_mkdir>.");
3879 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3881 "change file owner and group",
3883 Change the file owner to C<owner> and group to C<group>.
3884 This is like C<guestfs_chown> but if C<path> is a symlink then
3885 the link itself is changed, not the target.
3887 Only numeric uid and gid are supported. If you want to use
3888 names, you will need to locate and parse the password file
3889 yourself (Augeas support makes this relatively easy).");
3891 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3893 "lstat on multiple files",
3895 This call allows you to perform the C<guestfs_lstat> operation
3896 on multiple files, where all files are in the directory C<path>.
3897 C<names> is the list of files from this directory.
3899 On return you get a list of stat structs, with a one-to-one
3900 correspondence to the C<names> list. If any name did not exist
3901 or could not be lstat'd, then the C<ino> field of that structure
3904 This call is intended for programs that want to efficiently
3905 list a directory contents without making many round-trips.
3906 See also C<guestfs_lxattrlist> for a similarly efficient call
3907 for getting extended attributes. Very long directory listings
3908 might cause the protocol message size to be exceeded, causing
3909 this call to fail. The caller must split up such requests
3910 into smaller groups of names.");
3912 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3914 "lgetxattr on multiple files",
3916 This call allows you to get the extended attributes
3917 of multiple files, where all files are in the directory C<path>.
3918 C<names> is the list of files from this directory.
3920 On return you get a flat list of xattr structs which must be
3921 interpreted sequentially. The first xattr struct always has a zero-length
3922 C<attrname>. C<attrval> in this struct is zero-length
3923 to indicate there was an error doing C<lgetxattr> for this
3924 file, I<or> is a C string which is a decimal number
3925 (the number of following attributes for this file, which could
3926 be C<\"0\">). Then after the first xattr struct are the
3927 zero or more attributes for the first named file.
3928 This repeats for the second and subsequent files.
3930 This call is intended for programs that want to efficiently
3931 list a directory contents without making many round-trips.
3932 See also C<guestfs_lstatlist> for a similarly efficient call
3933 for getting standard stats. Very long directory listings
3934 might cause the protocol message size to be exceeded, causing
3935 this call to fail. The caller must split up such requests
3936 into smaller groups of names.");
3938 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3940 "readlink on multiple files",
3942 This call allows you to do a C<readlink> operation
3943 on multiple files, where all files are in the directory C<path>.
3944 C<names> is the list of files from this directory.
3946 On return you get a list of strings, with a one-to-one
3947 correspondence to the C<names> list. Each string is the
3948 value of the symbol link.
3950 If the C<readlink(2)> operation fails on any name, then
3951 the corresponding result string is the empty string C<\"\">.
3952 However the whole operation is completed even if there
3953 were C<readlink(2)> errors, and so you can call this
3954 function with names where you don't know if they are
3955 symbolic links already (albeit slightly less efficient).
3957 This call is intended for programs that want to efficiently
3958 list a directory contents without making many round-trips.
3959 Very long directory listings might cause the protocol
3960 message size to be exceeded, causing
3961 this call to fail. The caller must split up such requests
3962 into smaller groups of names.");
3964 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3965 [InitISOFS, Always, TestOutputBuffer (
3966 [["pread"; "/known-4"; "1"; "3"]], "\n");
3967 InitISOFS, Always, TestOutputBuffer (
3968 [["pread"; "/empty"; "0"; "100"]], "")],
3969 "read part of a file",
3971 This command lets you read part of a file. It reads C<count>
3972 bytes of the file, starting at C<offset>, from file C<path>.
3974 This may read fewer bytes than requested. For further details
3975 see the L<pread(2)> system call.");
3977 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3978 [InitEmpty, Always, TestRun (
3979 [["part_init"; "/dev/sda"; "gpt"]])],
3980 "create an empty partition table",
3982 This creates an empty partition table on C<device> of one of the
3983 partition types listed below. Usually C<parttype> should be
3984 either C<msdos> or C<gpt> (for large disks).
3986 Initially there are no partitions. Following this, you should
3987 call C<guestfs_part_add> for each partition required.
3989 Possible values for C<parttype> are:
3993 =item B<efi> | B<gpt>
3995 Intel EFI / GPT partition table.
3997 This is recommended for >= 2 TB partitions that will be accessed
3998 from Linux and Intel-based Mac OS X. It also has limited backwards
3999 compatibility with the C<mbr> format.
4001 =item B<mbr> | B<msdos>
4003 The standard PC \"Master Boot Record\" (MBR) format used
4004 by MS-DOS and Windows. This partition type will B<only> work
4005 for device sizes up to 2 TB. For large disks we recommend
4010 Other partition table types that may work but are not
4019 =item B<amiga> | B<rdb>
4021 Amiga \"Rigid Disk Block\" format.
4029 DASD, used on IBM mainframes.
4037 Old Mac partition format. Modern Macs use C<gpt>.
4041 NEC PC-98 format, common in Japan apparently.
4049 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4050 [InitEmpty, Always, TestRun (
4051 [["part_init"; "/dev/sda"; "mbr"];
4052 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4053 InitEmpty, Always, TestRun (
4054 [["part_init"; "/dev/sda"; "gpt"];
4055 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4056 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4057 InitEmpty, Always, TestRun (
4058 [["part_init"; "/dev/sda"; "mbr"];
4059 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4060 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4061 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4062 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4063 "add a partition to the device",
4065 This command adds a partition to C<device>. If there is no partition
4066 table on the device, call C<guestfs_part_init> first.
4068 The C<prlogex> parameter is the type of partition. Normally you
4069 should pass C<p> or C<primary> here, but MBR partition tables also
4070 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4073 C<startsect> and C<endsect> are the start and end of the partition
4074 in I<sectors>. C<endsect> may be negative, which means it counts
4075 backwards from the end of the disk (C<-1> is the last sector).
4077 Creating a partition which covers the whole disk is not so easy.
4078 Use C<guestfs_part_disk> to do that.");
4080 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4081 [InitEmpty, Always, TestRun (
4082 [["part_disk"; "/dev/sda"; "mbr"]]);
4083 InitEmpty, Always, TestRun (
4084 [["part_disk"; "/dev/sda"; "gpt"]])],
4085 "partition whole disk with a single primary partition",
4087 This command is simply a combination of C<guestfs_part_init>
4088 followed by C<guestfs_part_add> to create a single primary partition
4089 covering the whole disk.
4091 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4092 but other possible values are described in C<guestfs_part_init>.");
4094 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4095 [InitEmpty, Always, TestRun (
4096 [["part_disk"; "/dev/sda"; "mbr"];
4097 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4098 "make a partition bootable",
4100 This sets the bootable flag on partition numbered C<partnum> on
4101 device C<device>. Note that partitions are numbered from 1.
4103 The bootable flag is used by some operating systems (notably
4104 Windows) to determine which partition to boot from. It is by
4105 no means universally recognized.");
4107 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4108 [InitEmpty, Always, TestRun (
4109 [["part_disk"; "/dev/sda"; "gpt"];
4110 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4111 "set partition name",
4113 This sets the partition name on partition numbered C<partnum> on
4114 device C<device>. Note that partitions are numbered from 1.
4116 The partition name can only be set on certain types of partition
4117 table. This works on C<gpt> but not on C<mbr> partitions.");
4119 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4120 [], (* XXX Add a regression test for this. *)
4121 "list partitions on a device",
4123 This command parses the partition table on C<device> and
4124 returns the list of partitions found.
4126 The fields in the returned structure are:
4132 Partition number, counting from 1.
4136 Start of the partition I<in bytes>. To get sectors you have to
4137 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4141 End of the partition in bytes.
4145 Size of the partition in bytes.
4149 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4150 [InitEmpty, Always, TestOutput (
4151 [["part_disk"; "/dev/sda"; "gpt"];
4152 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4153 "get the partition table type",
4155 This command examines the partition table on C<device> and
4156 returns the partition table type (format) being used.
4158 Common return values include: C<msdos> (a DOS/Windows style MBR
4159 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4160 values are possible, although unusual. See C<guestfs_part_init>
4163 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4164 [InitBasicFS, Always, TestOutputBuffer (
4165 [["fill"; "0x63"; "10"; "/test"];
4166 ["read_file"; "/test"]], "cccccccccc")],
4167 "fill a file with octets",
4169 This command creates a new file called C<path>. The initial
4170 content of the file is C<len> octets of C<c>, where C<c>
4171 must be a number in the range C<[0..255]>.
4173 To fill a file with zero bytes (sparsely), it is
4174 much more efficient to use C<guestfs_truncate_size>.");
4176 ("available", (RErr, [StringList "groups"]), 216, [],
4177 [InitNone, Always, TestRun [["available"; ""]]],
4178 "test availability of some parts of the API",
4180 This command is used to check the availability of some
4181 groups of functionality in the appliance, which not all builds of
4182 the libguestfs appliance will be able to provide.
4184 The libguestfs groups, and the functions that those
4185 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4187 The argument C<groups> is a list of group names, eg:
4188 C<[\"inotify\", \"augeas\"]> would check for the availability of
4189 the Linux inotify functions and Augeas (configuration file
4192 The command returns no error if I<all> requested groups are available.
4194 It fails with an error if one or more of the requested
4195 groups is unavailable in the appliance.
4197 If an unknown group name is included in the
4198 list of groups then an error is always returned.
4206 You must call C<guestfs_launch> before calling this function.
4208 The reason is because we don't know what groups are
4209 supported by the appliance/daemon until it is running and can
4214 If a group of functions is available, this does not necessarily
4215 mean that they will work. You still have to check for errors
4216 when calling individual API functions even if they are
4221 It is usually the job of distro packagers to build
4222 complete functionality into the libguestfs appliance.
4223 Upstream libguestfs, if built from source with all
4224 requirements satisfied, will support everything.
4228 This call was added in version C<1.0.80>. In previous
4229 versions of libguestfs all you could do would be to speculatively
4230 execute a command to find out if the daemon implemented it.
4231 See also C<guestfs_version>.
4235 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4236 [InitBasicFS, Always, TestOutputBuffer (
4237 [["write_file"; "/src"; "hello, world"; "0"];
4238 ["dd"; "/src"; "/dest"];
4239 ["read_file"; "/dest"]], "hello, world")],
4240 "copy from source to destination using dd",
4242 This command copies from one source device or file C<src>
4243 to another destination device or file C<dest>. Normally you
4244 would use this to copy to or from a device or partition, for
4245 example to duplicate a filesystem.
4247 If the destination is a device, it must be as large or larger
4248 than the source file or device, otherwise the copy will fail.
4249 This command cannot do partial copies (see C<guestfs_copy_size>).");
4251 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4252 [InitBasicFS, Always, TestOutputInt (
4253 [["write_file"; "/file"; "hello, world"; "0"];
4254 ["filesize"; "/file"]], 12)],
4255 "return the size of the file in bytes",
4257 This command returns the size of C<file> in bytes.
4259 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4260 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4261 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4263 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4264 [InitBasicFSonLVM, Always, TestOutputList (
4265 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4266 ["lvs"]], ["/dev/VG/LV2"])],
4267 "rename an LVM logical volume",
4269 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4271 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4272 [InitBasicFSonLVM, Always, TestOutputList (
4274 ["vg_activate"; "false"; "VG"];
4275 ["vgrename"; "VG"; "VG2"];
4276 ["vg_activate"; "true"; "VG2"];
4277 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4278 ["vgs"]], ["VG2"])],
4279 "rename an LVM volume group",
4281 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4283 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4284 [InitISOFS, Always, TestOutputBuffer (
4285 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4286 "list the contents of a single file in an initrd",
4288 This command unpacks the file C<filename> from the initrd file
4289 called C<initrdpath>. The filename must be given I<without> the
4290 initial C</> character.
4292 For example, in guestfish you could use the following command
4293 to examine the boot script (usually called C</init>)
4294 contained in a Linux initrd or initramfs image:
4296 initrd-cat /boot/initrd-<version>.img init
4298 See also C<guestfs_initrd_list>.");
4300 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4302 "get the UUID of a physical volume",
4304 This command returns the UUID of the LVM PV C<device>.");
4306 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4308 "get the UUID of a volume group",
4310 This command returns the UUID of the LVM VG named C<vgname>.");
4312 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4314 "get the UUID of a logical volume",
4316 This command returns the UUID of the LVM LV C<device>.");
4318 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4320 "get the PV UUIDs containing the volume group",
4322 Given a VG called C<vgname>, this returns the UUIDs of all
4323 the physical volumes that this volume group resides on.
4325 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4326 calls to associate physical volumes and volume groups.
4328 See also C<guestfs_vglvuuids>.");
4330 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4332 "get the LV UUIDs of all LVs in the volume group",
4334 Given a VG called C<vgname>, this returns the UUIDs of all
4335 the logical volumes created in this volume group.
4337 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4338 calls to associate logical volumes and volume groups.
4340 See also C<guestfs_vgpvuuids>.");
4342 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4343 [InitBasicFS, Always, TestOutputBuffer (
4344 [["write_file"; "/src"; "hello, world"; "0"];
4345 ["copy_size"; "/src"; "/dest"; "5"];
4346 ["read_file"; "/dest"]], "hello")],
4347 "copy size bytes from source to destination using dd",
4349 This command copies exactly C<size> bytes from one source device
4350 or file C<src> to another destination device or file C<dest>.
4352 Note this will fail if the source is too short or if the destination
4353 is not large enough.");
4355 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4356 [InitBasicFSonLVM, Always, TestRun (
4357 [["zero_device"; "/dev/VG/LV"]])],
4358 "write zeroes to an entire device",
4360 This command writes zeroes over the entire C<device>. Compare
4361 with C<guestfs_zero> which just zeroes the first few blocks of
4364 ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4365 [InitBasicFS, Always, TestOutput (
4366 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4367 ["cat"; "/hello"]], "hello\n")],
4368 "unpack compressed tarball to directory",
4370 This command uploads and unpacks local file C<tarball> (an
4371 I<xz compressed> tar file) into C<directory>.");
4373 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4375 "pack directory into compressed tarball",
4377 This command packs the contents of C<directory> and downloads
4378 it to local file C<tarball> (as an xz compressed tar archive).");
4380 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4382 "resize an NTFS filesystem",
4384 This command resizes an NTFS filesystem, expanding or
4385 shrinking it to the size of the underlying device.
4386 See also L<ntfsresize(8)>.");
4388 ("vgscan", (RErr, []), 232, [],
4389 [InitEmpty, Always, TestRun (
4391 "rescan for LVM physical volumes, volume groups and logical volumes",
4393 This rescans all block devices and rebuilds the list of LVM
4394 physical volumes, volume groups and logical volumes.");
4396 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4397 [InitEmpty, Always, TestRun (
4398 [["part_init"; "/dev/sda"; "mbr"];
4399 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4400 ["part_del"; "/dev/sda"; "1"]])],
4401 "delete a partition",
4403 This command deletes the partition numbered C<partnum> on C<device>.
4405 Note that in the case of MBR partitioning, deleting an
4406 extended partition also deletes any logical partitions
4409 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4410 [InitEmpty, Always, TestOutputTrue (
4411 [["part_init"; "/dev/sda"; "mbr"];
4412 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4413 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4414 ["part_get_bootable"; "/dev/sda"; "1"]])],
4415 "return true if a partition is bootable",
4417 This command returns true if the partition C<partnum> on
4418 C<device> has the bootable flag set.
4420 See also C<guestfs_part_set_bootable>.");
4422 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4423 [InitEmpty, Always, TestOutputInt (
4424 [["part_init"; "/dev/sda"; "mbr"];
4425 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4426 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4427 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4428 "get the MBR type byte (ID byte) from a partition",
4430 Returns the MBR type byte (also known as the ID byte) from
4431 the numbered partition C<partnum>.
4433 Note that only MBR (old DOS-style) partitions have type bytes.
4434 You will get undefined results for other partition table
4435 types (see C<guestfs_part_get_parttype>).");
4437 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4438 [], (* tested by part_get_mbr_id *)
4439 "set the MBR type byte (ID byte) of a partition",
4441 Sets the MBR type byte (also known as the ID byte) of
4442 the numbered partition C<partnum> to C<idbyte>. Note
4443 that the type bytes quoted in most documentation are
4444 in fact hexadecimal numbers, but usually documented
4445 without any leading \"0x\" which might be confusing.
4447 Note that only MBR (old DOS-style) partitions have type bytes.
4448 You will get undefined results for other partition table
4449 types (see C<guestfs_part_get_parttype>).");
4451 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4452 [InitISOFS, Always, TestOutput (
4453 [["checksum_device"; "md5"; "/dev/sdd"]],
4454 (Digest.to_hex (Digest.file "images/test.iso")))],
4455 "compute MD5, SHAx or CRC checksum of the contents of a device",
4457 This call computes the MD5, SHAx or CRC checksum of the
4458 contents of the device named C<device>. For the types of
4459 checksums supported see the C<guestfs_checksum> command.");
4461 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4462 [InitNone, Always, TestRun (
4463 [["part_disk"; "/dev/sda"; "mbr"];
4464 ["pvcreate"; "/dev/sda1"];
4465 ["vgcreate"; "VG"; "/dev/sda1"];
4466 ["lvcreate"; "LV"; "VG"; "10"];
4467 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4468 "expand an LV to fill free space",
4470 This expands an existing logical volume C<lv> so that it fills
4471 C<pc>% of the remaining free space in the volume group. Commonly
4472 you would call this with pc = 100 which expands the logical volume
4473 as much as possible, using all remaining free space in the volume
4476 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4477 [], (* XXX Augeas code needs tests. *)
4478 "clear Augeas path",
4480 Set the value associated with C<path> to C<NULL>. This
4481 is the same as the L<augtool(1)> C<clear> command.");
4485 let all_functions = non_daemon_functions @ daemon_functions
4487 (* In some places we want the functions to be displayed sorted
4488 * alphabetically, so this is useful:
4490 let all_functions_sorted =
4491 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4492 compare n1 n2) all_functions
4494 (* Field types for structures. *)
4496 | FChar (* C 'char' (really, a 7 bit byte). *)
4497 | FString (* nul-terminated ASCII string, NOT NULL. *)
4498 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4503 | FBytes (* Any int measure that counts bytes. *)
4504 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4505 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4507 (* Because we generate extra parsing code for LVM command line tools,
4508 * we have to pull out the LVM columns separately here.
4518 "pv_attr", FString (* XXX *);
4519 "pv_pe_count", FInt64;
4520 "pv_pe_alloc_count", FInt64;
4523 "pv_mda_count", FInt64;
4524 "pv_mda_free", FBytes;
4525 (* Not in Fedora 10:
4526 "pv_mda_size", FBytes;
4533 "vg_attr", FString (* XXX *);
4536 "vg_sysid", FString;
4537 "vg_extent_size", FBytes;
4538 "vg_extent_count", FInt64;
4539 "vg_free_count", FInt64;
4544 "snap_count", FInt64;
4547 "vg_mda_count", FInt64;
4548 "vg_mda_free", FBytes;
4549 (* Not in Fedora 10:
4550 "vg_mda_size", FBytes;
4556 "lv_attr", FString (* XXX *);
4559 "lv_kernel_major", FInt64;
4560 "lv_kernel_minor", FInt64;
4562 "seg_count", FInt64;
4564 "snap_percent", FOptPercent;
4565 "copy_percent", FOptPercent;
4568 "mirror_log", FString;
4572 (* Names and fields in all structures (in RStruct and RStructList)
4576 (* The old RIntBool return type, only ever used for aug_defnode. Do
4577 * not use this struct in any new code.
4580 "i", FInt32; (* for historical compatibility *)
4581 "b", FInt32; (* for historical compatibility *)
4584 (* LVM PVs, VGs, LVs. *)
4585 "lvm_pv", lvm_pv_cols;
4586 "lvm_vg", lvm_vg_cols;
4587 "lvm_lv", lvm_lv_cols;
4589 (* Column names and types from stat structures.
4590 * NB. Can't use things like 'st_atime' because glibc header files
4591 * define some of these as macros. Ugh.
4622 (* Column names in dirent structure. *)
4625 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4630 (* Version numbers. *)
4638 (* Extended attribute. *)
4640 "attrname", FString;
4644 (* Inotify events. *)
4648 "in_cookie", FUInt32;
4652 (* Partition table entry. *)
4655 "part_start", FBytes;
4657 "part_size", FBytes;
4659 ] (* end of structs *)
4661 (* Ugh, Java has to be different ..
4662 * These names are also used by the Haskell bindings.
4664 let java_structs = [
4665 "int_bool", "IntBool";
4670 "statvfs", "StatVFS";
4672 "version", "Version";
4674 "inotify_event", "INotifyEvent";
4675 "partition", "Partition";
4678 (* What structs are actually returned. *)
4679 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4681 (* Returns a list of RStruct/RStructList structs that are returned
4682 * by any function. Each element of returned list is a pair:
4684 * (structname, RStructOnly)
4685 * == there exists function which returns RStruct (_, structname)
4686 * (structname, RStructListOnly)
4687 * == there exists function which returns RStructList (_, structname)
4688 * (structname, RStructAndList)
4689 * == there are functions returning both RStruct (_, structname)
4690 * and RStructList (_, structname)
4692 let rstructs_used_by functions =
4693 (* ||| is a "logical OR" for rstructs_used_t *)
4697 | _, RStructAndList -> RStructAndList
4698 | RStructOnly, RStructListOnly
4699 | RStructListOnly, RStructOnly -> RStructAndList
4700 | RStructOnly, RStructOnly -> RStructOnly
4701 | RStructListOnly, RStructListOnly -> RStructListOnly
4704 let h = Hashtbl.create 13 in
4706 (* if elem->oldv exists, update entry using ||| operator,
4707 * else just add elem->newv to the hash
4709 let update elem newv =
4710 try let oldv = Hashtbl.find h elem in
4711 Hashtbl.replace h elem (newv ||| oldv)
4712 with Not_found -> Hashtbl.add h elem newv
4716 fun (_, style, _, _, _, _, _) ->
4717 match fst style with
4718 | RStruct (_, structname) -> update structname RStructOnly
4719 | RStructList (_, structname) -> update structname RStructListOnly
4723 (* return key->values as a list of (key,value) *)
4724 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4726 (* Used for testing language bindings. *)
4728 | CallString of string
4729 | CallOptString of string option
4730 | CallStringList of string list
4732 | CallInt64 of int64
4735 (* Used to memoize the result of pod2text. *)
4736 let pod2text_memo_filename = "src/.pod2text.data"
4737 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4739 let chan = open_in pod2text_memo_filename in
4740 let v = input_value chan in
4744 _ -> Hashtbl.create 13
4745 let pod2text_memo_updated () =
4746 let chan = open_out pod2text_memo_filename in
4747 output_value chan pod2text_memo;
4750 (* Useful functions.
4751 * Note we don't want to use any external OCaml libraries which
4752 * makes this a bit harder than it should be.
4754 module StringMap = Map.Make (String)
4756 let failwithf fs = ksprintf failwith fs
4758 let unique = let i = ref 0 in fun () -> incr i; !i
4760 let replace_char s c1 c2 =
4761 let s2 = String.copy s in
4762 let r = ref false in
4763 for i = 0 to String.length s2 - 1 do
4764 if String.unsafe_get s2 i = c1 then (
4765 String.unsafe_set s2 i c2;
4769 if not !r then s else s2
4773 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4775 let triml ?(test = isspace) str =
4777 let n = ref (String.length str) in
4778 while !n > 0 && test str.[!i]; do
4783 else String.sub str !i !n
4785 let trimr ?(test = isspace) str =
4786 let n = ref (String.length str) in
4787 while !n > 0 && test str.[!n-1]; do
4790 if !n = String.length str then str
4791 else String.sub str 0 !n
4793 let trim ?(test = isspace) str =
4794 trimr ~test (triml ~test str)
4796 let rec find s sub =
4797 let len = String.length s in
4798 let sublen = String.length sub in
4800 if i <= len-sublen then (
4802 if j < sublen then (
4803 if s.[i+j] = sub.[j] then loop2 (j+1)
4809 if r = -1 then loop (i+1) else r
4815 let rec replace_str s s1 s2 =
4816 let len = String.length s in
4817 let sublen = String.length s1 in
4818 let i = find s s1 in
4821 let s' = String.sub s 0 i in
4822 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4823 s' ^ s2 ^ replace_str s'' s1 s2
4826 let rec string_split sep str =
4827 let len = String.length str in
4828 let seplen = String.length sep in
4829 let i = find str sep in
4830 if i = -1 then [str]
4832 let s' = String.sub str 0 i in
4833 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4834 s' :: string_split sep s''
4837 let files_equal n1 n2 =
4838 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4839 match Sys.command cmd with
4842 | i -> failwithf "%s: failed with error code %d" cmd i
4844 let rec filter_map f = function
4848 | Some y -> y :: filter_map f xs
4849 | None -> filter_map f xs
4851 let rec find_map f = function
4852 | [] -> raise Not_found
4856 | None -> find_map f xs
4859 let rec loop i = function
4861 | x :: xs -> f i x; loop (i+1) xs
4866 let rec loop i = function
4868 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4872 let count_chars c str =
4873 let count = ref 0 in
4874 for i = 0 to String.length str - 1 do
4875 if c = String.unsafe_get str i then incr count
4879 let name_of_argt = function
4880 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4881 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4882 | FileIn n | FileOut n -> n
4884 let java_name_of_struct typ =
4885 try List.assoc typ java_structs
4888 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4890 let cols_of_struct typ =
4891 try List.assoc typ structs
4893 failwithf "cols_of_struct: unknown struct %s" typ
4895 let seq_of_test = function
4896 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4897 | TestOutputListOfDevices (s, _)
4898 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4899 | TestOutputTrue s | TestOutputFalse s
4900 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4901 | TestOutputStruct (s, _)
4902 | TestLastFail s -> s
4904 (* Handling for function flags. *)
4905 let protocol_limit_warning =
4906 "Because of the message protocol, there is a transfer limit
4907 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4909 let danger_will_robinson =
4910 "B<This command is dangerous. Without careful use you
4911 can easily destroy all your data>."
4913 let deprecation_notice flags =
4916 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4918 sprintf "This function is deprecated.
4919 In new code, use the C<%s> call instead.
4921 Deprecated functions will not be removed from the API, but the
4922 fact that they are deprecated indicates that there are problems
4923 with correct use of these functions." alt in
4928 (* Create list of optional groups. *)
4930 let h = Hashtbl.create 13 in
4932 fun (name, _, _, flags, _, _, _) ->
4936 let names = try Hashtbl.find h group with Not_found -> [] in
4937 Hashtbl.replace h group (name :: names)
4941 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4944 fun group -> group, List.sort compare (Hashtbl.find h group)
4946 List.sort (fun x y -> compare (fst x) (fst y)) groups
4948 (* Check function names etc. for consistency. *)
4949 let check_functions () =
4950 let contains_uppercase str =
4951 let len = String.length str in
4953 if i >= len then false
4956 if c >= 'A' && c <= 'Z' then true
4963 (* Check function names. *)
4965 fun (name, _, _, _, _, _, _) ->
4966 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4967 failwithf "function name %s does not need 'guestfs' prefix" name;
4969 failwithf "function name is empty";
4970 if name.[0] < 'a' || name.[0] > 'z' then
4971 failwithf "function name %s must start with lowercase a-z" name;
4972 if String.contains name '-' then
4973 failwithf "function name %s should not contain '-', use '_' instead."
4977 (* Check function parameter/return names. *)
4979 fun (name, style, _, _, _, _, _) ->
4980 let check_arg_ret_name n =
4981 if contains_uppercase n then
4982 failwithf "%s param/ret %s should not contain uppercase chars"
4984 if String.contains n '-' || String.contains n '_' then
4985 failwithf "%s param/ret %s should not contain '-' or '_'"
4988 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;
4989 if n = "int" || n = "char" || n = "short" || n = "long" then
4990 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4991 if n = "i" || n = "n" then
4992 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4993 if n = "argv" || n = "args" then
4994 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4996 (* List Haskell, OCaml and C keywords here.
4997 * http://www.haskell.org/haskellwiki/Keywords
4998 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4999 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5000 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5001 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5002 * Omitting _-containing words, since they're handled above.
5003 * Omitting the OCaml reserved word, "val", is ok,
5004 * and saves us from renaming several parameters.
5007 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5008 "char"; "class"; "const"; "constraint"; "continue"; "data";
5009 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5010 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5011 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5012 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5013 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5015 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5016 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5017 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5018 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5019 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5020 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5021 "volatile"; "when"; "where"; "while";
5023 if List.mem n reserved then
5024 failwithf "%s has param/ret using reserved word %s" name n;
5027 (match fst style with
5029 | RInt n | RInt64 n | RBool n
5030 | RConstString n | RConstOptString n | RString n
5031 | RStringList n | RStruct (n, _) | RStructList (n, _)
5032 | RHashtable n | RBufferOut n ->
5033 check_arg_ret_name n
5035 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5038 (* Check short descriptions. *)
5040 fun (name, _, _, _, _, shortdesc, _) ->
5041 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5042 failwithf "short description of %s should begin with lowercase." name;
5043 let c = shortdesc.[String.length shortdesc-1] in
5044 if c = '\n' || c = '.' then
5045 failwithf "short description of %s should not end with . or \\n." name
5048 (* Check long dscriptions. *)
5050 fun (name, _, _, _, _, _, longdesc) ->
5051 if longdesc.[String.length longdesc-1] = '\n' then
5052 failwithf "long description of %s should not end with \\n." name
5055 (* Check proc_nrs. *)
5057 fun (name, _, proc_nr, _, _, _, _) ->
5058 if proc_nr <= 0 then
5059 failwithf "daemon function %s should have proc_nr > 0" name
5063 fun (name, _, proc_nr, _, _, _, _) ->
5064 if proc_nr <> -1 then
5065 failwithf "non-daemon function %s should have proc_nr -1" name
5066 ) non_daemon_functions;
5069 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5072 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5073 let rec loop = function
5076 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5078 | (name1,nr1) :: (name2,nr2) :: _ ->
5079 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5087 (* Ignore functions that have no tests. We generate a
5088 * warning when the user does 'make check' instead.
5090 | name, _, _, _, [], _, _ -> ()
5091 | name, _, _, _, tests, _, _ ->
5095 match seq_of_test test with
5097 failwithf "%s has a test containing an empty sequence" name
5098 | cmds -> List.map List.hd cmds
5100 let funcs = List.flatten funcs in
5102 let tested = List.mem name funcs in
5105 failwithf "function %s has tests but does not test itself" name
5108 (* 'pr' prints to the current output file. *)
5109 let chan = ref Pervasives.stdout
5114 let i = count_chars '\n' str in
5115 lines := !lines + i;
5116 output_string !chan str
5119 let copyright_years =
5120 let this_year = 1900 + (localtime (time ())).tm_year in
5121 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5123 (* Generate a header block in a number of standard styles. *)
5124 type comment_style =
5125 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5126 type license = GPLv2plus | LGPLv2plus
5128 let generate_header ?(extra_inputs = []) comment license =
5129 let inputs = "src/generator.ml" :: extra_inputs in
5130 let c = match comment with
5131 | CStyle -> pr "/* "; " *"
5132 | CPlusPlusStyle -> pr "// "; "//"
5133 | HashStyle -> pr "# "; "#"
5134 | OCamlStyle -> pr "(* "; " *"
5135 | HaskellStyle -> pr "{- "; " " in
5136 pr "libguestfs generated file\n";
5137 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5138 List.iter (pr "%s %s\n" c) inputs;
5139 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5141 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5145 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5146 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5147 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5148 pr "%s (at your option) any later version.\n" c;
5150 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5151 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5152 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5153 pr "%s GNU General Public License for more details.\n" c;
5155 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5156 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5157 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5160 pr "%s This library is free software; you can redistribute it and/or\n" c;
5161 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5162 pr "%s License as published by the Free Software Foundation; either\n" c;
5163 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5165 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5166 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5167 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5168 pr "%s Lesser General Public License for more details.\n" c;
5170 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5171 pr "%s License along with this library; if not, write to the Free Software\n" c;
5172 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5175 | CStyle -> pr " */\n"
5178 | OCamlStyle -> pr " *)\n"
5179 | HaskellStyle -> pr "-}\n"
5183 (* Start of main code generation functions below this line. *)
5185 (* Generate the pod documentation for the C API. *)
5186 let rec generate_actions_pod () =
5188 fun (shortname, style, _, flags, _, _, longdesc) ->
5189 if not (List.mem NotInDocs flags) then (
5190 let name = "guestfs_" ^ shortname in
5191 pr "=head2 %s\n\n" name;
5193 generate_prototype ~extern:false ~handle:"handle" name style;
5195 pr "%s\n\n" longdesc;
5196 (match fst style with
5198 pr "This function returns 0 on success or -1 on error.\n\n"
5200 pr "On error this function returns -1.\n\n"
5202 pr "On error this function returns -1.\n\n"
5204 pr "This function returns a C truth value on success or -1 on error.\n\n"
5206 pr "This function returns a string, or NULL on error.
5207 The string is owned by the guest handle and must I<not> be freed.\n\n"
5208 | RConstOptString _ ->
5209 pr "This function returns a string which may be NULL.
5210 There is way to return an error from this function.
5211 The string is owned by the guest handle and must I<not> be freed.\n\n"
5213 pr "This function returns a string, or NULL on error.
5214 I<The caller must free the returned string after use>.\n\n"
5216 pr "This function returns a NULL-terminated array of strings
5217 (like L<environ(3)>), or NULL if there was an error.
5218 I<The caller must free the strings and the array after use>.\n\n"
5219 | RStruct (_, typ) ->
5220 pr "This function returns a C<struct guestfs_%s *>,
5221 or NULL if there was an error.
5222 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5223 | RStructList (_, typ) ->
5224 pr "This function returns a C<struct guestfs_%s_list *>
5225 (see E<lt>guestfs-structs.hE<gt>),
5226 or NULL if there was an error.
5227 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5229 pr "This function returns a NULL-terminated array of
5230 strings, or NULL if there was an error.
5231 The array of strings will always have length C<2n+1>, where
5232 C<n> keys and values alternate, followed by the trailing NULL entry.
5233 I<The caller must free the strings and the array after use>.\n\n"
5235 pr "This function returns a buffer, or NULL on error.
5236 The size of the returned buffer is written to C<*size_r>.
5237 I<The caller must free the returned buffer after use>.\n\n"
5239 if List.mem ProtocolLimitWarning flags then
5240 pr "%s\n\n" protocol_limit_warning;
5241 if List.mem DangerWillRobinson flags then
5242 pr "%s\n\n" danger_will_robinson;
5243 match deprecation_notice flags with
5245 | Some txt -> pr "%s\n\n" txt
5247 ) all_functions_sorted
5249 and generate_structs_pod () =
5250 (* Structs documentation. *)
5253 pr "=head2 guestfs_%s\n" typ;
5255 pr " struct guestfs_%s {\n" typ;
5258 | name, FChar -> pr " char %s;\n" name
5259 | name, FUInt32 -> pr " uint32_t %s;\n" name
5260 | name, FInt32 -> pr " int32_t %s;\n" name
5261 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5262 | name, FInt64 -> pr " int64_t %s;\n" name
5263 | name, FString -> pr " char *%s;\n" name
5265 pr " /* The next two fields describe a byte array. */\n";
5266 pr " uint32_t %s_len;\n" name;
5267 pr " char *%s;\n" name
5269 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5270 pr " char %s[32];\n" name
5271 | name, FOptPercent ->
5272 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5273 pr " float %s;\n" name
5277 pr " struct guestfs_%s_list {\n" typ;
5278 pr " uint32_t len; /* Number of elements in list. */\n";
5279 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5282 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5283 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5288 and generate_availability_pod () =
5289 (* Availability documentation. *)
5293 fun (group, functions) ->
5294 pr "=item B<%s>\n" group;
5296 pr "The following functions:\n";
5297 List.iter (pr "L</guestfs_%s>\n") functions;
5303 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5304 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5306 * We have to use an underscore instead of a dash because otherwise
5307 * rpcgen generates incorrect code.
5309 * This header is NOT exported to clients, but see also generate_structs_h.
5311 and generate_xdr () =
5312 generate_header CStyle LGPLv2plus;
5314 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5315 pr "typedef string str<>;\n";
5318 (* Internal structures. *)
5322 pr "struct guestfs_int_%s {\n" typ;
5324 | name, FChar -> pr " char %s;\n" name
5325 | name, FString -> pr " string %s<>;\n" name
5326 | name, FBuffer -> pr " opaque %s<>;\n" name
5327 | name, FUUID -> pr " opaque %s[32];\n" name
5328 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5329 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5330 | name, FOptPercent -> pr " float %s;\n" name
5334 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5339 fun (shortname, style, _, _, _, _, _) ->
5340 let name = "guestfs_" ^ shortname in
5342 (match snd style with
5345 pr "struct %s_args {\n" name;
5348 | Pathname n | Device n | Dev_or_Path n | String n ->
5349 pr " string %s<>;\n" n
5350 | OptString n -> pr " str *%s;\n" n
5351 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5352 | Bool n -> pr " bool %s;\n" n
5353 | Int n -> pr " int %s;\n" n
5354 | Int64 n -> pr " hyper %s;\n" n
5355 | FileIn _ | FileOut _ -> ()
5359 (match fst style with
5362 pr "struct %s_ret {\n" name;
5366 pr "struct %s_ret {\n" name;
5367 pr " hyper %s;\n" n;
5370 pr "struct %s_ret {\n" name;
5373 | RConstString _ | RConstOptString _ ->
5374 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5376 pr "struct %s_ret {\n" name;
5377 pr " string %s<>;\n" n;
5380 pr "struct %s_ret {\n" name;
5381 pr " str %s<>;\n" n;
5383 | RStruct (n, typ) ->
5384 pr "struct %s_ret {\n" name;
5385 pr " guestfs_int_%s %s;\n" typ n;
5387 | RStructList (n, typ) ->
5388 pr "struct %s_ret {\n" name;
5389 pr " guestfs_int_%s_list %s;\n" typ n;
5392 pr "struct %s_ret {\n" name;
5393 pr " str %s<>;\n" n;
5396 pr "struct %s_ret {\n" name;
5397 pr " opaque %s<>;\n" n;
5402 (* Table of procedure numbers. *)
5403 pr "enum guestfs_procedure {\n";
5405 fun (shortname, _, proc_nr, _, _, _, _) ->
5406 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5408 pr " GUESTFS_PROC_NR_PROCS\n";
5412 (* Having to choose a maximum message size is annoying for several
5413 * reasons (it limits what we can do in the API), but it (a) makes
5414 * the protocol a lot simpler, and (b) provides a bound on the size
5415 * of the daemon which operates in limited memory space.
5417 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5420 (* Message header, etc. *)
5422 /* The communication protocol is now documented in the guestfs(3)
5426 const GUESTFS_PROGRAM = 0x2000F5F5;
5427 const GUESTFS_PROTOCOL_VERSION = 1;
5429 /* These constants must be larger than any possible message length. */
5430 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5431 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5433 enum guestfs_message_direction {
5434 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5435 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5438 enum guestfs_message_status {
5439 GUESTFS_STATUS_OK = 0,
5440 GUESTFS_STATUS_ERROR = 1
5443 const GUESTFS_ERROR_LEN = 256;
5445 struct guestfs_message_error {
5446 string error_message<GUESTFS_ERROR_LEN>;
5449 struct guestfs_message_header {
5450 unsigned prog; /* GUESTFS_PROGRAM */
5451 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5452 guestfs_procedure proc; /* GUESTFS_PROC_x */
5453 guestfs_message_direction direction;
5454 unsigned serial; /* message serial number */
5455 guestfs_message_status status;
5458 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5460 struct guestfs_chunk {
5461 int cancel; /* if non-zero, transfer is cancelled */
5462 /* data size is 0 bytes if the transfer has finished successfully */
5463 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5467 (* Generate the guestfs-structs.h file. *)
5468 and generate_structs_h () =
5469 generate_header CStyle LGPLv2plus;
5471 (* This is a public exported header file containing various
5472 * structures. The structures are carefully written to have
5473 * exactly the same in-memory format as the XDR structures that
5474 * we use on the wire to the daemon. The reason for creating
5475 * copies of these structures here is just so we don't have to
5476 * export the whole of guestfs_protocol.h (which includes much
5477 * unrelated and XDR-dependent stuff that we don't want to be
5478 * public, or required by clients).
5480 * To reiterate, we will pass these structures to and from the
5481 * client with a simple assignment or memcpy, so the format
5482 * must be identical to what rpcgen / the RFC defines.
5485 (* Public structures. *)
5488 pr "struct guestfs_%s {\n" typ;
5491 | name, FChar -> pr " char %s;\n" name
5492 | name, FString -> pr " char *%s;\n" name
5494 pr " uint32_t %s_len;\n" name;
5495 pr " char *%s;\n" name
5496 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5497 | name, FUInt32 -> pr " uint32_t %s;\n" name
5498 | name, FInt32 -> pr " int32_t %s;\n" name
5499 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5500 | name, FInt64 -> pr " int64_t %s;\n" name
5501 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5505 pr "struct guestfs_%s_list {\n" typ;
5506 pr " uint32_t len;\n";
5507 pr " struct guestfs_%s *val;\n" typ;
5510 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5511 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5515 (* Generate the guestfs-actions.h file. *)
5516 and generate_actions_h () =
5517 generate_header CStyle LGPLv2plus;
5519 fun (shortname, style, _, _, _, _, _) ->
5520 let name = "guestfs_" ^ shortname in
5521 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5525 (* Generate the guestfs-internal-actions.h file. *)
5526 and generate_internal_actions_h () =
5527 generate_header CStyle LGPLv2plus;
5529 fun (shortname, style, _, _, _, _, _) ->
5530 let name = "guestfs__" ^ shortname in
5531 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5533 ) non_daemon_functions
5535 (* Generate the client-side dispatch stubs. *)
5536 and generate_client_actions () =
5537 generate_header CStyle LGPLv2plus;
5544 #include <inttypes.h>
5546 #include \"guestfs.h\"
5547 #include \"guestfs-internal.h\"
5548 #include \"guestfs-internal-actions.h\"
5549 #include \"guestfs_protocol.h\"
5551 #define error guestfs_error
5552 //#define perrorf guestfs_perrorf
5553 #define safe_malloc guestfs_safe_malloc
5554 #define safe_realloc guestfs_safe_realloc
5555 //#define safe_strdup guestfs_safe_strdup
5556 #define safe_memdup guestfs_safe_memdup
5558 /* Check the return message from a call for validity. */
5560 check_reply_header (guestfs_h *g,
5561 const struct guestfs_message_header *hdr,
5562 unsigned int proc_nr, unsigned int serial)
5564 if (hdr->prog != GUESTFS_PROGRAM) {
5565 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5568 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5569 error (g, \"wrong protocol version (%%d/%%d)\",
5570 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5573 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5574 error (g, \"unexpected message direction (%%d/%%d)\",
5575 hdr->direction, GUESTFS_DIRECTION_REPLY);
5578 if (hdr->proc != proc_nr) {
5579 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5582 if (hdr->serial != serial) {
5583 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5590 /* Check we are in the right state to run a high-level action. */
5592 check_state (guestfs_h *g, const char *caller)
5594 if (!guestfs__is_ready (g)) {
5595 if (guestfs__is_config (g) || guestfs__is_launching (g))
5596 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5599 error (g, \"%%s called from the wrong state, %%d != READY\",
5600 caller, guestfs__get_state (g));
5608 (* Generate code to generate guestfish call traces. *)
5609 let trace_call shortname style =
5610 pr " if (guestfs__get_trace (g)) {\n";
5613 List.exists (function
5614 | StringList _ | DeviceList _ -> true
5615 | _ -> false) (snd style) in
5621 pr " printf (\"%s\");\n" shortname;
5624 | String n (* strings *)
5630 (* guestfish doesn't support string escaping, so neither do we *)
5631 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5632 | OptString n -> (* string option *)
5633 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5634 pr " else printf (\" null\");\n"
5636 | DeviceList n -> (* string list *)
5637 pr " putchar (' ');\n";
5638 pr " putchar ('\"');\n";
5639 pr " for (i = 0; %s[i]; ++i) {\n" n;
5640 pr " if (i > 0) putchar (' ');\n";
5641 pr " fputs (%s[i], stdout);\n" n;
5643 pr " putchar ('\"');\n";
5644 | Bool n -> (* boolean *)
5645 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5646 | Int n -> (* int *)
5647 pr " printf (\" %%d\", %s);\n" n
5649 pr " printf (\" %%\" PRIi64, %s);\n" n
5651 pr " putchar ('\\n');\n";
5656 (* For non-daemon functions, generate a wrapper around each function. *)
5658 fun (shortname, style, _, _, _, _, _) ->
5659 let name = "guestfs_" ^ shortname in
5661 generate_prototype ~extern:false ~semicolon:false ~newline:true
5662 ~handle:"g" name style;
5664 trace_call shortname style;
5665 pr " return guestfs__%s " shortname;
5666 generate_c_call_args ~handle:"g" style;
5670 ) non_daemon_functions;
5672 (* Client-side stubs for each function. *)
5674 fun (shortname, style, _, _, _, _, _) ->
5675 let name = "guestfs_" ^ shortname in
5677 (* Generate the action stub. *)
5678 generate_prototype ~extern:false ~semicolon:false ~newline:true
5679 ~handle:"g" name style;
5682 match fst style with
5683 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5684 | RConstString _ | RConstOptString _ ->
5685 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5686 | RString _ | RStringList _
5687 | RStruct _ | RStructList _
5688 | RHashtable _ | RBufferOut _ ->
5693 (match snd style with
5695 | _ -> pr " struct %s_args args;\n" name
5698 pr " guestfs_message_header hdr;\n";
5699 pr " guestfs_message_error err;\n";
5701 match fst style with
5703 | RConstString _ | RConstOptString _ ->
5704 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5706 | RBool _ | RString _ | RStringList _
5707 | RStruct _ | RStructList _
5708 | RHashtable _ | RBufferOut _ ->
5709 pr " struct %s_ret ret;\n" name;
5712 pr " int serial;\n";
5715 trace_call shortname style;
5716 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5717 pr " guestfs___set_busy (g);\n";
5720 (* Send the main header and arguments. *)
5721 (match snd style with
5723 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5724 (String.uppercase shortname)
5728 | Pathname n | Device n | Dev_or_Path n | String n ->
5729 pr " args.%s = (char *) %s;\n" n n
5731 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5732 | StringList n | DeviceList n ->
5733 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5734 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5736 pr " args.%s = %s;\n" n n
5738 pr " args.%s = %s;\n" n n
5740 pr " args.%s = %s;\n" n n
5741 | FileIn _ | FileOut _ -> ()
5743 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5744 (String.uppercase shortname);
5745 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5748 pr " if (serial == -1) {\n";
5749 pr " guestfs___end_busy (g);\n";
5750 pr " return %s;\n" error_code;
5754 (* Send any additional files (FileIn) requested. *)
5755 let need_read_reply_label = ref false in
5759 pr " r = guestfs___send_file (g, %s);\n" n;
5760 pr " if (r == -1) {\n";
5761 pr " guestfs___end_busy (g);\n";
5762 pr " return %s;\n" error_code;
5764 pr " if (r == -2) /* daemon cancelled */\n";
5765 pr " goto read_reply;\n";
5766 need_read_reply_label := true;
5771 (* Wait for the reply from the remote end. *)
5772 if !need_read_reply_label then pr " read_reply:\n";
5773 pr " memset (&hdr, 0, sizeof hdr);\n";
5774 pr " memset (&err, 0, sizeof err);\n";
5775 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5777 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5781 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5784 pr " if (r == -1) {\n";
5785 pr " guestfs___end_busy (g);\n";
5786 pr " return %s;\n" error_code;
5790 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5791 (String.uppercase shortname);
5792 pr " guestfs___end_busy (g);\n";
5793 pr " return %s;\n" error_code;
5797 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5798 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5799 pr " free (err.error_message);\n";
5800 pr " guestfs___end_busy (g);\n";
5801 pr " return %s;\n" error_code;
5805 (* Expecting to receive further files (FileOut)? *)
5809 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5810 pr " guestfs___end_busy (g);\n";
5811 pr " return %s;\n" error_code;
5817 pr " guestfs___end_busy (g);\n";
5819 (match fst style with
5820 | RErr -> pr " return 0;\n"
5821 | RInt n | RInt64 n | RBool n ->
5822 pr " return ret.%s;\n" n
5823 | RConstString _ | RConstOptString _ ->
5824 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5826 pr " return ret.%s; /* caller will free */\n" n
5827 | RStringList n | RHashtable n ->
5828 pr " /* caller will free this, but we need to add a NULL entry */\n";
5829 pr " ret.%s.%s_val =\n" n n;
5830 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5831 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5833 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5834 pr " return ret.%s.%s_val;\n" n n
5836 pr " /* caller will free this */\n";
5837 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5838 | RStructList (n, _) ->
5839 pr " /* caller will free this */\n";
5840 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5842 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5843 pr " * _val might be NULL here. To make the API saner for\n";
5844 pr " * callers, we turn this case into a unique pointer (using\n";
5845 pr " * malloc(1)).\n";
5847 pr " if (ret.%s.%s_len > 0) {\n" n n;
5848 pr " *size_r = ret.%s.%s_len;\n" n n;
5849 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5851 pr " free (ret.%s.%s_val);\n" n n;
5852 pr " char *p = safe_malloc (g, 1);\n";
5853 pr " *size_r = ret.%s.%s_len;\n" n n;
5861 (* Functions to free structures. *)
5862 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5863 pr " * structure format is identical to the XDR format. See note in\n";
5864 pr " * generator.ml.\n";
5871 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5873 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5879 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5881 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5888 (* Generate daemon/actions.h. *)
5889 and generate_daemon_actions_h () =
5890 generate_header CStyle GPLv2plus;
5892 pr "#include \"../src/guestfs_protocol.h\"\n";
5896 fun (name, style, _, _, _, _, _) ->
5898 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5902 (* Generate the linker script which controls the visibility of
5903 * symbols in the public ABI and ensures no other symbols get
5904 * exported accidentally.
5906 and generate_linker_script () =
5907 generate_header HashStyle GPLv2plus;
5912 "guestfs_get_error_handler";
5913 "guestfs_get_out_of_memory_handler";
5914 "guestfs_last_error";
5915 "guestfs_set_error_handler";
5916 "guestfs_set_launch_done_callback";
5917 "guestfs_set_log_message_callback";
5918 "guestfs_set_out_of_memory_handler";
5919 "guestfs_set_subprocess_quit_callback";
5921 (* Unofficial parts of the API: the bindings code use these
5922 * functions, so it is useful to export them.
5924 "guestfs_safe_calloc";
5925 "guestfs_safe_malloc";
5928 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5932 List.map (fun (typ, _) ->
5933 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5936 let globals = List.sort compare (globals @ functions @ structs) in
5940 List.iter (pr " %s;\n") globals;
5947 (* Generate the server-side stubs. *)
5948 and generate_daemon_actions () =
5949 generate_header CStyle GPLv2plus;
5951 pr "#include <config.h>\n";
5953 pr "#include <stdio.h>\n";
5954 pr "#include <stdlib.h>\n";
5955 pr "#include <string.h>\n";
5956 pr "#include <inttypes.h>\n";
5957 pr "#include <rpc/types.h>\n";
5958 pr "#include <rpc/xdr.h>\n";
5960 pr "#include \"daemon.h\"\n";
5961 pr "#include \"c-ctype.h\"\n";
5962 pr "#include \"../src/guestfs_protocol.h\"\n";
5963 pr "#include \"actions.h\"\n";
5967 fun (name, style, _, _, _, _, _) ->
5968 (* Generate server-side stubs. *)
5969 pr "static void %s_stub (XDR *xdr_in)\n" name;
5972 match fst style with
5973 | RErr | RInt _ -> pr " int r;\n"; "-1"
5974 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5975 | RBool _ -> pr " int r;\n"; "-1"
5976 | RConstString _ | RConstOptString _ ->
5977 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5978 | RString _ -> pr " char *r;\n"; "NULL"
5979 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
5980 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
5981 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
5983 pr " size_t size = 1;\n";
5987 (match snd style with
5990 pr " struct guestfs_%s_args args;\n" name;
5993 | Device n | Dev_or_Path n
5996 | OptString n -> pr " char *%s;\n" n
5997 | StringList n | DeviceList n -> pr " char **%s;\n" n
5998 | Bool n -> pr " int %s;\n" n
5999 | Int n -> pr " int %s;\n" n
6000 | Int64 n -> pr " int64_t %s;\n" n
6001 | FileIn _ | FileOut _ -> ()
6006 (match snd style with
6009 pr " memset (&args, 0, sizeof args);\n";
6011 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6012 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6016 pr " char *%s = args.%s;\n" n n
6018 let pr_list_handling_code n =
6019 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6020 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6021 pr " if (%s == NULL) {\n" n;
6022 pr " reply_with_perror (\"realloc\");\n";
6025 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6026 pr " args.%s.%s_val = %s;\n" n n n;
6032 pr " ABS_PATH (%s, goto done);\n" n;
6035 pr " RESOLVE_DEVICE (%s, goto done);\n" n;
6038 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6039 | String n -> pr_args n
6040 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6042 pr_list_handling_code n;
6044 pr_list_handling_code n;
6045 pr " /* Ensure that each is a device,\n";
6046 pr " * and perform device name translation. */\n";
6047 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6048 pr " RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6050 | Bool n -> pr " %s = args.%s;\n" n n
6051 | Int n -> pr " %s = args.%s;\n" n n
6052 | Int64 n -> pr " %s = args.%s;\n" n n
6053 | FileIn _ | FileOut _ -> ()
6059 (* this is used at least for do_equal *)
6060 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6061 (* Emit NEED_ROOT just once, even when there are two or
6062 more Pathname args *)
6063 pr " NEED_ROOT (goto done);\n";
6066 (* Don't want to call the impl with any FileIn or FileOut
6067 * parameters, since these go "outside" the RPC protocol.
6070 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6072 pr " r = do_%s " name;
6073 generate_c_call_args (fst style, args');
6076 (match fst style with
6077 | RErr | RInt _ | RInt64 _ | RBool _
6078 | RConstString _ | RConstOptString _
6079 | RString _ | RStringList _ | RHashtable _
6080 | RStruct (_, _) | RStructList (_, _) ->
6081 pr " if (r == %s)\n" error_code;
6082 pr " /* do_%s has already called reply_with_error */\n" name;
6086 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6087 pr " * an ordinary zero-length buffer), so be careful ...\n";
6089 pr " if (size == 1 && r == %s)\n" error_code;
6090 pr " /* do_%s has already called reply_with_error */\n" name;
6095 (* If there are any FileOut parameters, then the impl must
6096 * send its own reply.
6099 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6101 pr " /* do_%s has already sent a reply */\n" name
6103 match fst style with
6104 | RErr -> pr " reply (NULL, NULL);\n"
6105 | RInt n | RInt64 n | RBool n ->
6106 pr " struct guestfs_%s_ret ret;\n" name;
6107 pr " ret.%s = r;\n" n;
6108 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6110 | RConstString _ | RConstOptString _ ->
6111 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6113 pr " struct guestfs_%s_ret ret;\n" name;
6114 pr " ret.%s = r;\n" n;
6115 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6118 | RStringList n | RHashtable n ->
6119 pr " struct guestfs_%s_ret ret;\n" name;
6120 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6121 pr " ret.%s.%s_val = r;\n" n n;
6122 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6124 pr " free_strings (r);\n"
6126 pr " struct guestfs_%s_ret ret;\n" name;
6127 pr " ret.%s = *r;\n" n;
6128 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6130 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6132 | RStructList (n, _) ->
6133 pr " struct guestfs_%s_ret ret;\n" name;
6134 pr " ret.%s = *r;\n" n;
6135 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6137 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6140 pr " struct guestfs_%s_ret ret;\n" name;
6141 pr " ret.%s.%s_val = r;\n" n n;
6142 pr " ret.%s.%s_len = size;\n" n n;
6143 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6148 (* Free the args. *)
6149 (match snd style with
6154 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6161 (* Dispatch function. *)
6162 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6164 pr " switch (proc_nr) {\n";
6167 fun (name, style, _, _, _, _, _) ->
6168 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6169 pr " %s_stub (xdr_in);\n" name;
6174 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";
6179 (* LVM columns and tokenization functions. *)
6180 (* XXX This generates crap code. We should rethink how we
6186 pr "static const char *lvm_%s_cols = \"%s\";\n"
6187 typ (String.concat "," (List.map fst cols));
6190 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6192 pr " char *tok, *p, *next;\n";
6196 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6199 pr " if (!str) {\n";
6200 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6203 pr " if (!*str || c_isspace (*str)) {\n";
6204 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6209 fun (name, coltype) ->
6210 pr " if (!tok) {\n";
6211 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6214 pr " p = strchrnul (tok, ',');\n";
6215 pr " if (*p) next = p+1; else next = NULL;\n";
6216 pr " *p = '\\0';\n";
6219 pr " r->%s = strdup (tok);\n" name;
6220 pr " if (r->%s == NULL) {\n" name;
6221 pr " perror (\"strdup\");\n";
6225 pr " for (i = j = 0; i < 32; ++j) {\n";
6226 pr " if (tok[j] == '\\0') {\n";
6227 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6229 pr " } else if (tok[j] != '-')\n";
6230 pr " r->%s[i++] = tok[j];\n" name;
6233 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6234 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6238 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6239 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6243 pr " if (tok[0] == '\\0')\n";
6244 pr " r->%s = -1;\n" name;
6245 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6246 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6249 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6250 assert false (* can never be an LVM column *)
6252 pr " tok = next;\n";
6255 pr " if (tok != NULL) {\n";
6256 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6263 pr "guestfs_int_lvm_%s_list *\n" typ;
6264 pr "parse_command_line_%ss (void)\n" typ;
6266 pr " char *out, *err;\n";
6267 pr " char *p, *pend;\n";
6269 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6270 pr " void *newp;\n";
6272 pr " ret = malloc (sizeof *ret);\n";
6273 pr " if (!ret) {\n";
6274 pr " reply_with_perror (\"malloc\");\n";
6275 pr " return NULL;\n";
6278 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6279 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6281 pr " r = command (&out, &err,\n";
6282 pr " \"lvm\", \"%ss\",\n" typ;
6283 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6284 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6285 pr " if (r == -1) {\n";
6286 pr " reply_with_error (\"%%s\", err);\n";
6287 pr " free (out);\n";
6288 pr " free (err);\n";
6289 pr " free (ret);\n";
6290 pr " return NULL;\n";
6293 pr " free (err);\n";
6295 pr " /* Tokenize each line of the output. */\n";
6298 pr " while (p) {\n";
6299 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6300 pr " if (pend) {\n";
6301 pr " *pend = '\\0';\n";
6305 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6308 pr " if (!*p) { /* Empty line? Skip it. */\n";
6313 pr " /* Allocate some space to store this next entry. */\n";
6314 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6315 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6316 pr " if (newp == NULL) {\n";
6317 pr " reply_with_perror (\"realloc\");\n";
6318 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6319 pr " free (ret);\n";
6320 pr " free (out);\n";
6321 pr " return NULL;\n";
6323 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6325 pr " /* Tokenize the next entry. */\n";
6326 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6327 pr " if (r == -1) {\n";
6328 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6329 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6330 pr " free (ret);\n";
6331 pr " free (out);\n";
6332 pr " return NULL;\n";
6339 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6341 pr " free (out);\n";
6342 pr " return ret;\n";
6345 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6347 (* Generate a list of function names, for debugging in the daemon.. *)
6348 and generate_daemon_names () =
6349 generate_header CStyle GPLv2plus;
6351 pr "#include <config.h>\n";
6353 pr "#include \"daemon.h\"\n";
6356 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6357 pr "const char *function_names[] = {\n";
6359 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6363 (* Generate the optional groups for the daemon to implement
6364 * guestfs_available.
6366 and generate_daemon_optgroups_c () =
6367 generate_header CStyle GPLv2plus;
6369 pr "#include <config.h>\n";
6371 pr "#include \"daemon.h\"\n";
6372 pr "#include \"optgroups.h\"\n";
6375 pr "struct optgroup optgroups[] = {\n";
6378 pr " { \"%s\", optgroup_%s_available },\n" group group
6380 pr " { NULL, NULL }\n";
6383 and generate_daemon_optgroups_h () =
6384 generate_header CStyle GPLv2plus;
6388 pr "extern int optgroup_%s_available (void);\n" group
6391 (* Generate the tests. *)
6392 and generate_tests () =
6393 generate_header CStyle GPLv2plus;
6400 #include <sys/types.h>
6403 #include \"guestfs.h\"
6404 #include \"guestfs-internal.h\"
6406 static guestfs_h *g;
6407 static int suppress_error = 0;
6409 static void print_error (guestfs_h *g, void *data, const char *msg)
6411 if (!suppress_error)
6412 fprintf (stderr, \"%%s\\n\", msg);
6415 /* FIXME: nearly identical code appears in fish.c */
6416 static void print_strings (char *const *argv)
6420 for (argc = 0; argv[argc] != NULL; ++argc)
6421 printf (\"\\t%%s\\n\", argv[argc]);
6425 static void print_table (char const *const *argv)
6429 for (i = 0; argv[i] != NULL; i += 2)
6430 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6436 (* Generate a list of commands which are not tested anywhere. *)
6437 pr "static void no_test_warnings (void)\n";
6440 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6442 fun (_, _, _, _, tests, _, _) ->
6443 let tests = filter_map (
6445 | (_, (Always|If _|Unless _), test) -> Some test
6446 | (_, Disabled, _) -> None
6448 let seq = List.concat (List.map seq_of_test tests) in
6449 let cmds_tested = List.map List.hd seq in
6450 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6454 fun (name, _, _, _, _, _, _) ->
6455 if not (Hashtbl.mem hash name) then
6456 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6462 (* Generate the actual tests. Note that we generate the tests
6463 * in reverse order, deliberately, so that (in general) the
6464 * newest tests run first. This makes it quicker and easier to
6469 fun (name, _, _, flags, tests, _, _) ->
6470 mapi (generate_one_test name flags) tests
6471 ) (List.rev all_functions) in
6472 let test_names = List.concat test_names in
6473 let nr_tests = List.length test_names in
6476 int main (int argc, char *argv[])
6479 unsigned long int n_failed = 0;
6480 const char *filename;
6482 int nr_tests, test_num = 0;
6484 setbuf (stdout, NULL);
6486 no_test_warnings ();
6488 g = guestfs_create ();
6490 printf (\"guestfs_create FAILED\\n\");
6491 exit (EXIT_FAILURE);
6494 guestfs_set_error_handler (g, print_error, NULL);
6496 guestfs_set_path (g, \"../appliance\");
6498 filename = \"test1.img\";
6499 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6502 exit (EXIT_FAILURE);
6504 if (lseek (fd, %d, SEEK_SET) == -1) {
6508 exit (EXIT_FAILURE);
6510 if (write (fd, &c, 1) == -1) {
6514 exit (EXIT_FAILURE);
6516 if (close (fd) == -1) {
6519 exit (EXIT_FAILURE);
6521 if (guestfs_add_drive (g, filename) == -1) {
6522 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6523 exit (EXIT_FAILURE);
6526 filename = \"test2.img\";
6527 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6530 exit (EXIT_FAILURE);
6532 if (lseek (fd, %d, SEEK_SET) == -1) {
6536 exit (EXIT_FAILURE);
6538 if (write (fd, &c, 1) == -1) {
6542 exit (EXIT_FAILURE);
6544 if (close (fd) == -1) {
6547 exit (EXIT_FAILURE);
6549 if (guestfs_add_drive (g, filename) == -1) {
6550 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6551 exit (EXIT_FAILURE);
6554 filename = \"test3.img\";
6555 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6558 exit (EXIT_FAILURE);
6560 if (lseek (fd, %d, SEEK_SET) == -1) {
6564 exit (EXIT_FAILURE);
6566 if (write (fd, &c, 1) == -1) {
6570 exit (EXIT_FAILURE);
6572 if (close (fd) == -1) {
6575 exit (EXIT_FAILURE);
6577 if (guestfs_add_drive (g, filename) == -1) {
6578 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6579 exit (EXIT_FAILURE);
6582 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6583 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6584 exit (EXIT_FAILURE);
6587 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6590 if (guestfs_launch (g) == -1) {
6591 printf (\"guestfs_launch FAILED\\n\");
6592 exit (EXIT_FAILURE);
6595 /* Cancel previous alarm. */
6600 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6604 pr " test_num++;\n";
6605 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6606 pr " if (%s () == -1) {\n" test_name;
6607 pr " printf (\"%s FAILED\\n\");\n" test_name;
6608 pr " n_failed++;\n";
6613 pr " guestfs_close (g);\n";
6614 pr " unlink (\"test1.img\");\n";
6615 pr " unlink (\"test2.img\");\n";
6616 pr " unlink (\"test3.img\");\n";
6619 pr " if (n_failed > 0) {\n";
6620 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6621 pr " exit (EXIT_FAILURE);\n";
6625 pr " exit (EXIT_SUCCESS);\n";
6628 and generate_one_test name flags i (init, prereq, test) =
6629 let test_name = sprintf "test_%s_%d" name i in
6632 static int %s_skip (void)
6636 str = getenv (\"TEST_ONLY\");
6638 return strstr (str, \"%s\") == NULL;
6639 str = getenv (\"SKIP_%s\");
6640 if (str && STREQ (str, \"1\")) return 1;
6641 str = getenv (\"SKIP_TEST_%s\");
6642 if (str && STREQ (str, \"1\")) return 1;
6646 " test_name name (String.uppercase test_name) (String.uppercase name);
6649 | Disabled | Always -> ()
6650 | If code | Unless code ->
6651 pr "static int %s_prereq (void)\n" test_name;
6659 static int %s (void)
6662 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6666 " test_name test_name test_name;
6668 (* Optional functions should only be tested if the relevant
6669 * support is available in the daemon.
6675 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6677 pr " suppress_error = 1;\n";
6678 pr " r = guestfs_available (g, (char **) groups);\n";
6679 pr " suppress_error = 0;\n";
6680 pr " if (r == -1) {\n";
6681 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6690 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6692 pr " if (! %s_prereq ()) {\n" test_name;
6693 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6697 generate_one_test_body name i test_name init test;
6699 pr " if (%s_prereq ()) {\n" test_name;
6700 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6704 generate_one_test_body name i test_name init test;
6706 generate_one_test_body name i test_name init test
6714 and generate_one_test_body name i test_name init test =
6716 | InitNone (* XXX at some point, InitNone and InitEmpty became
6717 * folded together as the same thing. Really we should
6718 * make InitNone do nothing at all, but the tests may
6719 * need to be checked to make sure this is OK.
6722 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6723 List.iter (generate_test_command_call test_name)
6724 [["blockdev_setrw"; "/dev/sda"];
6728 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6729 List.iter (generate_test_command_call test_name)
6730 [["blockdev_setrw"; "/dev/sda"];
6733 ["part_disk"; "/dev/sda"; "mbr"]]
6735 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6736 List.iter (generate_test_command_call test_name)
6737 [["blockdev_setrw"; "/dev/sda"];
6740 ["part_disk"; "/dev/sda"; "mbr"];
6741 ["mkfs"; "ext2"; "/dev/sda1"];
6742 ["mount_options"; ""; "/dev/sda1"; "/"]]
6743 | InitBasicFSonLVM ->
6744 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6746 List.iter (generate_test_command_call test_name)
6747 [["blockdev_setrw"; "/dev/sda"];
6750 ["part_disk"; "/dev/sda"; "mbr"];
6751 ["pvcreate"; "/dev/sda1"];
6752 ["vgcreate"; "VG"; "/dev/sda1"];
6753 ["lvcreate"; "LV"; "VG"; "8"];
6754 ["mkfs"; "ext2"; "/dev/VG/LV"];
6755 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6757 pr " /* InitISOFS for %s */\n" test_name;
6758 List.iter (generate_test_command_call test_name)
6759 [["blockdev_setrw"; "/dev/sda"];
6762 ["mount_ro"; "/dev/sdd"; "/"]]
6765 let get_seq_last = function
6767 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6770 let seq = List.rev seq in
6771 List.rev (List.tl seq), List.hd seq
6776 pr " /* TestRun for %s (%d) */\n" name i;
6777 List.iter (generate_test_command_call test_name) seq
6778 | TestOutput (seq, expected) ->
6779 pr " /* TestOutput for %s (%d) */\n" name i;
6780 pr " const char *expected = \"%s\";\n" (c_quote expected);
6781 let seq, last = get_seq_last seq in
6783 pr " if (STRNEQ (r, expected)) {\n";
6784 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6788 List.iter (generate_test_command_call test_name) seq;
6789 generate_test_command_call ~test test_name last
6790 | TestOutputList (seq, expected) ->
6791 pr " /* TestOutputList for %s (%d) */\n" name i;
6792 let seq, last = get_seq_last seq in
6796 pr " if (!r[%d]) {\n" i;
6797 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6798 pr " print_strings (r);\n";
6802 pr " const char *expected = \"%s\";\n" (c_quote str);
6803 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6804 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6809 pr " if (r[%d] != NULL) {\n" (List.length expected);
6810 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6812 pr " print_strings (r);\n";
6816 List.iter (generate_test_command_call test_name) seq;
6817 generate_test_command_call ~test test_name last
6818 | TestOutputListOfDevices (seq, expected) ->
6819 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6820 let seq, last = get_seq_last seq in
6824 pr " if (!r[%d]) {\n" i;
6825 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6826 pr " print_strings (r);\n";
6830 pr " const char *expected = \"%s\";\n" (c_quote str);
6831 pr " r[%d][5] = 's';\n" i;
6832 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6833 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6838 pr " if (r[%d] != NULL) {\n" (List.length expected);
6839 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6841 pr " print_strings (r);\n";
6845 List.iter (generate_test_command_call test_name) seq;
6846 generate_test_command_call ~test test_name last
6847 | TestOutputInt (seq, expected) ->
6848 pr " /* TestOutputInt for %s (%d) */\n" name i;
6849 let seq, last = get_seq_last seq in
6851 pr " if (r != %d) {\n" expected;
6852 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6858 List.iter (generate_test_command_call test_name) seq;
6859 generate_test_command_call ~test test_name last
6860 | TestOutputIntOp (seq, op, expected) ->
6861 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6862 let seq, last = get_seq_last seq in
6864 pr " if (! (r %s %d)) {\n" op expected;
6865 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6866 test_name op expected;
6871 List.iter (generate_test_command_call test_name) seq;
6872 generate_test_command_call ~test test_name last
6873 | TestOutputTrue seq ->
6874 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6875 let seq, last = get_seq_last seq in
6878 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6883 List.iter (generate_test_command_call test_name) seq;
6884 generate_test_command_call ~test test_name last
6885 | TestOutputFalse seq ->
6886 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6887 let seq, last = get_seq_last seq in
6890 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6895 List.iter (generate_test_command_call test_name) seq;
6896 generate_test_command_call ~test test_name last
6897 | TestOutputLength (seq, expected) ->
6898 pr " /* TestOutputLength for %s (%d) */\n" name i;
6899 let seq, last = get_seq_last seq in
6902 pr " for (j = 0; j < %d; ++j)\n" expected;
6903 pr " if (r[j] == NULL) {\n";
6904 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6906 pr " print_strings (r);\n";
6909 pr " if (r[j] != NULL) {\n";
6910 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6912 pr " print_strings (r);\n";
6916 List.iter (generate_test_command_call test_name) seq;
6917 generate_test_command_call ~test test_name last
6918 | TestOutputBuffer (seq, expected) ->
6919 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6920 pr " const char *expected = \"%s\";\n" (c_quote expected);
6921 let seq, last = get_seq_last seq in
6922 let len = String.length expected in
6924 pr " if (size != %d) {\n" len;
6925 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6928 pr " if (STRNEQLEN (r, expected, size)) {\n";
6929 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6933 List.iter (generate_test_command_call test_name) seq;
6934 generate_test_command_call ~test test_name last
6935 | TestOutputStruct (seq, checks) ->
6936 pr " /* TestOutputStruct for %s (%d) */\n" name i;
6937 let seq, last = get_seq_last seq in
6941 | CompareWithInt (field, expected) ->
6942 pr " if (r->%s != %d) {\n" field expected;
6943 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6944 test_name field expected;
6945 pr " (int) r->%s);\n" field;
6948 | CompareWithIntOp (field, op, expected) ->
6949 pr " if (!(r->%s %s %d)) {\n" field op expected;
6950 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6951 test_name field op expected;
6952 pr " (int) r->%s);\n" field;
6955 | CompareWithString (field, expected) ->
6956 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6957 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6958 test_name field expected;
6959 pr " r->%s);\n" field;
6962 | CompareFieldsIntEq (field1, field2) ->
6963 pr " if (r->%s != r->%s) {\n" field1 field2;
6964 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6965 test_name field1 field2;
6966 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
6969 | CompareFieldsStrEq (field1, field2) ->
6970 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6971 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6972 test_name field1 field2;
6973 pr " r->%s, r->%s);\n" field1 field2;
6978 List.iter (generate_test_command_call test_name) seq;
6979 generate_test_command_call ~test test_name last
6980 | TestLastFail seq ->
6981 pr " /* TestLastFail for %s (%d) */\n" name i;
6982 let seq, last = get_seq_last seq in
6983 List.iter (generate_test_command_call test_name) seq;
6984 generate_test_command_call test_name ~expect_error:true last
6986 (* Generate the code to run a command, leaving the result in 'r'.
6987 * If you expect to get an error then you should set expect_error:true.
6989 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6991 | [] -> assert false
6993 (* Look up the command to find out what args/ret it has. *)
6996 let _, style, _, _, _, _, _ =
6997 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7000 failwithf "%s: in test, command %s was not found" test_name name in
7002 if List.length (snd style) <> List.length args then
7003 failwithf "%s: in test, wrong number of args given to %s"
7010 | OptString n, "NULL" -> ()
7013 | Dev_or_Path n, arg
7015 | OptString n, arg ->
7016 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7020 | FileIn _, _ | FileOut _, _ -> ()
7021 | StringList n, "" | DeviceList n, "" ->
7022 pr " const char *const %s[1] = { NULL };\n" n
7023 | StringList n, arg | DeviceList n, arg ->
7024 let strs = string_split " " arg in
7027 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7029 pr " const char *const %s[] = {\n" n;
7031 fun i _ -> pr " %s_%d,\n" n i
7035 ) (List.combine (snd style) args);
7038 match fst style with
7039 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7040 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7041 | RConstString _ | RConstOptString _ ->
7042 pr " const char *r;\n"; "NULL"
7043 | RString _ -> pr " char *r;\n"; "NULL"
7044 | RStringList _ | RHashtable _ ->
7048 | RStruct (_, typ) ->
7049 pr " struct guestfs_%s *r;\n" typ; "NULL"
7050 | RStructList (_, typ) ->
7051 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7054 pr " size_t size;\n";
7057 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7058 pr " r = guestfs_%s (g" name;
7060 (* Generate the parameters. *)
7063 | OptString _, "NULL" -> pr ", NULL"
7065 | Device n, _ | Dev_or_Path n, _
7069 | FileIn _, arg | FileOut _, arg ->
7070 pr ", \"%s\"" (c_quote arg)
7071 | StringList n, _ | DeviceList n, _ ->
7072 pr ", (char **) %s" n
7075 try int_of_string arg
7076 with Failure "int_of_string" ->
7077 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7081 try Int64.of_string arg
7082 with Failure "int_of_string" ->
7083 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7086 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7087 ) (List.combine (snd style) args);
7089 (match fst style with
7090 | RBufferOut _ -> pr ", &size"
7096 if not expect_error then
7097 pr " if (r == %s)\n" error_code
7099 pr " if (r != %s)\n" error_code;
7102 (* Insert the test code. *)
7108 (match fst style with
7109 | RErr | RInt _ | RInt64 _ | RBool _
7110 | RConstString _ | RConstOptString _ -> ()
7111 | RString _ | RBufferOut _ -> pr " free (r);\n"
7112 | RStringList _ | RHashtable _ ->
7113 pr " for (i = 0; r[i] != NULL; ++i)\n";
7114 pr " free (r[i]);\n";
7116 | RStruct (_, typ) ->
7117 pr " guestfs_free_%s (r);\n" typ
7118 | RStructList (_, typ) ->
7119 pr " guestfs_free_%s_list (r);\n" typ
7125 let str = replace_str str "\r" "\\r" in
7126 let str = replace_str str "\n" "\\n" in
7127 let str = replace_str str "\t" "\\t" in
7128 let str = replace_str str "\000" "\\0" in
7131 (* Generate a lot of different functions for guestfish. *)
7132 and generate_fish_cmds () =
7133 generate_header CStyle GPLv2plus;
7137 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7139 let all_functions_sorted =
7141 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7142 ) all_functions_sorted in
7144 pr "#include <config.h>\n";
7146 pr "#include <stdio.h>\n";
7147 pr "#include <stdlib.h>\n";
7148 pr "#include <string.h>\n";
7149 pr "#include <inttypes.h>\n";
7151 pr "#include <guestfs.h>\n";
7152 pr "#include \"c-ctype.h\"\n";
7153 pr "#include \"full-write.h\"\n";
7154 pr "#include \"xstrtol.h\"\n";
7155 pr "#include \"fish.h\"\n";
7158 (* list_commands function, which implements guestfish -h *)
7159 pr "void list_commands (void)\n";
7161 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7162 pr " list_builtin_commands ();\n";
7164 fun (name, _, _, flags, _, shortdesc, _) ->
7165 let name = replace_char name '_' '-' in
7166 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7168 ) all_functions_sorted;
7169 pr " printf (\" %%s\\n\",";
7170 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7174 (* display_command function, which implements guestfish -h cmd *)
7175 pr "void display_command (const char *cmd)\n";
7178 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7179 let name2 = replace_char name '_' '-' in
7181 try find_map (function FishAlias n -> Some n | _ -> None) flags
7182 with Not_found -> name in
7183 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7185 match snd style with
7189 name2 (String.concat " " (List.map name_of_argt args)) in
7192 if List.mem ProtocolLimitWarning flags then
7193 ("\n\n" ^ protocol_limit_warning)
7196 (* For DangerWillRobinson commands, we should probably have
7197 * guestfish prompt before allowing you to use them (especially
7198 * in interactive mode). XXX
7202 if List.mem DangerWillRobinson flags then
7203 ("\n\n" ^ danger_will_robinson)
7208 match deprecation_notice flags with
7210 | Some txt -> "\n\n" ^ txt in
7212 let describe_alias =
7213 if name <> alias then
7214 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7218 pr "STRCASEEQ (cmd, \"%s\")" name;
7219 if name <> name2 then
7220 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7221 if name <> alias then
7222 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7224 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7226 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7227 "=head1 DESCRIPTION\n\n" ^
7228 longdesc ^ warnings ^ describe_alias);
7231 pr " display_builtin_command (cmd);\n";
7235 let emit_print_list_function typ =
7236 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7239 pr " unsigned int i;\n";
7241 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7242 pr " printf (\"[%%d] = {\\n\", i);\n";
7243 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7244 pr " printf (\"}\\n\");\n";
7250 (* print_* functions *)
7254 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7256 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7259 pr " unsigned int i;\n";
7265 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7267 pr " printf (\"%%s%s: \", indent);\n" name;
7268 pr " for (i = 0; i < 32; ++i)\n";
7269 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7270 pr " printf (\"\\n\");\n"
7272 pr " printf (\"%%s%s: \", indent);\n" name;
7273 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7274 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7275 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7277 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7278 pr " printf (\"\\n\");\n"
7279 | name, (FUInt64|FBytes) ->
7280 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7283 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7286 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7289 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7292 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7294 | name, FOptPercent ->
7295 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7296 typ name name typ name;
7297 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7303 (* Emit a print_TYPE_list function definition only if that function is used. *)
7306 | typ, (RStructListOnly | RStructAndList) ->
7307 (* generate the function for typ *)
7308 emit_print_list_function typ
7309 | typ, _ -> () (* empty *)
7310 ) (rstructs_used_by all_functions);
7312 (* Emit a print_TYPE function definition only if that function is used. *)
7315 | typ, (RStructOnly | RStructAndList) ->
7316 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7318 pr " print_%s_indent (%s, \"\");\n" typ typ;
7321 | typ, _ -> () (* empty *)
7322 ) (rstructs_used_by all_functions);
7324 (* run_<action> actions *)
7326 fun (name, style, _, flags, _, _, _) ->
7327 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7329 (match fst style with
7332 | RBool _ -> pr " int r;\n"
7333 | RInt64 _ -> pr " int64_t r;\n"
7334 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7335 | RString _ -> pr " char *r;\n"
7336 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7337 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7338 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7341 pr " size_t size;\n";
7349 | FileOut n -> pr " const char *%s;\n" n
7351 | Dev_or_Path n -> pr " char *%s;\n" n
7352 | StringList n | DeviceList n -> pr " char **%s;\n" n
7353 | Bool n -> pr " int %s;\n" n
7354 | Int n -> pr " int %s;\n" n
7355 | Int64 n -> pr " int64_t %s;\n" n
7358 (* Check and convert parameters. *)
7359 let argc_expected = List.length (snd style) in
7360 pr " if (argc != %d) {\n" argc_expected;
7361 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7363 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7367 let parse_integer fn fntyp rtyp range name i =
7369 pr " strtol_error xerr;\n";
7370 pr " %s r;\n" fntyp;
7372 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7373 pr " if (xerr != LONGINT_OK) {\n";
7374 pr " fprintf (stderr,\n";
7375 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7376 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7381 | Some (min, max, comment) ->
7382 pr " /* %s */\n" comment;
7383 pr " if (r < %s || r > %s) {\n" min max;
7384 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7388 pr " /* The check above should ensure this assignment does not overflow. */\n";
7390 pr " %s = r;\n" name;
7399 pr " %s = argv[%d];\n" name i
7401 | Dev_or_Path name ->
7402 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7403 pr " if (%s == NULL) return -1;\n" name
7405 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7408 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7411 pr " %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7413 | StringList name | DeviceList name ->
7414 pr " %s = parse_string_list (argv[%d]);\n" name i;
7415 pr " if (%s == NULL) return -1;\n" name;
7417 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7420 let min = "(-(2LL<<30))"
7421 and max = "((2LL<<30)-1)"
7423 "The Int type in the generator is a signed 31 bit int." in
7424 Some (min, max, comment) in
7425 parse_integer "xstrtoll" "long long" "int" range name i
7427 parse_integer "xstrtoll" "long long" "int64_t" None name i
7430 (* Call C API function. *)
7432 try find_map (function FishAction n -> Some n | _ -> None) flags
7433 with Not_found -> sprintf "guestfs_%s" name in
7435 generate_c_call_args ~handle:"g" style;
7440 | Device name | String name
7441 | OptString name | FileIn name | FileOut name | Bool name
7442 | Int name | Int64 name -> ()
7443 | Pathname name | Dev_or_Path name ->
7444 pr " free (%s);\n" name
7445 | StringList name | DeviceList name ->
7446 pr " free_strings (%s);\n" name
7449 (* Check return value for errors and display command results. *)
7450 (match fst style with
7451 | RErr -> pr " return r;\n"
7453 pr " if (r == -1) return -1;\n";
7454 pr " printf (\"%%d\\n\", r);\n";
7457 pr " if (r == -1) return -1;\n";
7458 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7461 pr " if (r == -1) return -1;\n";
7462 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7465 pr " if (r == NULL) return -1;\n";
7466 pr " printf (\"%%s\\n\", r);\n";
7468 | RConstOptString _ ->
7469 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7472 pr " if (r == NULL) return -1;\n";
7473 pr " printf (\"%%s\\n\", r);\n";
7477 pr " if (r == NULL) return -1;\n";
7478 pr " print_strings (r);\n";
7479 pr " free_strings (r);\n";
7481 | RStruct (_, typ) ->
7482 pr " if (r == NULL) return -1;\n";
7483 pr " print_%s (r);\n" typ;
7484 pr " guestfs_free_%s (r);\n" typ;
7486 | RStructList (_, typ) ->
7487 pr " if (r == NULL) return -1;\n";
7488 pr " print_%s_list (r);\n" typ;
7489 pr " guestfs_free_%s_list (r);\n" typ;
7492 pr " if (r == NULL) return -1;\n";
7493 pr " print_table (r);\n";
7494 pr " free_strings (r);\n";
7497 pr " if (r == NULL) return -1;\n";
7498 pr " if (full_write (1, r, size) != size) {\n";
7499 pr " perror (\"write\");\n";
7510 (* run_action function *)
7511 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7514 fun (name, _, _, flags, _, _, _) ->
7515 let name2 = replace_char name '_' '-' in
7517 try find_map (function FishAlias n -> Some n | _ -> None) flags
7518 with Not_found -> name in
7520 pr "STRCASEEQ (cmd, \"%s\")" name;
7521 if name <> name2 then
7522 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7523 if name <> alias then
7524 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7526 pr " return run_%s (cmd, argc, argv);\n" name;
7530 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7531 pr " if (command_num == 1)\n";
7532 pr " extended_help_message ();\n";
7539 (* Readline completion for guestfish. *)
7540 and generate_fish_completion () =
7541 generate_header CStyle GPLv2plus;
7545 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7555 #ifdef HAVE_LIBREADLINE
7556 #include <readline/readline.h>
7561 #ifdef HAVE_LIBREADLINE
7563 static const char *const commands[] = {
7564 BUILTIN_COMMANDS_FOR_COMPLETION,
7567 (* Get the commands, including the aliases. They don't need to be
7568 * sorted - the generator() function just does a dumb linear search.
7572 fun (name, _, _, flags, _, _, _) ->
7573 let name2 = replace_char name '_' '-' in
7575 try find_map (function FishAlias n -> Some n | _ -> None) flags
7576 with Not_found -> name in
7578 if name <> alias then [name2; alias] else [name2]
7580 let commands = List.flatten commands in
7582 List.iter (pr " \"%s\",\n") commands;
7588 generator (const char *text, int state)
7590 static int index, len;
7595 len = strlen (text);
7598 rl_attempted_completion_over = 1;
7600 while ((name = commands[index]) != NULL) {
7602 if (STRCASEEQLEN (name, text, len))
7603 return strdup (name);
7609 #endif /* HAVE_LIBREADLINE */
7611 #ifdef HAVE_RL_COMPLETION_MATCHES
7612 #define RL_COMPLETION_MATCHES rl_completion_matches
7614 #ifdef HAVE_COMPLETION_MATCHES
7615 #define RL_COMPLETION_MATCHES completion_matches
7617 #endif /* else just fail if we don't have either symbol */
7620 do_completion (const char *text, int start, int end)
7622 char **matches = NULL;
7624 #ifdef HAVE_LIBREADLINE
7625 rl_completion_append_character = ' ';
7628 matches = RL_COMPLETION_MATCHES (text, generator);
7629 else if (complete_dest_paths)
7630 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7637 (* Generate the POD documentation for guestfish. *)
7638 and generate_fish_actions_pod () =
7639 let all_functions_sorted =
7641 fun (_, _, _, flags, _, _, _) ->
7642 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7643 ) all_functions_sorted in
7645 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7648 fun (name, style, _, flags, _, _, longdesc) ->
7650 Str.global_substitute rex (
7653 try Str.matched_group 1 s
7655 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7656 "C<" ^ replace_char sub '_' '-' ^ ">"
7658 let name = replace_char name '_' '-' in
7660 try find_map (function FishAlias n -> Some n | _ -> None) flags
7661 with Not_found -> name in
7663 pr "=head2 %s" name;
7664 if name <> alias then
7671 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7672 | OptString n -> pr " %s" n
7673 | StringList n | DeviceList n -> pr " '%s ...'" n
7674 | Bool _ -> pr " true|false"
7675 | Int n -> pr " %s" n
7676 | Int64 n -> pr " %s" n
7677 | FileIn n | FileOut n -> pr " (%s|-)" n
7681 pr "%s\n\n" longdesc;
7683 if List.exists (function FileIn _ | FileOut _ -> true
7684 | _ -> false) (snd style) then
7685 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7687 if List.mem ProtocolLimitWarning flags then
7688 pr "%s\n\n" protocol_limit_warning;
7690 if List.mem DangerWillRobinson flags then
7691 pr "%s\n\n" danger_will_robinson;
7693 match deprecation_notice flags with
7695 | Some txt -> pr "%s\n\n" txt
7696 ) all_functions_sorted
7698 (* Generate a C function prototype. *)
7699 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7700 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7702 ?handle name style =
7703 if extern then pr "extern ";
7704 if static then pr "static ";
7705 (match fst style with
7707 | RInt _ -> pr "int "
7708 | RInt64 _ -> pr "int64_t "
7709 | RBool _ -> pr "int "
7710 | RConstString _ | RConstOptString _ -> pr "const char *"
7711 | RString _ | RBufferOut _ -> pr "char *"
7712 | RStringList _ | RHashtable _ -> pr "char **"
7713 | RStruct (_, typ) ->
7714 if not in_daemon then pr "struct guestfs_%s *" typ
7715 else pr "guestfs_int_%s *" typ
7716 | RStructList (_, typ) ->
7717 if not in_daemon then pr "struct guestfs_%s_list *" typ
7718 else pr "guestfs_int_%s_list *" typ
7720 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7721 pr "%s%s (" prefix name;
7722 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7725 let comma = ref false in
7728 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7732 if single_line then pr ", " else pr ",\n\t\t"
7739 | Device n | Dev_or_Path n
7743 pr "const char *%s" n
7744 | StringList n | DeviceList n ->
7746 pr "char *const *%s" n
7747 | Bool n -> next (); pr "int %s" n
7748 | Int n -> next (); pr "int %s" n
7749 | Int64 n -> next (); pr "int64_t %s" n
7752 if not in_daemon then (next (); pr "const char *%s" n)
7754 if is_RBufferOut then (next (); pr "size_t *size_r");
7757 if semicolon then pr ";";
7758 if newline then pr "\n"
7760 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7761 and generate_c_call_args ?handle ?(decl = false) style =
7763 let comma = ref false in
7765 if !comma then pr ", ";
7770 | Some handle -> pr "%s" handle; comma := true
7775 pr "%s" (name_of_argt arg)
7777 (* For RBufferOut calls, add implicit &size parameter. *)
7779 match fst style with
7787 (* Generate the OCaml bindings interface. *)
7788 and generate_ocaml_mli () =
7789 generate_header OCamlStyle LGPLv2plus;
7792 (** For API documentation you should refer to the C API
7793 in the guestfs(3) manual page. The OCaml API uses almost
7794 exactly the same calls. *)
7797 (** A [guestfs_h] handle. *)
7799 exception Error of string
7800 (** This exception is raised when there is an error. *)
7802 exception Handle_closed of string
7803 (** This exception is raised if you use a {!Guestfs.t} handle
7804 after calling {!close} on it. The string is the name of
7807 val create : unit -> t
7808 (** Create a {!Guestfs.t} handle. *)
7810 val close : t -> unit
7811 (** Close the {!Guestfs.t} handle and free up all resources used
7814 Handles are closed by the garbage collector when they become
7815 unreferenced, but callers can call this in order to provide
7816 predictable cleanup. *)
7819 generate_ocaml_structure_decls ();
7823 fun (name, style, _, _, _, shortdesc, _) ->
7824 generate_ocaml_prototype name style;
7825 pr "(** %s *)\n" shortdesc;
7827 ) all_functions_sorted
7829 (* Generate the OCaml bindings implementation. *)
7830 and generate_ocaml_ml () =
7831 generate_header OCamlStyle LGPLv2plus;
7836 exception Error of string
7837 exception Handle_closed of string
7839 external create : unit -> t = \"ocaml_guestfs_create\"
7840 external close : t -> unit = \"ocaml_guestfs_close\"
7842 (* Give the exceptions names, so they can be raised from the C code. *)
7844 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7845 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7849 generate_ocaml_structure_decls ();
7853 fun (name, style, _, _, _, shortdesc, _) ->
7854 generate_ocaml_prototype ~is_external:true name style;
7855 ) all_functions_sorted
7857 (* Generate the OCaml bindings C implementation. *)
7858 and generate_ocaml_c () =
7859 generate_header CStyle LGPLv2plus;
7866 #include <caml/config.h>
7867 #include <caml/alloc.h>
7868 #include <caml/callback.h>
7869 #include <caml/fail.h>
7870 #include <caml/memory.h>
7871 #include <caml/mlvalues.h>
7872 #include <caml/signals.h>
7874 #include <guestfs.h>
7876 #include \"guestfs_c.h\"
7878 /* Copy a hashtable of string pairs into an assoc-list. We return
7879 * the list in reverse order, but hashtables aren't supposed to be
7882 static CAMLprim value
7883 copy_table (char * const * argv)
7886 CAMLlocal5 (rv, pairv, kv, vv, cons);
7890 for (i = 0; argv[i] != NULL; i += 2) {
7891 kv = caml_copy_string (argv[i]);
7892 vv = caml_copy_string (argv[i+1]);
7893 pairv = caml_alloc (2, 0);
7894 Store_field (pairv, 0, kv);
7895 Store_field (pairv, 1, vv);
7896 cons = caml_alloc (2, 0);
7897 Store_field (cons, 1, rv);
7899 Store_field (cons, 0, pairv);
7907 (* Struct copy functions. *)
7909 let emit_ocaml_copy_list_function typ =
7910 pr "static CAMLprim value\n";
7911 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7913 pr " CAMLparam0 ();\n";
7914 pr " CAMLlocal2 (rv, v);\n";
7915 pr " unsigned int i;\n";
7917 pr " if (%ss->len == 0)\n" typ;
7918 pr " CAMLreturn (Atom (0));\n";
7920 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
7921 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7922 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
7923 pr " caml_modify (&Field (rv, i), v);\n";
7925 pr " CAMLreturn (rv);\n";
7933 let has_optpercent_col =
7934 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7936 pr "static CAMLprim value\n";
7937 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7939 pr " CAMLparam0 ();\n";
7940 if has_optpercent_col then
7941 pr " CAMLlocal3 (rv, v, v2);\n"
7943 pr " CAMLlocal2 (rv, v);\n";
7945 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
7950 pr " v = caml_copy_string (%s->%s);\n" typ name
7952 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
7953 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7956 pr " v = caml_alloc_string (32);\n";
7957 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
7958 | name, (FBytes|FInt64|FUInt64) ->
7959 pr " v = caml_copy_int64 (%s->%s);\n" typ name
7960 | name, (FInt32|FUInt32) ->
7961 pr " v = caml_copy_int32 (%s->%s);\n" typ name
7962 | name, FOptPercent ->
7963 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7964 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
7965 pr " v = caml_alloc (1, 0);\n";
7966 pr " Store_field (v, 0, v2);\n";
7967 pr " } else /* None */\n";
7968 pr " v = Val_int (0);\n";
7970 pr " v = Val_int (%s->%s);\n" typ name
7972 pr " Store_field (rv, %d, v);\n" i
7974 pr " CAMLreturn (rv);\n";
7979 (* Emit a copy_TYPE_list function definition only if that function is used. *)
7982 | typ, (RStructListOnly | RStructAndList) ->
7983 (* generate the function for typ *)
7984 emit_ocaml_copy_list_function typ
7985 | typ, _ -> () (* empty *)
7986 ) (rstructs_used_by all_functions);
7990 fun (name, style, _, _, _, _, _) ->
7991 pr "/* Automatically generated wrapper for function\n";
7993 generate_ocaml_prototype name style;
7998 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8000 let needs_extra_vs =
8001 match fst style with RConstOptString _ -> true | _ -> false in
8003 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8004 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8005 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8008 pr "CAMLprim value\n";
8009 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8010 List.iter (pr ", value %s") (List.tl params);
8015 | [p1; p2; p3; p4; p5] ->
8016 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8017 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8018 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8019 pr " CAMLxparam%d (%s);\n"
8020 (List.length rest) (String.concat ", " rest)
8022 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8024 if not needs_extra_vs then
8025 pr " CAMLlocal1 (rv);\n"
8027 pr " CAMLlocal3 (rv, v, v2);\n";
8030 pr " guestfs_h *g = Guestfs_val (gv);\n";
8031 pr " if (g == NULL)\n";
8032 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8038 | Device n | Dev_or_Path n
8042 pr " const char *%s = String_val (%sv);\n" n n
8044 pr " const char *%s =\n" n;
8045 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8047 | StringList n | DeviceList n ->
8048 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8050 pr " int %s = Bool_val (%sv);\n" n n
8052 pr " int %s = Int_val (%sv);\n" n n
8054 pr " int64_t %s = Int64_val (%sv);\n" n n
8057 match fst style with
8058 | RErr -> pr " int r;\n"; "-1"
8059 | RInt _ -> pr " int r;\n"; "-1"
8060 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8061 | RBool _ -> pr " int r;\n"; "-1"
8062 | RConstString _ | RConstOptString _ ->
8063 pr " const char *r;\n"; "NULL"
8064 | RString _ -> pr " char *r;\n"; "NULL"
8069 | RStruct (_, typ) ->
8070 pr " struct guestfs_%s *r;\n" typ; "NULL"
8071 | RStructList (_, typ) ->
8072 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8079 pr " size_t size;\n";
8083 pr " caml_enter_blocking_section ();\n";
8084 pr " r = guestfs_%s " name;
8085 generate_c_call_args ~handle:"g" style;
8087 pr " caml_leave_blocking_section ();\n";
8091 | StringList n | DeviceList n ->
8092 pr " ocaml_guestfs_free_strings (%s);\n" n;
8093 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8094 | Bool _ | Int _ | Int64 _
8095 | FileIn _ | FileOut _ -> ()
8098 pr " if (r == %s)\n" error_code;
8099 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8102 (match fst style with
8103 | RErr -> pr " rv = Val_unit;\n"
8104 | RInt _ -> pr " rv = Val_int (r);\n"
8106 pr " rv = caml_copy_int64 (r);\n"
8107 | RBool _ -> pr " rv = Val_bool (r);\n"
8109 pr " rv = caml_copy_string (r);\n"
8110 | RConstOptString _ ->
8111 pr " if (r) { /* Some string */\n";
8112 pr " v = caml_alloc (1, 0);\n";
8113 pr " v2 = caml_copy_string (r);\n";
8114 pr " Store_field (v, 0, v2);\n";
8115 pr " } else /* None */\n";
8116 pr " v = Val_int (0);\n";
8118 pr " rv = caml_copy_string (r);\n";
8121 pr " rv = caml_copy_string_array ((const char **) r);\n";
8122 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8124 | RStruct (_, typ) ->
8125 pr " rv = copy_%s (r);\n" typ;
8126 pr " guestfs_free_%s (r);\n" typ;
8127 | RStructList (_, typ) ->
8128 pr " rv = copy_%s_list (r);\n" typ;
8129 pr " guestfs_free_%s_list (r);\n" typ;
8131 pr " rv = copy_table (r);\n";
8132 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8135 pr " rv = caml_alloc_string (size);\n";
8136 pr " memcpy (String_val (rv), r, size);\n";
8139 pr " CAMLreturn (rv);\n";
8143 if List.length params > 5 then (
8144 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8145 pr "CAMLprim value ";
8146 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8147 pr "CAMLprim value\n";
8148 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8150 pr " return ocaml_guestfs_%s (argv[0]" name;
8151 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8156 ) all_functions_sorted
8158 and generate_ocaml_structure_decls () =
8161 pr "type %s = {\n" typ;
8164 | name, FString -> pr " %s : string;\n" name
8165 | name, FBuffer -> pr " %s : string;\n" name
8166 | name, FUUID -> pr " %s : string;\n" name
8167 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8168 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8169 | name, FChar -> pr " %s : char;\n" name
8170 | name, FOptPercent -> pr " %s : float option;\n" name
8176 and generate_ocaml_prototype ?(is_external = false) name style =
8177 if is_external then pr "external " else pr "val ";
8178 pr "%s : t -> " name;
8181 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8182 | OptString _ -> pr "string option -> "
8183 | StringList _ | DeviceList _ -> pr "string array -> "
8184 | Bool _ -> pr "bool -> "
8185 | Int _ -> pr "int -> "
8186 | Int64 _ -> pr "int64 -> "
8188 (match fst style with
8189 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8190 | RInt _ -> pr "int"
8191 | RInt64 _ -> pr "int64"
8192 | RBool _ -> pr "bool"
8193 | RConstString _ -> pr "string"
8194 | RConstOptString _ -> pr "string option"
8195 | RString _ | RBufferOut _ -> pr "string"
8196 | RStringList _ -> pr "string array"
8197 | RStruct (_, typ) -> pr "%s" typ
8198 | RStructList (_, typ) -> pr "%s array" typ
8199 | RHashtable _ -> pr "(string * string) list"
8201 if is_external then (
8203 if List.length (snd style) + 1 > 5 then
8204 pr "\"ocaml_guestfs_%s_byte\" " name;
8205 pr "\"ocaml_guestfs_%s\"" name
8209 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8210 and generate_perl_xs () =
8211 generate_header CStyle LGPLv2plus;
8214 #include \"EXTERN.h\"
8218 #include <guestfs.h>
8221 #define PRId64 \"lld\"
8225 my_newSVll(long long val) {
8226 #ifdef USE_64_BIT_ALL
8227 return newSViv(val);
8231 len = snprintf(buf, 100, \"%%\" PRId64, val);
8232 return newSVpv(buf, len);
8237 #define PRIu64 \"llu\"
8241 my_newSVull(unsigned long long val) {
8242 #ifdef USE_64_BIT_ALL
8243 return newSVuv(val);
8247 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8248 return newSVpv(buf, len);
8252 /* http://www.perlmonks.org/?node_id=680842 */
8254 XS_unpack_charPtrPtr (SV *arg) {
8259 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8260 croak (\"array reference expected\");
8262 av = (AV *)SvRV (arg);
8263 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8265 croak (\"malloc failed\");
8267 for (i = 0; i <= av_len (av); i++) {
8268 SV **elem = av_fetch (av, i, 0);
8270 if (!elem || !*elem)
8271 croak (\"missing element in list\");
8273 ret[i] = SvPV_nolen (*elem);
8281 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8288 RETVAL = guestfs_create ();
8290 croak (\"could not create guestfs handle\");
8291 guestfs_set_error_handler (RETVAL, NULL, NULL);
8304 fun (name, style, _, _, _, _, _) ->
8305 (match fst style with
8306 | RErr -> pr "void\n"
8307 | RInt _ -> pr "SV *\n"
8308 | RInt64 _ -> pr "SV *\n"
8309 | RBool _ -> pr "SV *\n"
8310 | RConstString _ -> pr "SV *\n"
8311 | RConstOptString _ -> pr "SV *\n"
8312 | RString _ -> pr "SV *\n"
8313 | RBufferOut _ -> pr "SV *\n"
8315 | RStruct _ | RStructList _
8317 pr "void\n" (* all lists returned implictly on the stack *)
8319 (* Call and arguments. *)
8321 generate_c_call_args ~handle:"g" ~decl:true style;
8323 pr " guestfs_h *g;\n";
8327 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8330 (* http://www.perlmonks.org/?node_id=554277
8331 * Note that the implicit handle argument means we have
8332 * to add 1 to the ST(x) operator.
8334 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8335 | StringList n | DeviceList n -> pr " char **%s;\n" n
8336 | Bool n -> pr " int %s;\n" n
8337 | Int n -> pr " int %s;\n" n
8338 | Int64 n -> pr " int64_t %s;\n" n
8341 let do_cleanups () =
8344 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8345 | Bool _ | Int _ | Int64 _
8346 | FileIn _ | FileOut _ -> ()
8347 | StringList n | DeviceList n -> pr " free (%s);\n" n
8352 (match fst style with
8357 pr " r = guestfs_%s " name;
8358 generate_c_call_args ~handle:"g" style;
8361 pr " if (r == -1)\n";
8362 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8368 pr " %s = guestfs_%s " n name;
8369 generate_c_call_args ~handle:"g" style;
8372 pr " if (%s == -1)\n" n;
8373 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8374 pr " RETVAL = newSViv (%s);\n" n;
8379 pr " int64_t %s;\n" n;
8381 pr " %s = guestfs_%s " n name;
8382 generate_c_call_args ~handle:"g" style;
8385 pr " if (%s == -1)\n" n;
8386 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8387 pr " RETVAL = my_newSVll (%s);\n" n;
8392 pr " const char *%s;\n" n;
8394 pr " %s = guestfs_%s " n name;
8395 generate_c_call_args ~handle:"g" style;
8398 pr " if (%s == NULL)\n" n;
8399 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8400 pr " RETVAL = newSVpv (%s, 0);\n" n;
8403 | RConstOptString n ->
8405 pr " const char *%s;\n" n;
8407 pr " %s = guestfs_%s " n name;
8408 generate_c_call_args ~handle:"g" style;
8411 pr " if (%s == NULL)\n" n;
8412 pr " RETVAL = &PL_sv_undef;\n";
8414 pr " RETVAL = newSVpv (%s, 0);\n" n;
8419 pr " char *%s;\n" n;
8421 pr " %s = guestfs_%s " n name;
8422 generate_c_call_args ~handle:"g" style;
8425 pr " if (%s == NULL)\n" n;
8426 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8427 pr " RETVAL = newSVpv (%s, 0);\n" n;
8428 pr " free (%s);\n" n;
8431 | RStringList n | RHashtable n ->
8433 pr " char **%s;\n" n;
8436 pr " %s = guestfs_%s " n name;
8437 generate_c_call_args ~handle:"g" style;
8440 pr " if (%s == NULL)\n" n;
8441 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8442 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8443 pr " EXTEND (SP, n);\n";
8444 pr " for (i = 0; i < n; ++i) {\n";
8445 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8446 pr " free (%s[i]);\n" n;
8448 pr " free (%s);\n" n;
8449 | RStruct (n, typ) ->
8450 let cols = cols_of_struct typ in
8451 generate_perl_struct_code typ cols name style n do_cleanups
8452 | RStructList (n, typ) ->
8453 let cols = cols_of_struct typ in
8454 generate_perl_struct_list_code typ cols name style n do_cleanups
8457 pr " char *%s;\n" n;
8458 pr " size_t size;\n";
8460 pr " %s = guestfs_%s " n name;
8461 generate_c_call_args ~handle:"g" style;
8464 pr " if (%s == NULL)\n" n;
8465 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8466 pr " RETVAL = newSVpvn (%s, size);\n" n;
8467 pr " free (%s);\n" n;
8475 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8477 pr " struct guestfs_%s_list *%s;\n" typ n;
8481 pr " %s = guestfs_%s " n name;
8482 generate_c_call_args ~handle:"g" style;
8485 pr " if (%s == NULL)\n" n;
8486 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8487 pr " EXTEND (SP, %s->len);\n" n;
8488 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8489 pr " hv = newHV ();\n";
8493 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8494 name (String.length name) n name
8496 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8497 name (String.length name) n name
8499 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8500 name (String.length name) n name n name
8501 | name, (FBytes|FUInt64) ->
8502 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8503 name (String.length name) n name
8505 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8506 name (String.length name) n name
8507 | name, (FInt32|FUInt32) ->
8508 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8509 name (String.length name) n name
8511 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8512 name (String.length name) n name
8513 | name, FOptPercent ->
8514 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8515 name (String.length name) n name
8517 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8519 pr " guestfs_free_%s_list (%s);\n" typ n
8521 and generate_perl_struct_code typ cols name style n do_cleanups =
8523 pr " struct guestfs_%s *%s;\n" typ n;
8525 pr " %s = guestfs_%s " n name;
8526 generate_c_call_args ~handle:"g" style;
8529 pr " if (%s == NULL)\n" n;
8530 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8531 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8533 fun ((name, _) as col) ->
8534 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8538 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8541 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8544 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8546 | name, (FBytes|FUInt64) ->
8547 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8550 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8552 | name, (FInt32|FUInt32) ->
8553 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8556 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8558 | name, FOptPercent ->
8559 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8562 pr " free (%s);\n" n
8564 (* Generate Sys/Guestfs.pm. *)
8565 and generate_perl_pm () =
8566 generate_header HashStyle LGPLv2plus;
8573 Sys::Guestfs - Perl bindings for libguestfs
8579 my $h = Sys::Guestfs->new ();
8580 $h->add_drive ('guest.img');
8582 $h->mount ('/dev/sda1', '/');
8583 $h->touch ('/hello');
8588 The C<Sys::Guestfs> module provides a Perl XS binding to the
8589 libguestfs API for examining and modifying virtual machine
8592 Amongst the things this is good for: making batch configuration
8593 changes to guests, getting disk used/free statistics (see also:
8594 virt-df), migrating between virtualization systems (see also:
8595 virt-p2v), performing partial backups, performing partial guest
8596 clones, cloning guests and changing registry/UUID/hostname info, and
8599 Libguestfs uses Linux kernel and qemu code, and can access any type of
8600 guest filesystem that Linux and qemu can, including but not limited
8601 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8602 schemes, qcow, qcow2, vmdk.
8604 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8605 LVs, what filesystem is in each LV, etc.). It can also run commands
8606 in the context of the guest. Also you can access filesystems over
8609 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8610 functions for using libguestfs from Perl, including integration
8615 All errors turn into calls to C<croak> (see L<Carp(3)>).
8623 package Sys::Guestfs;
8629 XSLoader::load ('Sys::Guestfs');
8631 =item $h = Sys::Guestfs->new ();
8633 Create a new guestfs handle.
8639 my $class = ref ($proto) || $proto;
8641 my $self = Sys::Guestfs::_create ();
8642 bless $self, $class;
8648 (* Actions. We only need to print documentation for these as
8649 * they are pulled in from the XS code automatically.
8652 fun (name, style, _, flags, _, _, longdesc) ->
8653 if not (List.mem NotInDocs flags) then (
8654 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8656 generate_perl_prototype name style;
8658 pr "%s\n\n" longdesc;
8659 if List.mem ProtocolLimitWarning flags then
8660 pr "%s\n\n" protocol_limit_warning;
8661 if List.mem DangerWillRobinson flags then
8662 pr "%s\n\n" danger_will_robinson;
8663 match deprecation_notice flags with
8665 | Some txt -> pr "%s\n\n" txt
8667 ) all_functions_sorted;
8679 Copyright (C) %s Red Hat Inc.
8683 Please see the file COPYING.LIB for the full license.
8689 L<http://libguestfs.org>,
8690 L<Sys::Guestfs::Lib(3)>.
8695 and generate_perl_prototype name style =
8696 (match fst style with
8704 | RBufferOut n -> pr "$%s = " n
8706 | RHashtable n -> pr "%%%s = " n
8708 | RStructList (n,_) -> pr "@%s = " n
8711 let comma = ref false in
8714 if !comma then pr ", ";
8717 | Pathname n | Device n | Dev_or_Path n | String n
8718 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8720 | StringList n | DeviceList n ->
8725 (* Generate Python C module. *)
8726 and generate_python_c () =
8727 generate_header CStyle LGPLv2plus;
8736 #include \"guestfs.h\"
8744 get_handle (PyObject *obj)
8747 assert (obj != Py_None);
8748 return ((Pyguestfs_Object *) obj)->g;
8752 put_handle (guestfs_h *g)
8756 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8759 /* This list should be freed (but not the strings) after use. */
8761 get_string_list (PyObject *obj)
8768 if (!PyList_Check (obj)) {
8769 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8773 len = PyList_Size (obj);
8774 r = malloc (sizeof (char *) * (len+1));
8776 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8780 for (i = 0; i < len; ++i)
8781 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8788 put_string_list (char * const * const argv)
8793 for (argc = 0; argv[argc] != NULL; ++argc)
8796 list = PyList_New (argc);
8797 for (i = 0; i < argc; ++i)
8798 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8804 put_table (char * const * const argv)
8806 PyObject *list, *item;
8809 for (argc = 0; argv[argc] != NULL; ++argc)
8812 list = PyList_New (argc >> 1);
8813 for (i = 0; i < argc; i += 2) {
8814 item = PyTuple_New (2);
8815 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8816 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8817 PyList_SetItem (list, i >> 1, item);
8824 free_strings (char **argv)
8828 for (argc = 0; argv[argc] != NULL; ++argc)
8834 py_guestfs_create (PyObject *self, PyObject *args)
8838 g = guestfs_create ();
8840 PyErr_SetString (PyExc_RuntimeError,
8841 \"guestfs.create: failed to allocate handle\");
8844 guestfs_set_error_handler (g, NULL, NULL);
8845 return put_handle (g);
8849 py_guestfs_close (PyObject *self, PyObject *args)
8854 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8856 g = get_handle (py_g);
8860 Py_INCREF (Py_None);
8866 let emit_put_list_function typ =
8867 pr "static PyObject *\n";
8868 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8870 pr " PyObject *list;\n";
8873 pr " list = PyList_New (%ss->len);\n" typ;
8874 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8875 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8876 pr " return list;\n";
8881 (* Structures, turned into Python dictionaries. *)
8884 pr "static PyObject *\n";
8885 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8887 pr " PyObject *dict;\n";
8889 pr " dict = PyDict_New ();\n";
8893 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8894 pr " PyString_FromString (%s->%s));\n"
8897 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8898 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8901 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8902 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
8904 | name, (FBytes|FUInt64) ->
8905 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8906 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
8909 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8910 pr " PyLong_FromLongLong (%s->%s));\n"
8913 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8914 pr " PyLong_FromUnsignedLong (%s->%s));\n"
8917 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8918 pr " PyLong_FromLong (%s->%s));\n"
8920 | name, FOptPercent ->
8921 pr " if (%s->%s >= 0)\n" typ name;
8922 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8923 pr " PyFloat_FromDouble ((double) %s->%s));\n"
8926 pr " Py_INCREF (Py_None);\n";
8927 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8930 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8931 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8933 pr " return dict;\n";
8939 (* Emit a put_TYPE_list function definition only if that function is used. *)
8942 | typ, (RStructListOnly | RStructAndList) ->
8943 (* generate the function for typ *)
8944 emit_put_list_function typ
8945 | typ, _ -> () (* empty *)
8946 ) (rstructs_used_by all_functions);
8948 (* Python wrapper functions. *)
8950 fun (name, style, _, _, _, _, _) ->
8951 pr "static PyObject *\n";
8952 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8955 pr " PyObject *py_g;\n";
8956 pr " guestfs_h *g;\n";
8957 pr " PyObject *py_r;\n";
8960 match fst style with
8961 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8962 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8963 | RConstString _ | RConstOptString _ ->
8964 pr " const char *r;\n"; "NULL"
8965 | RString _ -> pr " char *r;\n"; "NULL"
8966 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8967 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8968 | RStructList (_, typ) ->
8969 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8972 pr " size_t size;\n";
8977 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8978 pr " const char *%s;\n" n
8979 | OptString n -> pr " const char *%s;\n" n
8980 | StringList n | DeviceList n ->
8981 pr " PyObject *py_%s;\n" n;
8982 pr " char **%s;\n" n
8983 | Bool n -> pr " int %s;\n" n
8984 | Int n -> pr " int %s;\n" n
8985 | Int64 n -> pr " long long %s;\n" n
8990 (* Convert the parameters. *)
8991 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
8994 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8995 | OptString _ -> pr "z"
8996 | StringList _ | DeviceList _ -> pr "O"
8997 | Bool _ -> pr "i" (* XXX Python has booleans? *)
8999 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9000 * emulate C's int/long/long long in Python?
9003 pr ":guestfs_%s\",\n" name;
9007 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9008 | OptString n -> pr ", &%s" n
9009 | StringList n | DeviceList n -> pr ", &py_%s" n
9010 | Bool n -> pr ", &%s" n
9011 | Int n -> pr ", &%s" n
9012 | Int64 n -> pr ", &%s" n
9016 pr " return NULL;\n";
9018 pr " g = get_handle (py_g);\n";
9021 | Pathname _ | Device _ | Dev_or_Path _ | String _
9022 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9023 | StringList n | DeviceList n ->
9024 pr " %s = get_string_list (py_%s);\n" n n;
9025 pr " if (!%s) return NULL;\n" n
9030 pr " r = guestfs_%s " name;
9031 generate_c_call_args ~handle:"g" style;
9036 | Pathname _ | Device _ | Dev_or_Path _ | String _
9037 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9038 | StringList n | DeviceList n ->
9039 pr " free (%s);\n" n
9042 pr " if (r == %s) {\n" error_code;
9043 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9044 pr " return NULL;\n";
9048 (match fst style with
9050 pr " Py_INCREF (Py_None);\n";
9051 pr " py_r = Py_None;\n"
9053 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9054 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9055 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9056 | RConstOptString _ ->
9058 pr " py_r = PyString_FromString (r);\n";
9060 pr " Py_INCREF (Py_None);\n";
9061 pr " py_r = Py_None;\n";
9064 pr " py_r = PyString_FromString (r);\n";
9067 pr " py_r = put_string_list (r);\n";
9068 pr " free_strings (r);\n"
9069 | RStruct (_, typ) ->
9070 pr " py_r = put_%s (r);\n" typ;
9071 pr " guestfs_free_%s (r);\n" typ
9072 | RStructList (_, typ) ->
9073 pr " py_r = put_%s_list (r);\n" typ;
9074 pr " guestfs_free_%s_list (r);\n" typ
9076 pr " py_r = put_table (r);\n";
9077 pr " free_strings (r);\n"
9079 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9083 pr " return py_r;\n";
9088 (* Table of functions. *)
9089 pr "static PyMethodDef methods[] = {\n";
9090 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9091 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9093 fun (name, _, _, _, _, _, _) ->
9094 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9097 pr " { NULL, NULL, 0, NULL }\n";
9101 (* Init function. *)
9104 initlibguestfsmod (void)
9106 static int initialized = 0;
9108 if (initialized) return;
9109 Py_InitModule ((char *) \"libguestfsmod\", methods);
9114 (* Generate Python module. *)
9115 and generate_python_py () =
9116 generate_header HashStyle LGPLv2plus;
9119 u\"\"\"Python bindings for libguestfs
9122 g = guestfs.GuestFS ()
9123 g.add_drive (\"guest.img\")
9125 parts = g.list_partitions ()
9127 The guestfs module provides a Python binding to the libguestfs API
9128 for examining and modifying virtual machine disk images.
9130 Amongst the things this is good for: making batch configuration
9131 changes to guests, getting disk used/free statistics (see also:
9132 virt-df), migrating between virtualization systems (see also:
9133 virt-p2v), performing partial backups, performing partial guest
9134 clones, cloning guests and changing registry/UUID/hostname info, and
9137 Libguestfs uses Linux kernel and qemu code, and can access any type of
9138 guest filesystem that Linux and qemu can, including but not limited
9139 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9140 schemes, qcow, qcow2, vmdk.
9142 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9143 LVs, what filesystem is in each LV, etc.). It can also run commands
9144 in the context of the guest. Also you can access filesystems over
9147 Errors which happen while using the API are turned into Python
9148 RuntimeError exceptions.
9150 To create a guestfs handle you usually have to perform the following
9153 # Create the handle, call add_drive at least once, and possibly
9154 # several times if the guest has multiple block devices:
9155 g = guestfs.GuestFS ()
9156 g.add_drive (\"guest.img\")
9158 # Launch the qemu subprocess and wait for it to become ready:
9161 # Now you can issue commands, for example:
9166 import libguestfsmod
9169 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9171 def __init__ (self):
9172 \"\"\"Create a new libguestfs handle.\"\"\"
9173 self._o = libguestfsmod.create ()
9176 libguestfsmod.close (self._o)
9181 fun (name, style, _, flags, _, _, longdesc) ->
9183 generate_py_call_args ~handle:"self" (snd style);
9186 if not (List.mem NotInDocs flags) then (
9187 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9189 match fst style with
9190 | RErr | RInt _ | RInt64 _ | RBool _
9191 | RConstOptString _ | RConstString _
9192 | RString _ | RBufferOut _ -> doc
9194 doc ^ "\n\nThis function returns a list of strings."
9195 | RStruct (_, typ) ->
9196 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9197 | RStructList (_, typ) ->
9198 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9200 doc ^ "\n\nThis function returns a dictionary." in
9202 if List.mem ProtocolLimitWarning flags then
9203 doc ^ "\n\n" ^ protocol_limit_warning
9206 if List.mem DangerWillRobinson flags then
9207 doc ^ "\n\n" ^ danger_will_robinson
9210 match deprecation_notice flags with
9212 | Some txt -> doc ^ "\n\n" ^ txt in
9213 let doc = pod2text ~width:60 name doc in
9214 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9215 let doc = String.concat "\n " doc in
9216 pr " u\"\"\"%s\"\"\"\n" doc;
9218 pr " return libguestfsmod.%s " name;
9219 generate_py_call_args ~handle:"self._o" (snd style);
9224 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9225 and generate_py_call_args ~handle args =
9227 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9230 (* Useful if you need the longdesc POD text as plain text. Returns a
9233 * Because this is very slow (the slowest part of autogeneration),
9234 * we memoize the results.
9236 and pod2text ~width name longdesc =
9237 let key = width, name, longdesc in
9238 try Hashtbl.find pod2text_memo key
9240 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9241 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9243 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9244 let chan = open_process_in cmd in
9245 let lines = ref [] in
9247 let line = input_line chan in
9248 if i = 1 then (* discard the first line of output *)
9251 let line = triml line in
9252 lines := line :: !lines;
9255 let lines = try loop 1 with End_of_file -> List.rev !lines in
9257 (match close_process_in chan with
9260 failwithf "pod2text: process exited with non-zero status (%d)" i
9261 | WSIGNALED i | WSTOPPED i ->
9262 failwithf "pod2text: process signalled or stopped by signal %d" i
9264 Hashtbl.add pod2text_memo key lines;
9265 pod2text_memo_updated ();
9268 (* Generate ruby bindings. *)
9269 and generate_ruby_c () =
9270 generate_header CStyle LGPLv2plus;
9278 #include \"guestfs.h\"
9280 #include \"extconf.h\"
9282 /* For Ruby < 1.9 */
9284 #define RARRAY_LEN(r) (RARRAY((r))->len)
9287 static VALUE m_guestfs; /* guestfs module */
9288 static VALUE c_guestfs; /* guestfs_h handle */
9289 static VALUE e_Error; /* used for all errors */
9291 static void ruby_guestfs_free (void *p)
9294 guestfs_close ((guestfs_h *) p);
9297 static VALUE ruby_guestfs_create (VALUE m)
9301 g = guestfs_create ();
9303 rb_raise (e_Error, \"failed to create guestfs handle\");
9305 /* Don't print error messages to stderr by default. */
9306 guestfs_set_error_handler (g, NULL, NULL);
9308 /* Wrap it, and make sure the close function is called when the
9311 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9314 static VALUE ruby_guestfs_close (VALUE gv)
9317 Data_Get_Struct (gv, guestfs_h, g);
9319 ruby_guestfs_free (g);
9320 DATA_PTR (gv) = NULL;
9328 fun (name, style, _, _, _, _, _) ->
9329 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9330 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9333 pr " guestfs_h *g;\n";
9334 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9336 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9342 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9343 pr " Check_Type (%sv, T_STRING);\n" n;
9344 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9346 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9347 pr " \"%s\", \"%s\");\n" n name
9349 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9350 | StringList n | DeviceList n ->
9351 pr " char **%s;\n" n;
9352 pr " Check_Type (%sv, T_ARRAY);\n" n;
9354 pr " int i, len;\n";
9355 pr " len = RARRAY_LEN (%sv);\n" n;
9356 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9358 pr " for (i = 0; i < len; ++i) {\n";
9359 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9360 pr " %s[i] = StringValueCStr (v);\n" n;
9362 pr " %s[len] = NULL;\n" n;
9365 pr " int %s = RTEST (%sv);\n" n n
9367 pr " int %s = NUM2INT (%sv);\n" n n
9369 pr " long long %s = NUM2LL (%sv);\n" n n
9374 match fst style with
9375 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9376 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9377 | RConstString _ | RConstOptString _ ->
9378 pr " const char *r;\n"; "NULL"
9379 | RString _ -> pr " char *r;\n"; "NULL"
9380 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9381 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9382 | RStructList (_, typ) ->
9383 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9386 pr " size_t size;\n";
9390 pr " r = guestfs_%s " name;
9391 generate_c_call_args ~handle:"g" style;
9396 | Pathname _ | Device _ | Dev_or_Path _ | String _
9397 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9398 | StringList n | DeviceList n ->
9399 pr " free (%s);\n" n
9402 pr " if (r == %s)\n" error_code;
9403 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9406 (match fst style with
9408 pr " return Qnil;\n"
9409 | RInt _ | RBool _ ->
9410 pr " return INT2NUM (r);\n"
9412 pr " return ULL2NUM (r);\n"
9414 pr " return rb_str_new2 (r);\n";
9415 | RConstOptString _ ->
9417 pr " return rb_str_new2 (r);\n";
9419 pr " return Qnil;\n";
9421 pr " VALUE rv = rb_str_new2 (r);\n";
9425 pr " int i, len = 0;\n";
9426 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9427 pr " VALUE rv = rb_ary_new2 (len);\n";
9428 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9429 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9430 pr " free (r[i]);\n";
9434 | RStruct (_, typ) ->
9435 let cols = cols_of_struct typ in
9436 generate_ruby_struct_code typ cols
9437 | RStructList (_, typ) ->
9438 let cols = cols_of_struct typ in
9439 generate_ruby_struct_list_code typ cols
9441 pr " VALUE rv = rb_hash_new ();\n";
9443 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9444 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9445 pr " free (r[i]);\n";
9446 pr " free (r[i+1]);\n";
9451 pr " VALUE rv = rb_str_new (r, size);\n";
9461 /* Initialize the module. */
9462 void Init__guestfs ()
9464 m_guestfs = rb_define_module (\"Guestfs\");
9465 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9466 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9468 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9469 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9472 (* Define the rest of the methods. *)
9474 fun (name, style, _, _, _, _, _) ->
9475 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9476 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9481 (* Ruby code to return a struct. *)
9482 and generate_ruby_struct_code typ cols =
9483 pr " VALUE rv = rb_hash_new ();\n";
9487 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9489 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9491 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9492 | name, (FBytes|FUInt64) ->
9493 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9495 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9497 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9499 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9500 | name, FOptPercent ->
9501 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9502 | name, FChar -> (* XXX wrong? *)
9503 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9505 pr " guestfs_free_%s (r);\n" typ;
9508 (* Ruby code to return a struct list. *)
9509 and generate_ruby_struct_list_code typ cols =
9510 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9512 pr " for (i = 0; i < r->len; ++i) {\n";
9513 pr " VALUE hv = rb_hash_new ();\n";
9517 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9519 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
9521 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9522 | name, (FBytes|FUInt64) ->
9523 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9525 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9527 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9529 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9530 | name, FOptPercent ->
9531 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9532 | name, FChar -> (* XXX wrong? *)
9533 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9535 pr " rb_ary_push (rv, hv);\n";
9537 pr " guestfs_free_%s_list (r);\n" typ;
9540 (* Generate Java bindings GuestFS.java file. *)
9541 and generate_java_java () =
9542 generate_header CStyle LGPLv2plus;
9545 package com.redhat.et.libguestfs;
9547 import java.util.HashMap;
9548 import com.redhat.et.libguestfs.LibGuestFSException;
9549 import com.redhat.et.libguestfs.PV;
9550 import com.redhat.et.libguestfs.VG;
9551 import com.redhat.et.libguestfs.LV;
9552 import com.redhat.et.libguestfs.Stat;
9553 import com.redhat.et.libguestfs.StatVFS;
9554 import com.redhat.et.libguestfs.IntBool;
9555 import com.redhat.et.libguestfs.Dirent;
9558 * The GuestFS object is a libguestfs handle.
9562 public class GuestFS {
9563 // Load the native code.
9565 System.loadLibrary (\"guestfs_jni\");
9569 * The native guestfs_h pointer.
9574 * Create a libguestfs handle.
9576 * @throws LibGuestFSException
9578 public GuestFS () throws LibGuestFSException
9582 private native long _create () throws LibGuestFSException;
9585 * Close a libguestfs handle.
9587 * You can also leave handles to be collected by the garbage
9588 * collector, but this method ensures that the resources used
9589 * by the handle are freed up immediately. If you call any
9590 * other methods after closing the handle, you will get an
9593 * @throws LibGuestFSException
9595 public void close () throws LibGuestFSException
9601 private native void _close (long g) throws LibGuestFSException;
9603 public void finalize () throws LibGuestFSException
9611 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9612 if not (List.mem NotInDocs flags); then (
9613 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9615 if List.mem ProtocolLimitWarning flags then
9616 doc ^ "\n\n" ^ protocol_limit_warning
9619 if List.mem DangerWillRobinson flags then
9620 doc ^ "\n\n" ^ danger_will_robinson
9623 match deprecation_notice flags with
9625 | Some txt -> doc ^ "\n\n" ^ txt in
9626 let doc = pod2text ~width:60 name doc in
9627 let doc = List.map ( (* RHBZ#501883 *)
9630 | nonempty -> nonempty
9632 let doc = String.concat "\n * " doc in
9635 pr " * %s\n" shortdesc;
9638 pr " * @throws LibGuestFSException\n";
9642 generate_java_prototype ~public:true ~semicolon:false name style;
9645 pr " if (g == 0)\n";
9646 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9649 if fst style <> RErr then pr "return ";
9651 generate_java_call_args ~handle:"g" (snd style);
9655 generate_java_prototype ~privat:true ~native:true name style;
9662 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9663 and generate_java_call_args ~handle args =
9665 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9668 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9669 ?(semicolon=true) name style =
9670 if privat then pr "private ";
9671 if public then pr "public ";
9672 if native then pr "native ";
9675 (match fst style with
9676 | RErr -> pr "void ";
9677 | RInt _ -> pr "int ";
9678 | RInt64 _ -> pr "long ";
9679 | RBool _ -> pr "boolean ";
9680 | RConstString _ | RConstOptString _ | RString _
9681 | RBufferOut _ -> pr "String ";
9682 | RStringList _ -> pr "String[] ";
9683 | RStruct (_, typ) ->
9684 let name = java_name_of_struct typ in
9686 | RStructList (_, typ) ->
9687 let name = java_name_of_struct typ in
9689 | RHashtable _ -> pr "HashMap<String,String> ";
9692 if native then pr "_%s " name else pr "%s " name;
9694 let needs_comma = ref false in
9703 if !needs_comma then pr ", ";
9704 needs_comma := true;
9708 | Device n | Dev_or_Path n
9714 | StringList n | DeviceList n ->
9725 pr " throws LibGuestFSException";
9726 if semicolon then pr ";"
9728 and generate_java_struct jtyp cols () =
9729 generate_header CStyle LGPLv2plus;
9732 package com.redhat.et.libguestfs;
9735 * Libguestfs %s structure.
9747 | name, FBuffer -> pr " public String %s;\n" name
9748 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9749 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9750 | name, FChar -> pr " public char %s;\n" name
9751 | name, FOptPercent ->
9752 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9753 pr " public float %s;\n" name
9758 and generate_java_c () =
9759 generate_header CStyle LGPLv2plus;
9766 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9767 #include \"guestfs.h\"
9769 /* Note that this function returns. The exception is not thrown
9770 * until after the wrapper function returns.
9773 throw_exception (JNIEnv *env, const char *msg)
9776 cl = (*env)->FindClass (env,
9777 \"com/redhat/et/libguestfs/LibGuestFSException\");
9778 (*env)->ThrowNew (env, cl, msg);
9781 JNIEXPORT jlong JNICALL
9782 Java_com_redhat_et_libguestfs_GuestFS__1create
9783 (JNIEnv *env, jobject obj)
9787 g = guestfs_create ();
9789 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9792 guestfs_set_error_handler (g, NULL, NULL);
9793 return (jlong) (long) g;
9796 JNIEXPORT void JNICALL
9797 Java_com_redhat_et_libguestfs_GuestFS__1close
9798 (JNIEnv *env, jobject obj, jlong jg)
9800 guestfs_h *g = (guestfs_h *) (long) jg;
9807 fun (name, style, _, _, _, _, _) ->
9809 (match fst style with
9810 | RErr -> pr "void ";
9811 | RInt _ -> pr "jint ";
9812 | RInt64 _ -> pr "jlong ";
9813 | RBool _ -> pr "jboolean ";
9814 | RConstString _ | RConstOptString _ | RString _
9815 | RBufferOut _ -> pr "jstring ";
9816 | RStruct _ | RHashtable _ ->
9818 | RStringList _ | RStructList _ ->
9822 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9823 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9825 pr " (JNIEnv *env, jobject obj, jlong jg";
9829 | Device n | Dev_or_Path n
9834 pr ", jstring j%s" n
9835 | StringList n | DeviceList n ->
9836 pr ", jobjectArray j%s" n
9838 pr ", jboolean j%s" n
9846 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9847 let error_code, no_ret =
9848 match fst style with
9849 | RErr -> pr " int r;\n"; "-1", ""
9851 | RInt _ -> pr " int r;\n"; "-1", "0"
9852 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9853 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9854 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9856 pr " jstring jr;\n";
9857 pr " char *r;\n"; "NULL", "NULL"
9859 pr " jobjectArray jr;\n";
9862 pr " jstring jstr;\n";
9863 pr " char **r;\n"; "NULL", "NULL"
9864 | RStruct (_, typ) ->
9865 pr " jobject jr;\n";
9867 pr " jfieldID fl;\n";
9868 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9869 | RStructList (_, typ) ->
9870 pr " jobjectArray jr;\n";
9872 pr " jfieldID fl;\n";
9873 pr " jobject jfl;\n";
9874 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9875 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9877 pr " jstring jr;\n";
9879 pr " size_t size;\n";
9884 | Device n | Dev_or_Path n
9889 pr " const char *%s;\n" n
9890 | StringList n | DeviceList n ->
9891 pr " int %s_len;\n" n;
9892 pr " const char **%s;\n" n
9897 pr " int64_t %s;\n" n
9901 (match fst style with
9902 | RStringList _ | RStructList _ -> true
9903 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9905 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9906 List.exists (function
9907 | StringList _ -> true
9908 | DeviceList _ -> true
9909 | _ -> false) (snd style) in
9915 (* Get the parameters. *)
9919 | Device n | Dev_or_Path n
9923 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9925 (* This is completely undocumented, but Java null becomes
9928 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9929 | StringList n | DeviceList n ->
9930 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9931 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9932 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9933 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9935 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9937 pr " %s[%s_len] = NULL;\n" n n;
9941 pr " %s = j%s;\n" n n
9944 (* Make the call. *)
9945 pr " r = guestfs_%s " name;
9946 generate_c_call_args ~handle:"g" style;
9949 (* Release the parameters. *)
9953 | Device n | Dev_or_Path n
9957 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9960 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9961 | StringList n | DeviceList n ->
9962 pr " for (i = 0; i < %s_len; ++i) {\n" n;
9963 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9965 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9967 pr " free (%s);\n" n
9973 (* Check for errors. *)
9974 pr " if (r == %s) {\n" error_code;
9975 pr " throw_exception (env, guestfs_last_error (g));\n";
9976 pr " return %s;\n" no_ret;
9980 (match fst style with
9982 | RInt _ -> pr " return (jint) r;\n"
9983 | RBool _ -> pr " return (jboolean) r;\n"
9984 | RInt64 _ -> pr " return (jlong) r;\n"
9985 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
9986 | RConstOptString _ ->
9987 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9989 pr " jr = (*env)->NewStringUTF (env, r);\n";
9993 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9994 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9995 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
9996 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9997 pr " for (i = 0; i < r_len; ++i) {\n";
9998 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
9999 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10000 pr " free (r[i]);\n";
10004 | RStruct (_, typ) ->
10005 let jtyp = java_name_of_struct typ in
10006 let cols = cols_of_struct typ in
10007 generate_java_struct_return typ jtyp cols
10008 | RStructList (_, typ) ->
10009 let jtyp = java_name_of_struct typ in
10010 let cols = cols_of_struct typ in
10011 generate_java_struct_list_return typ jtyp cols
10014 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10015 pr " return NULL;\n"
10017 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10026 and generate_java_struct_return typ jtyp cols =
10027 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10028 pr " jr = (*env)->AllocObject (env, cl);\n";
10032 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10033 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10036 pr " char s[33];\n";
10037 pr " memcpy (s, r->%s, 32);\n" name;
10038 pr " s[32] = 0;\n";
10039 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10040 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10044 pr " int len = r->%s_len;\n" name;
10045 pr " char s[len+1];\n";
10046 pr " memcpy (s, r->%s, len);\n" name;
10047 pr " s[len] = 0;\n";
10048 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10049 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10051 | name, (FBytes|FUInt64|FInt64) ->
10052 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10053 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10054 | name, (FUInt32|FInt32) ->
10055 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10056 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10057 | name, FOptPercent ->
10058 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10059 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10061 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10062 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10067 and generate_java_struct_list_return typ jtyp cols =
10068 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10069 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10070 pr " for (i = 0; i < r->len; ++i) {\n";
10071 pr " jfl = (*env)->AllocObject (env, cl);\n";
10075 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10076 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10079 pr " char s[33];\n";
10080 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10081 pr " s[32] = 0;\n";
10082 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10083 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10087 pr " int len = r->val[i].%s_len;\n" name;
10088 pr " char s[len+1];\n";
10089 pr " memcpy (s, r->val[i].%s, len);\n" name;
10090 pr " s[len] = 0;\n";
10091 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10092 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10094 | name, (FBytes|FUInt64|FInt64) ->
10095 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10096 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10097 | name, (FUInt32|FInt32) ->
10098 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10099 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10100 | name, FOptPercent ->
10101 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10102 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10104 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10105 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10107 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10109 pr " guestfs_free_%s_list (r);\n" typ;
10112 and generate_java_makefile_inc () =
10113 generate_header HashStyle GPLv2plus;
10115 pr "java_built_sources = \\\n";
10118 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10120 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10122 and generate_haskell_hs () =
10123 generate_header HaskellStyle LGPLv2plus;
10125 (* XXX We only know how to generate partial FFI for Haskell
10126 * at the moment. Please help out!
10128 let can_generate style =
10132 | RInt64 _, _ -> true
10134 | RConstString _, _
10135 | RConstOptString _, _
10141 | RBufferOut _, _ -> false in
10144 {-# INCLUDE <guestfs.h> #-}
10145 {-# LANGUAGE ForeignFunctionInterface #-}
10150 (* List out the names of the actions we want to export. *)
10152 fun (name, style, _, _, _, _, _) ->
10153 if can_generate style then pr ",\n %s" name
10159 -- Unfortunately some symbols duplicate ones already present
10160 -- in Prelude. We don't know which, so we hard-code a list
10162 import Prelude hiding (truncate)
10166 import Foreign.C.Types
10168 import Control.Exception
10169 import Data.Typeable
10171 data GuestfsS = GuestfsS -- represents the opaque C struct
10172 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10173 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10175 -- XXX define properly later XXX
10179 data IntBool = IntBool
10181 data StatVFS = StatVFS
10182 data Hashtable = Hashtable
10184 foreign import ccall unsafe \"guestfs_create\" c_create
10186 foreign import ccall unsafe \"&guestfs_close\" c_close
10187 :: FunPtr (GuestfsP -> IO ())
10188 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10189 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10191 create :: IO GuestfsH
10194 c_set_error_handler p nullPtr nullPtr
10195 h <- newForeignPtr c_close p
10198 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10199 :: GuestfsP -> IO CString
10201 -- last_error :: GuestfsH -> IO (Maybe String)
10202 -- last_error h = do
10203 -- str <- withForeignPtr h (\\p -> c_last_error p)
10204 -- maybePeek peekCString str
10206 last_error :: GuestfsH -> IO (String)
10208 str <- withForeignPtr h (\\p -> c_last_error p)
10209 if (str == nullPtr)
10210 then return \"no error\"
10211 else peekCString str
10215 (* Generate wrappers for each foreign function. *)
10217 fun (name, style, _, _, _, _, _) ->
10218 if can_generate style then (
10219 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10221 generate_haskell_prototype ~handle:"GuestfsP" style;
10225 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10227 pr "%s %s = do\n" name
10228 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10230 (* Convert pointer arguments using with* functions. *)
10235 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10236 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10237 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10238 | Bool _ | Int _ | Int64 _ -> ()
10240 (* Convert integer arguments. *)
10244 | Bool n -> sprintf "(fromBool %s)" n
10245 | Int n -> sprintf "(fromIntegral %s)" n
10246 | Int64 n -> sprintf "(fromIntegral %s)" n
10247 | FileIn n | FileOut n
10248 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10250 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10251 (String.concat " " ("p" :: args));
10252 (match fst style with
10253 | RErr | RInt _ | RInt64 _ | RBool _ ->
10254 pr " if (r == -1)\n";
10256 pr " err <- last_error h\n";
10258 | RConstString _ | RConstOptString _ | RString _
10259 | RStringList _ | RStruct _
10260 | RStructList _ | RHashtable _ | RBufferOut _ ->
10261 pr " if (r == nullPtr)\n";
10263 pr " err <- last_error h\n";
10266 (match fst style with
10268 pr " else return ()\n"
10270 pr " else return (fromIntegral r)\n"
10272 pr " else return (fromIntegral r)\n"
10274 pr " else return (toBool r)\n"
10276 | RConstOptString _
10283 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10289 and generate_haskell_prototype ~handle ?(hs = false) style =
10290 pr "%s -> " handle;
10291 let string = if hs then "String" else "CString" in
10292 let int = if hs then "Int" else "CInt" in
10293 let bool = if hs then "Bool" else "CInt" in
10294 let int64 = if hs then "Integer" else "Int64" in
10298 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10299 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10300 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10301 | Bool _ -> pr "%s" bool
10302 | Int _ -> pr "%s" int
10303 | Int64 _ -> pr "%s" int
10304 | FileIn _ -> pr "%s" string
10305 | FileOut _ -> pr "%s" string
10310 (match fst style with
10311 | RErr -> if not hs then pr "CInt"
10312 | RInt _ -> pr "%s" int
10313 | RInt64 _ -> pr "%s" int64
10314 | RBool _ -> pr "%s" bool
10315 | RConstString _ -> pr "%s" string
10316 | RConstOptString _ -> pr "Maybe %s" string
10317 | RString _ -> pr "%s" string
10318 | RStringList _ -> pr "[%s]" string
10319 | RStruct (_, typ) ->
10320 let name = java_name_of_struct typ in
10322 | RStructList (_, typ) ->
10323 let name = java_name_of_struct typ in
10325 | RHashtable _ -> pr "Hashtable"
10326 | RBufferOut _ -> pr "%s" string
10330 and generate_csharp () =
10331 generate_header CPlusPlusStyle LGPLv2plus;
10333 (* XXX Make this configurable by the C# assembly users. *)
10334 let library = "libguestfs.so.0" in
10337 // These C# bindings are highly experimental at present.
10339 // Firstly they only work on Linux (ie. Mono). In order to get them
10340 // to work on Windows (ie. .Net) you would need to port the library
10341 // itself to Windows first.
10343 // The second issue is that some calls are known to be incorrect and
10344 // can cause Mono to segfault. Particularly: calls which pass or
10345 // return string[], or return any structure value. This is because
10346 // we haven't worked out the correct way to do this from C#.
10348 // The third issue is that when compiling you get a lot of warnings.
10349 // We are not sure whether the warnings are important or not.
10351 // Fourthly we do not routinely build or test these bindings as part
10352 // of the make && make check cycle, which means that regressions might
10355 // Suggestions and patches are welcome.
10359 // gmcs Libguestfs.cs
10360 // mono Libguestfs.exe
10362 // (You'll probably want to add a Test class / static main function
10363 // otherwise this won't do anything useful).
10367 using System.Runtime.InteropServices;
10368 using System.Runtime.Serialization;
10369 using System.Collections;
10373 class Error : System.ApplicationException
10375 public Error (string message) : base (message) {}
10376 protected Error (SerializationInfo info, StreamingContext context) {}
10383 [DllImport (\"%s\")]
10384 static extern IntPtr guestfs_create ();
10388 _handle = guestfs_create ();
10389 if (_handle == IntPtr.Zero)
10390 throw new Error (\"could not create guestfs handle\");
10393 [DllImport (\"%s\")]
10394 static extern void guestfs_close (IntPtr h);
10398 guestfs_close (_handle);
10401 [DllImport (\"%s\")]
10402 static extern string guestfs_last_error (IntPtr h);
10404 " library library library;
10406 (* Generate C# structure bindings. We prefix struct names with
10407 * underscore because C# cannot have conflicting struct names and
10408 * method names (eg. "class stat" and "stat").
10412 pr " [StructLayout (LayoutKind.Sequential)]\n";
10413 pr " public class _%s {\n" typ;
10416 | name, FChar -> pr " char %s;\n" name
10417 | name, FString -> pr " string %s;\n" name
10419 pr " uint %s_len;\n" name;
10420 pr " string %s;\n" name
10422 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10423 pr " string %s;\n" name
10424 | name, FUInt32 -> pr " uint %s;\n" name
10425 | name, FInt32 -> pr " int %s;\n" name
10426 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10427 | name, FInt64 -> pr " long %s;\n" name
10428 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10434 (* Generate C# function bindings. *)
10436 fun (name, style, _, _, _, shortdesc, _) ->
10437 let rec csharp_return_type () =
10438 match fst style with
10440 | RBool n -> "bool"
10442 | RInt64 n -> "long"
10444 | RConstOptString n
10446 | RBufferOut n -> "string"
10447 | RStruct (_,n) -> "_" ^ n
10448 | RHashtable n -> "Hashtable"
10449 | RStringList n -> "string[]"
10450 | RStructList (_,n) -> sprintf "_%s[]" n
10452 and c_return_type () =
10453 match fst style with
10457 | RInt64 _ -> "long"
10459 | RConstOptString _
10461 | RBufferOut _ -> "string"
10462 | RStruct (_,n) -> "_" ^ n
10464 | RStringList _ -> "string[]"
10465 | RStructList (_,n) -> sprintf "_%s[]" n
10467 and c_error_comparison () =
10468 match fst style with
10472 | RInt64 _ -> "== -1"
10474 | RConstOptString _
10480 | RStructList (_,_) -> "== null"
10482 and generate_extern_prototype () =
10483 pr " static extern %s guestfs_%s (IntPtr h"
10484 (c_return_type ()) name;
10487 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10488 | FileIn n | FileOut n ->
10489 pr ", [In] string %s" n
10490 | StringList n | DeviceList n ->
10491 pr ", [In] string[] %s" n
10501 and generate_public_prototype () =
10502 pr " public %s %s (" (csharp_return_type ()) name;
10503 let comma = ref false in
10505 if !comma then pr ", ";
10510 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10511 | FileIn n | FileOut n ->
10512 next (); pr "string %s" n
10513 | StringList n | DeviceList n ->
10514 next (); pr "string[] %s" n
10516 next (); pr "bool %s" n
10518 next (); pr "int %s" n
10520 next (); pr "long %s" n
10524 and generate_call () =
10525 pr "guestfs_%s (_handle" name;
10526 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10530 pr " [DllImport (\"%s\")]\n" library;
10531 generate_extern_prototype ();
10533 pr " /// <summary>\n";
10534 pr " /// %s\n" shortdesc;
10535 pr " /// </summary>\n";
10536 generate_public_prototype ();
10538 pr " %s r;\n" (c_return_type ());
10541 pr " if (r %s)\n" (c_error_comparison ());
10542 pr " throw new Error (guestfs_last_error (_handle));\n";
10543 (match fst style with
10546 pr " return r != 0 ? true : false;\n"
10548 pr " Hashtable rr = new Hashtable ();\n";
10549 pr " for (int i = 0; i < r.Length; i += 2)\n";
10550 pr " rr.Add (r[i], r[i+1]);\n";
10552 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10553 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10559 ) all_functions_sorted;
10565 and generate_bindtests () =
10566 generate_header CStyle LGPLv2plus;
10570 #include <stdlib.h>
10571 #include <inttypes.h>
10572 #include <string.h>
10574 #include \"guestfs.h\"
10575 #include \"guestfs-internal.h\"
10576 #include \"guestfs-internal-actions.h\"
10577 #include \"guestfs_protocol.h\"
10579 #define error guestfs_error
10580 #define safe_calloc guestfs_safe_calloc
10581 #define safe_malloc guestfs_safe_malloc
10584 print_strings (char *const *argv)
10589 for (argc = 0; argv[argc] != NULL; ++argc) {
10590 if (argc > 0) printf (\", \");
10591 printf (\"\\\"%%s\\\"\", argv[argc]);
10596 /* The test0 function prints its parameters to stdout. */
10600 match test_functions with
10601 | [] -> assert false
10602 | test0 :: tests -> test0, tests in
10605 let (name, style, _, _, _, _, _) = test0 in
10606 generate_prototype ~extern:false ~semicolon:false ~newline:true
10607 ~handle:"g" ~prefix:"guestfs__" name style;
10612 | Device n | Dev_or_Path n
10615 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10616 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10617 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10618 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10619 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10620 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10622 pr " /* Java changes stdout line buffering so we need this: */\n";
10623 pr " fflush (stdout);\n";
10629 fun (name, style, _, _, _, _, _) ->
10630 if String.sub name (String.length name - 3) 3 <> "err" then (
10631 pr "/* Test normal return. */\n";
10632 generate_prototype ~extern:false ~semicolon:false ~newline:true
10633 ~handle:"g" ~prefix:"guestfs__" name style;
10635 (match fst style with
10640 pr " sscanf (val, \"%%d\", &r);\n";
10643 pr " int64_t r;\n";
10644 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10647 pr " return STREQ (val, \"true\");\n"
10649 | RConstOptString _ ->
10650 (* Can't return the input string here. Return a static
10651 * string so we ensure we get a segfault if the caller
10652 * tries to free it.
10654 pr " return \"static string\";\n"
10656 pr " return strdup (val);\n"
10658 pr " char **strs;\n";
10660 pr " sscanf (val, \"%%d\", &n);\n";
10661 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10662 pr " for (i = 0; i < n; ++i) {\n";
10663 pr " strs[i] = safe_malloc (g, 16);\n";
10664 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10666 pr " strs[n] = NULL;\n";
10667 pr " return strs;\n"
10668 | RStruct (_, typ) ->
10669 pr " struct guestfs_%s *r;\n" typ;
10670 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10672 | RStructList (_, typ) ->
10673 pr " struct guestfs_%s_list *r;\n" typ;
10674 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10675 pr " sscanf (val, \"%%d\", &r->len);\n";
10676 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10679 pr " char **strs;\n";
10681 pr " sscanf (val, \"%%d\", &n);\n";
10682 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10683 pr " for (i = 0; i < n; ++i) {\n";
10684 pr " strs[i*2] = safe_malloc (g, 16);\n";
10685 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10686 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10687 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10689 pr " strs[n*2] = NULL;\n";
10690 pr " return strs;\n"
10692 pr " return strdup (val);\n"
10697 pr "/* Test error return. */\n";
10698 generate_prototype ~extern:false ~semicolon:false ~newline:true
10699 ~handle:"g" ~prefix:"guestfs__" name style;
10701 pr " error (g, \"error\");\n";
10702 (match fst style with
10703 | RErr | RInt _ | RInt64 _ | RBool _ ->
10705 | RConstString _ | RConstOptString _
10706 | RString _ | RStringList _ | RStruct _
10710 pr " return NULL;\n"
10717 and generate_ocaml_bindtests () =
10718 generate_header OCamlStyle GPLv2plus;
10722 let g = Guestfs.create () in
10726 String.concat " " (
10729 | CallString s -> "\"" ^ s ^ "\""
10730 | CallOptString None -> "None"
10731 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10732 | CallStringList xs ->
10733 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10734 | CallInt i when i >= 0 -> string_of_int i
10735 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10736 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10737 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10738 | CallBool b -> string_of_bool b
10743 generate_lang_bindtests (
10744 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10747 pr "print_endline \"EOF\"\n"
10749 and generate_perl_bindtests () =
10750 pr "#!/usr/bin/perl -w\n";
10751 generate_header HashStyle GPLv2plus;
10758 my $g = Sys::Guestfs->new ();
10762 String.concat ", " (
10765 | CallString s -> "\"" ^ s ^ "\""
10766 | CallOptString None -> "undef"
10767 | CallOptString (Some s) -> sprintf "\"%s\"" s
10768 | CallStringList xs ->
10769 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10770 | CallInt i -> string_of_int i
10771 | CallInt64 i -> Int64.to_string i
10772 | CallBool b -> if b then "1" else "0"
10777 generate_lang_bindtests (
10778 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10781 pr "print \"EOF\\n\"\n"
10783 and generate_python_bindtests () =
10784 generate_header HashStyle GPLv2plus;
10789 g = guestfs.GuestFS ()
10793 String.concat ", " (
10796 | CallString s -> "\"" ^ s ^ "\""
10797 | CallOptString None -> "None"
10798 | CallOptString (Some s) -> sprintf "\"%s\"" s
10799 | CallStringList xs ->
10800 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10801 | CallInt i -> string_of_int i
10802 | CallInt64 i -> Int64.to_string i
10803 | CallBool b -> if b then "1" else "0"
10808 generate_lang_bindtests (
10809 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10812 pr "print \"EOF\"\n"
10814 and generate_ruby_bindtests () =
10815 generate_header HashStyle GPLv2plus;
10820 g = Guestfs::create()
10824 String.concat ", " (
10827 | CallString s -> "\"" ^ s ^ "\""
10828 | CallOptString None -> "nil"
10829 | CallOptString (Some s) -> sprintf "\"%s\"" s
10830 | CallStringList xs ->
10831 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10832 | CallInt i -> string_of_int i
10833 | CallInt64 i -> Int64.to_string i
10834 | CallBool b -> string_of_bool b
10839 generate_lang_bindtests (
10840 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10843 pr "print \"EOF\\n\"\n"
10845 and generate_java_bindtests () =
10846 generate_header CStyle GPLv2plus;
10849 import com.redhat.et.libguestfs.*;
10851 public class Bindtests {
10852 public static void main (String[] argv)
10855 GuestFS g = new GuestFS ();
10859 String.concat ", " (
10862 | CallString s -> "\"" ^ s ^ "\""
10863 | CallOptString None -> "null"
10864 | CallOptString (Some s) -> sprintf "\"%s\"" s
10865 | CallStringList xs ->
10867 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10868 | CallInt i -> string_of_int i
10869 | CallInt64 i -> Int64.to_string i
10870 | CallBool b -> string_of_bool b
10875 generate_lang_bindtests (
10876 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10880 System.out.println (\"EOF\");
10882 catch (Exception exn) {
10883 System.err.println (exn);
10890 and generate_haskell_bindtests () =
10891 generate_header HaskellStyle GPLv2plus;
10894 module Bindtests where
10895 import qualified Guestfs
10898 g <- Guestfs.create
10902 String.concat " " (
10905 | CallString s -> "\"" ^ s ^ "\""
10906 | CallOptString None -> "Nothing"
10907 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10908 | CallStringList xs ->
10909 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10910 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10911 | CallInt i -> string_of_int i
10912 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10913 | CallInt64 i -> Int64.to_string i
10914 | CallBool true -> "True"
10915 | CallBool false -> "False"
10920 generate_lang_bindtests (
10921 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
10924 pr " putStrLn \"EOF\"\n"
10926 (* Language-independent bindings tests - we do it this way to
10927 * ensure there is parity in testing bindings across all languages.
10929 and generate_lang_bindtests call =
10930 call "test0" [CallString "abc"; CallOptString (Some "def");
10931 CallStringList []; CallBool false;
10932 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10933 call "test0" [CallString "abc"; CallOptString None;
10934 CallStringList []; CallBool false;
10935 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10936 call "test0" [CallString ""; CallOptString (Some "def");
10937 CallStringList []; CallBool false;
10938 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10939 call "test0" [CallString ""; CallOptString (Some "");
10940 CallStringList []; CallBool false;
10941 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10942 call "test0" [CallString "abc"; CallOptString (Some "def");
10943 CallStringList ["1"]; CallBool false;
10944 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10945 call "test0" [CallString "abc"; CallOptString (Some "def");
10946 CallStringList ["1"; "2"]; CallBool false;
10947 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10948 call "test0" [CallString "abc"; CallOptString (Some "def");
10949 CallStringList ["1"]; CallBool true;
10950 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10951 call "test0" [CallString "abc"; CallOptString (Some "def");
10952 CallStringList ["1"]; CallBool false;
10953 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10954 call "test0" [CallString "abc"; CallOptString (Some "def");
10955 CallStringList ["1"]; CallBool false;
10956 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10957 call "test0" [CallString "abc"; CallOptString (Some "def");
10958 CallStringList ["1"]; CallBool false;
10959 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10960 call "test0" [CallString "abc"; CallOptString (Some "def");
10961 CallStringList ["1"]; CallBool false;
10962 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10963 call "test0" [CallString "abc"; CallOptString (Some "def");
10964 CallStringList ["1"]; CallBool false;
10965 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10966 call "test0" [CallString "abc"; CallOptString (Some "def");
10967 CallStringList ["1"]; CallBool false;
10968 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10970 (* XXX Add here tests of the return and error functions. *)
10972 (* Code to generator bindings for virt-inspector. Currently only
10973 * implemented for OCaml code (for virt-p2v 2.0).
10975 let rng_input = "inspector/virt-inspector.rng"
10977 (* Read the input file and parse it into internal structures. This is
10978 * by no means a complete RELAX NG parser, but is just enough to be
10979 * able to parse the specific input file.
10982 | Element of string * rng list (* <element name=name/> *)
10983 | Attribute of string * rng list (* <attribute name=name/> *)
10984 | Interleave of rng list (* <interleave/> *)
10985 | ZeroOrMore of rng (* <zeroOrMore/> *)
10986 | OneOrMore of rng (* <oneOrMore/> *)
10987 | Optional of rng (* <optional/> *)
10988 | Choice of string list (* <choice><value/>*</choice> *)
10989 | Value of string (* <value>str</value> *)
10990 | Text (* <text/> *)
10992 let rec string_of_rng = function
10993 | Element (name, xs) ->
10994 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10995 | Attribute (name, xs) ->
10996 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10997 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10998 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10999 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11000 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11001 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11002 | Value value -> "Value \"" ^ value ^ "\""
11005 and string_of_rng_list xs =
11006 String.concat ", " (List.map string_of_rng xs)
11008 let rec parse_rng ?defines context = function
11010 | Xml.Element ("element", ["name", name], children) :: rest ->
11011 Element (name, parse_rng ?defines context children)
11012 :: parse_rng ?defines context rest
11013 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11014 Attribute (name, parse_rng ?defines context children)
11015 :: parse_rng ?defines context rest
11016 | Xml.Element ("interleave", [], children) :: rest ->
11017 Interleave (parse_rng ?defines context children)
11018 :: parse_rng ?defines context rest
11019 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11020 let rng = parse_rng ?defines context [child] in
11022 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11024 failwithf "%s: <zeroOrMore> contains more than one child element"
11027 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11028 let rng = parse_rng ?defines context [child] in
11030 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11032 failwithf "%s: <oneOrMore> contains more than one child element"
11035 | Xml.Element ("optional", [], [child]) :: rest ->
11036 let rng = parse_rng ?defines context [child] in
11038 | [child] -> Optional child :: parse_rng ?defines context rest
11040 failwithf "%s: <optional> contains more than one child element"
11043 | Xml.Element ("choice", [], children) :: rest ->
11044 let values = List.map (
11045 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11047 failwithf "%s: can't handle anything except <value> in <choice>"
11051 :: parse_rng ?defines context rest
11052 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11053 Value value :: parse_rng ?defines context rest
11054 | Xml.Element ("text", [], []) :: rest ->
11055 Text :: parse_rng ?defines context rest
11056 | Xml.Element ("ref", ["name", name], []) :: rest ->
11057 (* Look up the reference. Because of limitations in this parser,
11058 * we can't handle arbitrarily nested <ref> yet. You can only
11059 * use <ref> from inside <start>.
11061 (match defines with
11063 failwithf "%s: contains <ref>, but no refs are defined yet" context
11065 let rng = StringMap.find name map in
11066 rng @ parse_rng ?defines context rest
11069 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11072 let xml = Xml.parse_file rng_input in
11074 | Xml.Element ("grammar", _,
11075 Xml.Element ("start", _, gram) :: defines) ->
11076 (* The <define/> elements are referenced in the <start> section,
11077 * so build a map of those first.
11079 let defines = List.fold_left (
11081 function Xml.Element ("define", ["name", name], defn) ->
11082 StringMap.add name defn map
11084 failwithf "%s: expected <define name=name/>" rng_input
11085 ) StringMap.empty defines in
11086 let defines = StringMap.mapi parse_rng defines in
11088 (* Parse the <start> clause, passing the defines. *)
11089 parse_rng ~defines "<start>" gram
11091 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11094 let name_of_field = function
11095 | Element (name, _) | Attribute (name, _)
11096 | ZeroOrMore (Element (name, _))
11097 | OneOrMore (Element (name, _))
11098 | Optional (Element (name, _)) -> name
11099 | Optional (Attribute (name, _)) -> name
11100 | Text -> (* an unnamed field in an element *)
11103 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11105 (* At the moment this function only generates OCaml types. However we
11106 * should parameterize it later so it can generate types/structs in a
11107 * variety of languages.
11109 let generate_types xs =
11110 (* A simple type is one that can be printed out directly, eg.
11111 * "string option". A complex type is one which has a name and has
11112 * to be defined via another toplevel definition, eg. a struct.
11114 * generate_type generates code for either simple or complex types.
11115 * In the simple case, it returns the string ("string option"). In
11116 * the complex case, it returns the name ("mountpoint"). In the
11117 * complex case it has to print out the definition before returning,
11118 * so it should only be called when we are at the beginning of a
11119 * new line (BOL context).
11121 let rec generate_type = function
11122 | Text -> (* string *)
11124 | Choice values -> (* [`val1|`val2|...] *)
11125 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11126 | ZeroOrMore rng -> (* <rng> list *)
11127 let t, is_simple = generate_type rng in
11128 t ^ " list (* 0 or more *)", is_simple
11129 | OneOrMore rng -> (* <rng> list *)
11130 let t, is_simple = generate_type rng in
11131 t ^ " list (* 1 or more *)", is_simple
11132 (* virt-inspector hack: bool *)
11133 | Optional (Attribute (name, [Value "1"])) ->
11135 | Optional rng -> (* <rng> list *)
11136 let t, is_simple = generate_type rng in
11137 t ^ " option", is_simple
11138 (* type name = { fields ... } *)
11139 | Element (name, fields) when is_attrs_interleave fields ->
11140 generate_type_struct name (get_attrs_interleave fields)
11141 | Element (name, [field]) (* type name = field *)
11142 | Attribute (name, [field]) ->
11143 let t, is_simple = generate_type field in
11144 if is_simple then (t, true)
11146 pr "type %s = %s\n" name t;
11149 | Element (name, fields) -> (* type name = { fields ... } *)
11150 generate_type_struct name fields
11152 failwithf "generate_type failed at: %s" (string_of_rng rng)
11154 and is_attrs_interleave = function
11155 | [Interleave _] -> true
11156 | Attribute _ :: fields -> is_attrs_interleave fields
11157 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11160 and get_attrs_interleave = function
11161 | [Interleave fields] -> fields
11162 | ((Attribute _) as field) :: fields
11163 | ((Optional (Attribute _)) as field) :: fields ->
11164 field :: get_attrs_interleave fields
11165 | _ -> assert false
11167 and generate_types xs =
11168 List.iter (fun x -> ignore (generate_type x)) xs
11170 and generate_type_struct name fields =
11171 (* Calculate the types of the fields first. We have to do this
11172 * before printing anything so we are still in BOL context.
11174 let types = List.map fst (List.map generate_type fields) in
11176 (* Special case of a struct containing just a string and another
11177 * field. Turn it into an assoc list.
11180 | ["string"; other] ->
11181 let fname1, fname2 =
11183 | [f1; f2] -> name_of_field f1, name_of_field f2
11184 | _ -> assert false in
11185 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11189 pr "type %s = {\n" name;
11191 fun (field, ftype) ->
11192 let fname = name_of_field field in
11193 pr " %s_%s : %s;\n" name fname ftype
11194 ) (List.combine fields types);
11196 (* Return the name of this type, and
11197 * false because it's not a simple type.
11204 let generate_parsers xs =
11205 (* As for generate_type above, generate_parser makes a parser for
11206 * some type, and returns the name of the parser it has generated.
11207 * Because it (may) need to print something, it should always be
11208 * called in BOL context.
11210 let rec generate_parser = function
11211 | Text -> (* string *)
11212 "string_child_or_empty"
11213 | Choice values -> (* [`val1|`val2|...] *)
11214 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11216 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11217 | ZeroOrMore rng -> (* <rng> list *)
11218 let pa = generate_parser rng in
11219 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11220 | OneOrMore rng -> (* <rng> list *)
11221 let pa = generate_parser rng in
11222 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11223 (* virt-inspector hack: bool *)
11224 | Optional (Attribute (name, [Value "1"])) ->
11225 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11226 | Optional rng -> (* <rng> list *)
11227 let pa = generate_parser rng in
11228 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11229 (* type name = { fields ... } *)
11230 | Element (name, fields) when is_attrs_interleave fields ->
11231 generate_parser_struct name (get_attrs_interleave fields)
11232 | Element (name, [field]) -> (* type name = field *)
11233 let pa = generate_parser field in
11234 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11235 pr "let %s =\n" parser_name;
11237 pr "let parse_%s = %s\n" name parser_name;
11239 | Attribute (name, [field]) ->
11240 let pa = generate_parser field in
11241 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11242 pr "let %s =\n" parser_name;
11244 pr "let parse_%s = %s\n" name parser_name;
11246 | Element (name, fields) -> (* type name = { fields ... } *)
11247 generate_parser_struct name ([], fields)
11249 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11251 and is_attrs_interleave = function
11252 | [Interleave _] -> true
11253 | Attribute _ :: fields -> is_attrs_interleave fields
11254 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11257 and get_attrs_interleave = function
11258 | [Interleave fields] -> [], fields
11259 | ((Attribute _) as field) :: fields
11260 | ((Optional (Attribute _)) as field) :: fields ->
11261 let attrs, interleaves = get_attrs_interleave fields in
11262 (field :: attrs), interleaves
11263 | _ -> assert false
11265 and generate_parsers xs =
11266 List.iter (fun x -> ignore (generate_parser x)) xs
11268 and generate_parser_struct name (attrs, interleaves) =
11269 (* Generate parsers for the fields first. We have to do this
11270 * before printing anything so we are still in BOL context.
11272 let fields = attrs @ interleaves in
11273 let pas = List.map generate_parser fields in
11275 (* Generate an intermediate tuple from all the fields first.
11276 * If the type is just a string + another field, then we will
11277 * return this directly, otherwise it is turned into a record.
11279 * RELAX NG note: This code treats <interleave> and plain lists of
11280 * fields the same. In other words, it doesn't bother enforcing
11281 * any ordering of fields in the XML.
11283 pr "let parse_%s x =\n" name;
11284 pr " let t = (\n ";
11285 let comma = ref false in
11288 if !comma then pr ",\n ";
11291 | Optional (Attribute (fname, [field])), pa ->
11293 | Optional (Element (fname, [field])), pa ->
11294 pr "%s (optional_child %S x)" pa fname
11295 | Attribute (fname, [Text]), _ ->
11296 pr "attribute %S x" fname
11297 | (ZeroOrMore _ | OneOrMore _), pa ->
11302 let fname = name_of_field field in
11303 pr "%s (child %S x)" pa fname
11304 ) (List.combine fields pas);
11308 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11312 pr " (Obj.magic t : %s)\n" name
11316 | (Optional (Attribute (fname, [field])), pa) ->
11317 pr " %s_%s =\n" name fname;
11319 | (Optional (Element (fname, [field])), pa) ->
11320 pr " %s_%s =\n" name fname;
11321 pr " (let x = optional_child %S x in\n" fname;
11324 let fname = name_of_field field in
11325 pr " %s_%s =\n" name fname;
11326 pr " (let x = child %S x in\n" fname;
11328 ) (List.combine fields pas);
11332 sprintf "parse_%s" name
11335 generate_parsers xs
11337 (* Generate ocaml/guestfs_inspector.mli. *)
11338 let generate_ocaml_inspector_mli () =
11339 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11342 (** This is an OCaml language binding to the external [virt-inspector]
11345 For more information, please read the man page [virt-inspector(1)].
11350 generate_types grammar;
11351 pr "(** The nested information returned from the {!inspect} function. *)\n";
11355 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11356 (** To inspect a libvirt domain called [name], pass a singleton
11357 list: [inspect [name]]. When using libvirt only, you may
11358 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11360 To inspect a disk image or images, pass a list of the filenames
11361 of the disk images: [inspect filenames]
11363 This function inspects the given guest or disk images and
11364 returns a list of operating system(s) found and a large amount
11365 of information about them. In the vast majority of cases,
11366 a virtual machine only contains a single operating system.
11368 If the optional [~xml] parameter is given, then this function
11369 skips running the external virt-inspector program and just
11370 parses the given XML directly (which is expected to be XML
11371 produced from a previous run of virt-inspector). The list of
11372 names and connect URI are ignored in this case.
11374 This function can throw a wide variety of exceptions, for example
11375 if the external virt-inspector program cannot be found, or if
11376 it doesn't generate valid XML.
11380 (* Generate ocaml/guestfs_inspector.ml. *)
11381 let generate_ocaml_inspector_ml () =
11382 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11387 generate_types grammar;
11391 (* Misc functions which are used by the parser code below. *)
11392 let first_child = function
11393 | Xml.Element (_, _, c::_) -> c
11394 | Xml.Element (name, _, []) ->
11395 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11396 | Xml.PCData str ->
11397 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11399 let string_child_or_empty = function
11400 | Xml.Element (_, _, [Xml.PCData s]) -> s
11401 | Xml.Element (_, _, []) -> \"\"
11402 | Xml.Element (x, _, _) ->
11403 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11405 | Xml.PCData str ->
11406 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11408 let optional_child name xml =
11409 let children = Xml.children xml in
11411 Some (List.find (function
11412 | Xml.Element (n, _, _) when n = name -> true
11413 | _ -> false) children)
11417 let child name xml =
11418 match optional_child name xml with
11421 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11423 let attribute name xml =
11424 try Xml.attrib xml name
11425 with Xml.No_attribute _ ->
11426 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11430 generate_parsers grammar;
11434 (* Run external virt-inspector, then use parser to parse the XML. *)
11435 let inspect ?connect ?xml names =
11439 if names = [] then invalid_arg \"inspect: no names given\";
11440 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11441 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11443 let cmd = List.map Filename.quote cmd in
11444 let cmd = String.concat \" \" cmd in
11445 let chan = open_process_in cmd in
11446 let xml = Xml.parse_in chan in
11447 (match close_process_in chan with
11449 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11450 | WSIGNALED i | WSTOPPED i ->
11451 failwith (\"external virt-inspector command died or stopped on sig \" ^
11456 Xml.parse_string doc in
11457 parse_operatingsystems xml
11460 (* This is used to generate the src/MAX_PROC_NR file which
11461 * contains the maximum procedure number, a surrogate for the
11462 * ABI version number. See src/Makefile.am for the details.
11464 and generate_max_proc_nr () =
11465 let proc_nrs = List.map (
11466 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11467 ) daemon_functions in
11469 let max_proc_nr = List.fold_left max 0 proc_nrs in
11471 pr "%d\n" max_proc_nr
11473 let output_to filename k =
11474 let filename_new = filename ^ ".new" in
11475 chan := open_out filename_new;
11478 chan := Pervasives.stdout;
11480 (* Is the new file different from the current file? *)
11481 if Sys.file_exists filename && files_equal filename filename_new then
11482 unlink filename_new (* same, so skip it *)
11484 (* different, overwrite old one *)
11485 (try chmod filename 0o644 with Unix_error _ -> ());
11486 rename filename_new filename;
11487 chmod filename 0o444;
11488 printf "written %s\n%!" filename;
11491 let perror msg = function
11492 | Unix_error (err, _, _) ->
11493 eprintf "%s: %s\n" msg (error_message err)
11495 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11497 (* Main program. *)
11500 try openfile "HACKING" [O_RDWR] 0
11502 | Unix_error (ENOENT, _, _) ->
11504 You are probably running this from the wrong directory.
11505 Run it from the top source directory using the command
11510 perror "open: HACKING" exn;
11513 (* Acquire a lock so parallel builds won't try to run the generator
11514 * twice at the same time. Subsequent builds will wait for the first
11515 * one to finish. Note the lock is released implicitly when the
11518 (try lockf lock_fd F_LOCK 1
11520 perror "lock: HACKING" exn;
11523 check_functions ();
11525 output_to "src/guestfs_protocol.x" generate_xdr;
11526 output_to "src/guestfs-structs.h" generate_structs_h;
11527 output_to "src/guestfs-actions.h" generate_actions_h;
11528 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11529 output_to "src/guestfs-actions.c" generate_client_actions;
11530 output_to "src/guestfs-bindtests.c" generate_bindtests;
11531 output_to "src/guestfs-structs.pod" generate_structs_pod;
11532 output_to "src/guestfs-actions.pod" generate_actions_pod;
11533 output_to "src/guestfs-availability.pod" generate_availability_pod;
11534 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11535 output_to "src/libguestfs.syms" generate_linker_script;
11536 output_to "daemon/actions.h" generate_daemon_actions_h;
11537 output_to "daemon/stubs.c" generate_daemon_actions;
11538 output_to "daemon/names.c" generate_daemon_names;
11539 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11540 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11541 output_to "capitests/tests.c" generate_tests;
11542 output_to "fish/cmds.c" generate_fish_cmds;
11543 output_to "fish/completion.c" generate_fish_completion;
11544 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11545 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11546 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11547 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11548 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11549 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11550 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11551 output_to "perl/Guestfs.xs" generate_perl_xs;
11552 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11553 output_to "perl/bindtests.pl" generate_perl_bindtests;
11554 output_to "python/guestfs-py.c" generate_python_c;
11555 output_to "python/guestfs.py" generate_python_py;
11556 output_to "python/bindtests.py" generate_python_bindtests;
11557 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11558 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11559 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11563 let cols = cols_of_struct typ in
11564 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11565 output_to filename (generate_java_struct jtyp cols);
11568 output_to "java/Makefile.inc" generate_java_makefile_inc;
11569 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11570 output_to "java/Bindtests.java" generate_java_bindtests;
11571 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11572 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11573 output_to "csharp/Libguestfs.cs" generate_csharp;
11575 (* Always generate this file last, and unconditionally. It's used
11576 * by the Makefile to know when we must re-run the generator.
11578 let chan = open_out "src/stamp-generator" in
11579 fprintf chan "1\n";
11582 printf "generated %d lines of code\n" !lines