3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | FishOutput of fish_output_t (* how to display output in guestfish *)
186 | NotInFish (* do not export via guestfish *)
187 | NotInDocs (* do not add this function to documentation *)
188 | DeprecatedBy of string (* function is deprecated, use .. instead *)
189 | Optional of string (* function is part of an optional group *)
192 | FishOutputOctal (* for int return, print in octal *)
193 | FishOutputHexadecimal (* for int return, print in hex *)
195 (* You can supply zero or as many tests as you want per API call.
197 * Note that the test environment has 3 block devices, of size 500MB,
198 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199 * a fourth ISO block device with some known files on it (/dev/sdd).
201 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202 * Number of cylinders was 63 for IDE emulated disks with precisely
203 * the same size. How exactly this is calculated is a mystery.
205 * The ISO block device (/dev/sdd) comes from images/test.iso.
207 * To be able to run the tests in a reasonable amount of time,
208 * the virtual machine and block devices are reused between tests.
209 * So don't try testing kill_subprocess :-x
211 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
213 * Don't assume anything about the previous contents of the block
214 * devices. Use 'Init*' to create some initial scenarios.
216 * You can add a prerequisite clause to any individual test. This
217 * is a run-time check, which, if it fails, causes the test to be
218 * skipped. Useful if testing a command which might not work on
219 * all variations of libguestfs builds. A test that has prerequisite
220 * of 'Always' is run unconditionally.
222 * In addition, packagers can skip individual tests by setting the
223 * environment variables: eg:
224 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
225 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
227 type tests = (test_init * test_prereq * test) list
229 (* Run the command sequence and just expect nothing to fail. *)
232 (* Run the command sequence and expect the output of the final
233 * command to be the string.
235 | TestOutput of seq * string
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of strings.
240 | TestOutputList of seq * string list
242 (* Run the command sequence and expect the output of the final
243 * command to be the list of block devices (could be either
244 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245 * character of each string).
247 | TestOutputListOfDevices of seq * string list
249 (* Run the command sequence and expect the output of the final
250 * command to be the integer.
252 | TestOutputInt of seq * int
254 (* Run the command sequence and expect the output of the final
255 * command to be <op> <int>, eg. ">=", "1".
257 | TestOutputIntOp of seq * string * int
259 (* Run the command sequence and expect the output of the final
260 * command to be a true value (!= 0 or != NULL).
262 | TestOutputTrue of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a false value (== 0 or == NULL, but not an error).
267 | TestOutputFalse of seq
269 (* Run the command sequence and expect the output of the final
270 * command to be a list of the given length (but don't care about
273 | TestOutputLength of seq * int
275 (* Run the command sequence and expect the output of the final
276 * command to be a buffer (RBufferOut), ie. string + size.
278 | TestOutputBuffer of seq * string
280 (* Run the command sequence and expect the output of the final
281 * command to be a structure.
283 | TestOutputStruct of seq * test_field_compare list
285 (* Run the command sequence and expect the final command (only)
288 | TestLastFail of seq
290 and test_field_compare =
291 | CompareWithInt of string * int
292 | CompareWithIntOp of string * string * int
293 | CompareWithString of string * string
294 | CompareFieldsIntEq of string * string
295 | CompareFieldsStrEq of string * string
297 (* Test prerequisites. *)
299 (* Test always runs. *)
302 (* Test is currently disabled - eg. it fails, or it tests some
303 * unimplemented feature.
307 (* 'string' is some C code (a function body) that should return
308 * true or false. The test will run if the code returns true.
312 (* As for 'If' but the test runs _unless_ the code returns true. *)
315 (* Some initial scenarios for testing. *)
317 (* Do nothing, block devices could contain random stuff including
318 * LVM PVs, and some filesystems might be mounted. This is usually
323 (* Block devices are empty and no filesystems are mounted. *)
326 (* /dev/sda contains a single partition /dev/sda1, with random
327 * content. /dev/sdb and /dev/sdc may have random content.
332 (* /dev/sda contains a single partition /dev/sda1, which is formatted
333 * as ext2, empty [except for lost+found] and mounted on /.
334 * /dev/sdb and /dev/sdc may have random content.
340 * /dev/sda1 (is a PV):
341 * /dev/VG/LV (size 8MB):
342 * formatted as ext2, empty [except for lost+found], mounted on /
343 * /dev/sdb and /dev/sdc may have random content.
347 (* /dev/sdd (the ISO, see images/ directory in source)
352 (* Sequence of commands for testing. *)
354 and cmd = string list
356 (* Note about long descriptions: When referring to another
357 * action, use the format C<guestfs_other> (ie. the full name of
358 * the C function). This will be replaced as appropriate in other
361 * Apart from that, long descriptions are just perldoc paragraphs.
364 (* Generate a random UUID (used in tests). *)
366 let chan = open_process_in "uuidgen" in
367 let uuid = input_line chan in
368 (match close_process_in chan with
371 failwith "uuidgen: process exited with non-zero status"
372 | WSIGNALED _ | WSTOPPED _ ->
373 failwith "uuidgen: process signalled or stopped by signal"
377 (* These test functions are used in the language binding tests. *)
379 let test_all_args = [
382 StringList "strlist";
390 let test_all_rets = [
391 (* except for RErr, which is tested thoroughly elsewhere *)
392 "test0rint", RInt "valout";
393 "test0rint64", RInt64 "valout";
394 "test0rbool", RBool "valout";
395 "test0rconststring", RConstString "valout";
396 "test0rconstoptstring", RConstOptString "valout";
397 "test0rstring", RString "valout";
398 "test0rstringlist", RStringList "valout";
399 "test0rstruct", RStruct ("valout", "lvm_pv");
400 "test0rstructlist", RStructList ("valout", "lvm_pv");
401 "test0rhashtable", RHashtable "valout";
404 let test_functions = [
405 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407 "internal test function - do not use",
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
413 It echos the contents of each parameter to stdout.
415 You probably don't want to call this function.");
419 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421 "internal test function - do not use",
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
427 It converts string C<val> to the return type.
429 You probably don't want to call this function.");
430 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432 "internal test function - do not use",
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
438 This function always returns an error.
440 You probably don't want to call this function.")]
444 (* non_daemon_functions are any functions which don't get processed
445 * in the daemon, eg. functions for setting and getting local
446 * configuration values.
449 let non_daemon_functions = test_functions @ [
450 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
452 "launch the qemu subprocess",
454 Internally libguestfs is implemented by running a virtual machine
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
460 ("wait_ready", (RErr, []), -1, [NotInFish],
462 "wait until the qemu subprocess launches (no op)",
464 This function is a no op.
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete. However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
475 ("kill_subprocess", (RErr, []), -1, [],
477 "kill the qemu subprocess",
479 This kills the qemu subprocess. You should never need to call this.");
481 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483 "add an image to examine or modify",
485 This function adds a virtual machine disk image C<filename> to the
486 guest. The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
490 You don't necessarily need to be root when using libguestfs. However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>. In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
507 Note that this call checks for the existence of C<filename>. This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
510 the general C<guestfs_config> call instead.");
512 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514 "add a CD-ROM disk image to examine",
516 This function adds a virtual CD-ROM disk image to the guest.
518 This is equivalent to the qemu parameter C<-cdrom filename>.
526 This call checks for the existence of C<filename>. This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
529 the general C<guestfs_config> call instead.
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
539 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541 "add a drive in snapshot mode (read-only)",
543 This adds a drive in snapshot mode, making it effectively
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed. We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>. In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
560 C<readonly=on> is only added where qemu supports this option.
562 Note that this call checks for the existence of C<filename>. This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
565 the general C<guestfs_config> call instead.");
567 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569 "add qemu parameters",
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>. Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
576 The first character of C<param> string must be a C<-> (dash).
578 C<value> can be NULL.");
580 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
582 "set the qemu binary",
584 Set the qemu binary that we will use.
586 The default is chosen when the library was compiled by the
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
594 Note that you should call this function as early as possible
595 after creating the handle. This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results. Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
602 ("get_qemu", (RConstString "qemu", []), -1, [],
603 [InitNone, Always, TestRun (
605 "get the qemu binary",
607 Return the current qemu binary.
609 This is always non-NULL. If it wasn't set already, then this will
610 return the default qemu binary name.");
612 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
614 "set the search path",
616 Set the path that libguestfs searches for kernel and initrd.img.
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
621 Setting C<path> to C<NULL> restores the default path.");
623 ("get_path", (RConstString "path", []), -1, [],
624 [InitNone, Always, TestRun (
626 "get the search path",
628 Return the current search path.
630 This is always non-NULL. If it wasn't set already, then this will
631 return the default path.");
633 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635 "add options to kernel command line",
637 This function is used to add additional options to the
638 guest kernel command line.
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
646 ("get_append", (RConstOptString "append", []), -1, [],
647 (* This cannot be tested with the current framework. The
648 * function can return NULL in normal operations, which the
649 * test framework interprets as an error.
652 "get the additional kernel options",
654 Return the additional kernel options which are added to the
655 guest kernel command line.
657 If C<NULL> then no options are added.");
659 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
663 If C<autosync> is true, this enables autosync. Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
671 ("get_autosync", (RBool "autosync", []), -1, [],
672 [InitNone, Always, TestRun (
673 [["get_autosync"]])],
676 Get the autosync flag.");
678 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687 ("get_verbose", (RBool "verbose", []), -1, [],
691 This returns the verbose messages flag.");
693 ("is_ready", (RBool "ready", []), -1, [],
694 [InitNone, Always, TestOutputTrue (
696 "is ready to accept commands",
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
701 For more information on states, see L<guestfs(3)>.");
703 ("is_config", (RBool "config", []), -1, [],
704 [InitNone, Always, TestOutputFalse (
706 "is in configuration state",
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
711 For more information on states, see L<guestfs(3)>.");
713 ("is_launching", (RBool "launching", []), -1, [],
714 [InitNone, Always, TestOutputFalse (
715 [["is_launching"]])],
716 "is launching subprocess",
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
721 For more information on states, see L<guestfs(3)>.");
723 ("is_busy", (RBool "busy", []), -1, [],
724 [InitNone, Always, TestOutputFalse (
726 "is busy processing a command",
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
731 For more information on states, see L<guestfs(3)>.");
733 ("get_state", (RInt "state", []), -1, [],
735 "get the current state",
737 This returns the current state as an opaque integer. This is
738 only useful for printing debug and internal error messages.
740 For more information on states, see L<guestfs(3)>.");
742 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743 [InitNone, Always, TestOutputInt (
744 [["set_memsize"; "500"];
745 ["get_memsize"]], 500)],
746 "set memory allocated to the qemu subprocess",
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess. This only has any effect if called before
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
759 ("get_memsize", (RInt "memsize", []), -1, [],
760 [InitNone, Always, TestOutputIntOp (
761 [["get_memsize"]], ">=", 256)],
762 "get memory allocated to the qemu subprocess",
764 This gets the memory size in megabytes allocated to the
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
774 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775 [InitNone, Always, TestOutputIntOp (
776 [["get_pid"]], ">=", 1)],
777 "get PID of qemu subprocess",
779 Return the process ID of the qemu subprocess. If there is no
780 qemu subprocess, then this will return an error.
782 This is an internal call used for debugging and testing.");
784 ("version", (RStruct ("version", "version"), []), -1, [],
785 [InitNone, Always, TestOutputStruct (
786 [["version"]], [CompareWithInt ("major", 1)])],
787 "get the library version number",
789 Return the libguestfs version number that the program is linked
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against. You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
797 This call was added in version C<1.0.58>. In previous
798 versions of libguestfs there was no way to get the version
799 number. From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
802 The call returns a structure with four elements. The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet. The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
811 I<Note:> Don't use this call to test for availability
812 of features. Distro backports makes this unreliable. Use
813 C<guestfs_available> instead.");
815 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816 [InitNone, Always, TestOutputTrue (
817 [["set_selinux"; "true"];
819 "set SELinux enabled or disabled at appliance boot",
821 This sets the selinux flag that is passed to the appliance
822 at boot time. The default is C<selinux=0> (disabled).
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
830 ("get_selinux", (RBool "selinux", []), -1, [],
832 "get SELinux enabled flag",
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
840 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841 [InitNone, Always, TestOutputFalse (
842 [["set_trace"; "false"];
844 "enable or disable command traces",
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish. In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
860 ("get_trace", (RBool "trace", []), -1, [],
862 "get command trace enabled flag",
864 Return the command trace flag.");
866 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867 [InitNone, Always, TestOutputFalse (
868 [["set_direct"; "false"];
870 "enable or disable direct appliance mode",
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
880 You probably don't want to use this unless you know what you
883 The default is disabled.");
885 ("get_direct", (RBool "direct", []), -1, [],
887 "get direct appliance mode flag",
889 Return the direct appliance mode flag.");
891 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892 [InitNone, Always, TestOutputTrue (
893 [["set_recovery_proc"; "true"];
894 ["get_recovery_proc"]])],
895 "enable or disable the recovery process",
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process. The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself). In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
911 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
913 "get recovery process enabled flag",
915 Return the recovery process enabled flag.");
917 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919 "add a drive specifying the QEMU block emulation to use",
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
924 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
926 "add a drive read-only specifying the QEMU block emulation to use",
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
933 (* daemon_functions are any functions which cause some action
934 * to take place in the daemon.
937 let daemon_functions = [
938 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939 [InitEmpty, Always, TestOutput (
940 [["part_disk"; "/dev/sda"; "mbr"];
941 ["mkfs"; "ext2"; "/dev/sda1"];
942 ["mount"; "/dev/sda1"; "/"];
943 ["write_file"; "/new"; "new file contents"; "0"];
944 ["cat"; "/new"]], "new file contents")],
945 "mount a guest disk at a position in the filesystem",
947 Mount a guest disk at a position in the filesystem. Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest. If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
953 The rules are the same as for L<mount(2)>: A filesystem must
954 first be mounted on C</> before others can be mounted. Other
955 filesystems can only be mounted on directories which already
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
964 ("sync", (RErr, []), 2, [],
965 [ InitEmpty, Always, TestRun [["sync"]]],
966 "sync disks, writes are flushed through to the disk image",
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
974 ("touch", (RErr, [Pathname "path"]), 3, [],
975 [InitBasicFS, Always, TestOutputTrue (
977 ["exists"; "/new"]])],
978 "update file timestamps or create a new file",
980 Touch acts like the L<touch(1)> command. It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
984 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985 [InitISOFS, Always, TestOutput (
986 [["cat"; "/known-2"]], "abcdef\n")],
987 "list the contents of a file",
989 Return the contents of the file named C<path>.
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string). For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
996 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997 [], (* XXX Tricky to test because it depends on the exact format
998 * of the 'ls -l' command, which changes between F10 and F11.
1000 "list the files in a directory (long format)",
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1005 This command is mostly useful for interactive sessions. It
1006 is I<not> intended that you try to parse the output string.");
1008 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009 [InitBasicFS, Always, TestOutputList (
1011 ["touch"; "/newer"];
1012 ["touch"; "/newest"];
1013 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014 "list the files in a directory",
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd). The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1020 This command is mostly useful for interactive sessions. Programs
1021 should probably use C<guestfs_readdir> instead.");
1023 ("list_devices", (RStringList "devices", []), 7, [],
1024 [InitEmpty, Always, TestOutputListOfDevices (
1025 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026 "list the block devices",
1028 List all the block devices.
1030 The full block device names are returned, eg. C</dev/sda>");
1032 ("list_partitions", (RStringList "partitions", []), 8, [],
1033 [InitBasicFS, Always, TestOutputListOfDevices (
1034 [["list_partitions"]], ["/dev/sda1"]);
1035 InitEmpty, Always, TestOutputListOfDevices (
1036 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038 "list the partitions",
1040 List all the partitions detected on all block devices.
1042 The full partition device names are returned, eg. C</dev/sda1>
1044 This does not return logical volumes. For that you will need to
1045 call C<guestfs_lvs>.");
1047 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049 [["pvs"]], ["/dev/sda1"]);
1050 InitEmpty, Always, TestOutputListOfDevices (
1051 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052 ["pvcreate"; "/dev/sda1"];
1053 ["pvcreate"; "/dev/sda2"];
1054 ["pvcreate"; "/dev/sda3"];
1055 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056 "list the LVM physical volumes (PVs)",
1058 List all the physical volumes detected. This is the equivalent
1059 of the L<pvs(8)> command.
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1064 See also C<guestfs_pvs_full>.");
1066 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067 [InitBasicFSonLVM, Always, TestOutputList (
1069 InitEmpty, Always, TestOutputList (
1070 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071 ["pvcreate"; "/dev/sda1"];
1072 ["pvcreate"; "/dev/sda2"];
1073 ["pvcreate"; "/dev/sda3"];
1074 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075 ["vgcreate"; "VG2"; "/dev/sda3"];
1076 ["vgs"]], ["VG1"; "VG2"])],
1077 "list the LVM volume groups (VGs)",
1079 List all the volumes groups detected. This is the equivalent
1080 of the L<vgs(8)> command.
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1085 See also C<guestfs_vgs_full>.");
1087 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088 [InitBasicFSonLVM, Always, TestOutputList (
1089 [["lvs"]], ["/dev/VG/LV"]);
1090 InitEmpty, Always, TestOutputList (
1091 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092 ["pvcreate"; "/dev/sda1"];
1093 ["pvcreate"; "/dev/sda2"];
1094 ["pvcreate"; "/dev/sda3"];
1095 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096 ["vgcreate"; "VG2"; "/dev/sda3"];
1097 ["lvcreate"; "LV1"; "VG1"; "50"];
1098 ["lvcreate"; "LV2"; "VG1"; "50"];
1099 ["lvcreate"; "LV3"; "VG2"; "50"];
1100 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101 "list the LVM logical volumes (LVs)",
1103 List all the logical volumes detected. This is the equivalent
1104 of the L<lvs(8)> command.
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1109 See also C<guestfs_lvs_full>.");
1111 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112 [], (* XXX how to test? *)
1113 "list the LVM physical volumes (PVs)",
1115 List all the physical volumes detected. This is the equivalent
1116 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1118 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119 [], (* XXX how to test? *)
1120 "list the LVM volume groups (VGs)",
1122 List all the volumes groups detected. This is the equivalent
1123 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1125 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM logical volumes (LVs)",
1129 List all the logical volumes detected. This is the equivalent
1130 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1132 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133 [InitISOFS, Always, TestOutputList (
1134 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135 InitISOFS, Always, TestOutputList (
1136 [["read_lines"; "/empty"]], [])],
1137 "read file as lines",
1139 Return the contents of the file named C<path>.
1141 The file contents are returned as a list of lines. Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line). For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1149 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150 [], (* XXX Augeas code needs tests. *)
1151 "create a new Augeas handle",
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1157 You must call this before using any other C<guestfs_aug_*>
1160 C<root> is the filesystem root. C<root> must not be NULL,
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1169 =item C<AUG_SAVE_BACKUP> = 1
1171 Keep the original file with a C<.augsave> extension.
1173 =item C<AUG_SAVE_NEWFILE> = 2
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1178 =item C<AUG_TYPE_CHECK> = 4
1180 Typecheck lenses (can be expensive).
1182 =item C<AUG_NO_STDINC> = 8
1184 Do not use standard load path for modules.
1186 =item C<AUG_SAVE_NOOP> = 16
1188 Make save a no-op, just record what would have been changed.
1190 =item C<AUG_NO_LOAD> = 32
1192 Do not load the tree in C<guestfs_aug_init>.
1196 To close the handle, you can call C<guestfs_aug_close>.
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1200 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201 [], (* XXX Augeas code needs tests. *)
1202 "close the current Augeas handle",
1204 Close the current Augeas handle and free up any resources
1205 used by it. After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1209 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210 [], (* XXX Augeas code needs tests. *)
1211 "define an Augeas variable",
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1220 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221 [], (* XXX Augeas code needs tests. *)
1222 "define an Augeas node",
1224 Defines a variable C<name> whose value is the result of
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1235 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236 [], (* XXX Augeas code needs tests. *)
1237 "look up the value of an Augeas path",
1239 Look up the value associated with C<path>. If C<path>
1240 matches exactly one node, the C<value> is returned.");
1242 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "set Augeas path to value",
1246 Set the value associated with C<path> to C<val>.
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL. Due to an oversight in the libguestfs API
1250 you cannot do that with this call. Instead you must use the
1251 C<guestfs_aug_clear> call.");
1253 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254 [], (* XXX Augeas code needs tests. *)
1255 "insert a sibling Augeas node",
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1265 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266 [], (* XXX Augeas code needs tests. *)
1267 "remove an Augeas path",
1269 Remove C<path> and all of its children.
1271 On success this returns the number of entries which were removed.");
1273 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274 [], (* XXX Augeas code needs tests. *)
1277 Move the node C<src> to C<dest>. C<src> must match exactly
1278 one node. C<dest> is overwritten if it exists.");
1280 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1282 "return Augeas nodes which match augpath",
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1288 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289 [], (* XXX Augeas code needs tests. *)
1290 "write all pending Augeas changes to disk",
1292 This writes all pending changes to disk.
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1297 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298 [], (* XXX Augeas code needs tests. *)
1299 "load files into the tree",
1301 Load files into the tree.
1303 See C<aug_load> in the Augeas documentation for the full gory
1306 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307 [], (* XXX Augeas code needs tests. *)
1308 "list Augeas nodes under augpath",
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1313 ("rm", (RErr, [Pathname "path"]), 29, [],
1314 [InitBasicFS, Always, TestRun
1317 InitBasicFS, Always, TestLastFail
1319 InitBasicFS, Always, TestLastFail
1324 Remove the single file C<path>.");
1326 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327 [InitBasicFS, Always, TestRun
1330 InitBasicFS, Always, TestLastFail
1331 [["rmdir"; "/new"]];
1332 InitBasicFS, Always, TestLastFail
1334 ["rmdir"; "/new"]]],
1335 "remove a directory",
1337 Remove the single directory C<path>.");
1339 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340 [InitBasicFS, Always, TestOutputFalse
1342 ["mkdir"; "/new/foo"];
1343 ["touch"; "/new/foo/bar"];
1345 ["exists"; "/new"]]],
1346 "remove a file or directory recursively",
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory. This is like the C<rm -rf> shell
1352 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353 [InitBasicFS, Always, TestOutputTrue
1355 ["is_dir"; "/new"]];
1356 InitBasicFS, Always, TestLastFail
1357 [["mkdir"; "/new/foo/bar"]]],
1358 "create a directory",
1360 Create a directory named C<path>.");
1362 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363 [InitBasicFS, Always, TestOutputTrue
1364 [["mkdir_p"; "/new/foo/bar"];
1365 ["is_dir"; "/new/foo/bar"]];
1366 InitBasicFS, Always, TestOutputTrue
1367 [["mkdir_p"; "/new/foo/bar"];
1368 ["is_dir"; "/new/foo"]];
1369 InitBasicFS, Always, TestOutputTrue
1370 [["mkdir_p"; "/new/foo/bar"];
1371 ["is_dir"; "/new"]];
1372 (* Regression tests for RHBZ#503133: *)
1373 InitBasicFS, Always, TestRun
1375 ["mkdir_p"; "/new"]];
1376 InitBasicFS, Always, TestLastFail
1378 ["mkdir_p"; "/new"]]],
1379 "create a directory and parents",
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary. This is like the C<mkdir -p> shell command.");
1384 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385 [], (* XXX Need stat command to test *)
1388 Change the mode (permissions) of C<path> to C<mode>. Only
1389 numeric modes are supported.
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1395 The mode actually set is affected by the umask.");
1397 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398 [], (* XXX Need stat command to test *)
1399 "change file owner and group",
1401 Change the file owner to C<owner> and group to C<group>.
1403 Only numeric uid and gid are supported. If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1407 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408 [InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/empty"]]);
1410 InitISOFS, Always, TestOutputTrue (
1411 [["exists"; "/directory"]])],
1412 "test if file or directory exists",
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1419 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420 [InitISOFS, Always, TestOutputTrue (
1421 [["is_file"; "/known-1"]]);
1422 InitISOFS, Always, TestOutputFalse (
1423 [["is_file"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name. Note that it returns false for
1428 other objects like directories.
1430 See also C<guestfs_stat>.");
1432 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433 [InitISOFS, Always, TestOutputFalse (
1434 [["is_dir"; "/known-3"]]);
1435 InitISOFS, Always, TestOutputTrue (
1436 [["is_dir"; "/directory"]])],
1437 "test if file exists",
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name. Note that it returns false for
1441 other objects like files.
1443 See also C<guestfs_stat>.");
1445 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputListOfDevices (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452 "create an LVM physical volume",
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1458 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459 [InitEmpty, Always, TestOutputList (
1460 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461 ["pvcreate"; "/dev/sda1"];
1462 ["pvcreate"; "/dev/sda2"];
1463 ["pvcreate"; "/dev/sda3"];
1464 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465 ["vgcreate"; "VG2"; "/dev/sda3"];
1466 ["vgs"]], ["VG1"; "VG2"])],
1467 "create an LVM volume group",
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1472 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473 [InitEmpty, Always, TestOutputList (
1474 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475 ["pvcreate"; "/dev/sda1"];
1476 ["pvcreate"; "/dev/sda2"];
1477 ["pvcreate"; "/dev/sda3"];
1478 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479 ["vgcreate"; "VG2"; "/dev/sda3"];
1480 ["lvcreate"; "LV1"; "VG1"; "50"];
1481 ["lvcreate"; "LV2"; "VG1"; "50"];
1482 ["lvcreate"; "LV3"; "VG2"; "50"];
1483 ["lvcreate"; "LV4"; "VG2"; "50"];
1484 ["lvcreate"; "LV5"; "VG2"; "50"];
1486 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488 "create an LVM logical volume",
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1493 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494 [InitEmpty, Always, TestOutput (
1495 [["part_disk"; "/dev/sda"; "mbr"];
1496 ["mkfs"; "ext2"; "/dev/sda1"];
1497 ["mount_options"; ""; "/dev/sda1"; "/"];
1498 ["write_file"; "/new"; "new file contents"; "0"];
1499 ["cat"; "/new"]], "new file contents")],
1500 "make a filesystem",
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume). The filesystem type is C<fstype>, for
1506 ("sfdisk", (RErr, [Device "device";
1507 Int "cyls"; Int "heads"; Int "sectors";
1508 StringList "lines"]), 43, [DangerWillRobinson],
1510 "create partitions on a block device",
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1515 C<device> should be a block device, for example C</dev/sda>.
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted. Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1525 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1526 information refer to the L<sfdisk(8)> manpage.
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1535 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536 [InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "new file contents"; "0"];
1538 ["cat"; "/new"]], "new file contents");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541 ["cat"; "/new"]], "\nnew file contents\n");
1542 InitBasicFS, Always, TestOutput (
1543 [["write_file"; "/new"; "\n\n"; "0"];
1544 ["cat"; "/new"]], "\n\n");
1545 InitBasicFS, Always, TestOutput (
1546 [["write_file"; "/new"; ""; "0"];
1547 ["cat"; "/new"]], "");
1548 InitBasicFS, Always, TestOutput (
1549 [["write_file"; "/new"; "\n\n\n"; "0"];
1550 ["cat"; "/new"]], "\n\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["write_file"; "/new"; "\n"; "0"];
1553 ["cat"; "/new"]], "\n")],
1556 This call creates a file called C<path>. The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version. In the meantime
1567 use C<guestfs_upload>.");
1569 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570 [InitEmpty, Always, TestOutputListOfDevices (
1571 [["part_disk"; "/dev/sda"; "mbr"];
1572 ["mkfs"; "ext2"; "/dev/sda1"];
1573 ["mount_options"; ""; "/dev/sda1"; "/"];
1574 ["mounts"]], ["/dev/sda1"]);
1575 InitEmpty, Always, TestOutputList (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 "unmount a filesystem",
1583 This unmounts the given filesystem. The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1587 ("mounts", (RStringList "devices", []), 46, [],
1588 [InitBasicFS, Always, TestOutputListOfDevices (
1589 [["mounts"]], ["/dev/sda1"])],
1590 "show mounted filesystems",
1592 This returns the list of currently mounted filesystems. It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1595 Some internal mounts are not shown.
1597 See also: C<guestfs_mountpoints>");
1599 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600 [InitBasicFS, Always, TestOutputList (
1603 (* check that umount_all can unmount nested mounts correctly: *)
1604 InitEmpty, Always, TestOutputList (
1605 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606 ["mkfs"; "ext2"; "/dev/sda1"];
1607 ["mkfs"; "ext2"; "/dev/sda2"];
1608 ["mkfs"; "ext2"; "/dev/sda3"];
1609 ["mount_options"; ""; "/dev/sda1"; "/"];
1611 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612 ["mkdir"; "/mp1/mp2"];
1613 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614 ["mkdir"; "/mp1/mp2/mp3"];
1617 "unmount all filesystems",
1619 This unmounts all mounted filesystems.
1621 Some internal mounts are not unmounted by this call.");
1623 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1625 "remove all LVM LVs, VGs and PVs",
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1630 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631 [InitISOFS, Always, TestOutput (
1632 [["file"; "/empty"]], "empty");
1633 InitISOFS, Always, TestOutput (
1634 [["file"; "/known-1"]], "ASCII text");
1635 InitISOFS, Always, TestLastFail (
1636 [["file"; "/notexists"]])],
1637 "determine file type",
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file. This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zbsL path>. Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1650 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651 [InitBasicFS, Always, TestOutput (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command"; "/test-command 1"]], "Result1");
1655 InitBasicFS, Always, TestOutput (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command"; "/test-command 2"]], "Result2\n");
1659 InitBasicFS, Always, TestOutput (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command"; "/test-command 3"]], "\nResult3");
1663 InitBasicFS, Always, TestOutput (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command"; "/test-command 4"]], "\nResult4\n");
1667 InitBasicFS, Always, TestOutput (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command"; "/test-command 5"]], "\nResult5\n\n");
1671 InitBasicFS, Always, TestOutput (
1672 [["upload"; "test-command"; "/test-command"];
1673 ["chmod"; "0o755"; "/test-command"];
1674 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675 InitBasicFS, Always, TestOutput (
1676 [["upload"; "test-command"; "/test-command"];
1677 ["chmod"; "0o755"; "/test-command"];
1678 ["command"; "/test-command 7"]], "");
1679 InitBasicFS, Always, TestOutput (
1680 [["upload"; "test-command"; "/test-command"];
1681 ["chmod"; "0o755"; "/test-command"];
1682 ["command"; "/test-command 8"]], "\n");
1683 InitBasicFS, Always, TestOutput (
1684 [["upload"; "test-command"; "/test-command"];
1685 ["chmod"; "0o755"; "/test-command"];
1686 ["command"; "/test-command 9"]], "\n\n");
1687 InitBasicFS, Always, TestOutput (
1688 [["upload"; "test-command"; "/test-command"];
1689 ["chmod"; "0o755"; "/test-command"];
1690 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691 InitBasicFS, Always, TestOutput (
1692 [["upload"; "test-command"; "/test-command"];
1693 ["chmod"; "0o755"; "/test-command"];
1694 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695 InitBasicFS, Always, TestLastFail (
1696 [["upload"; "test-command"; "/test-command"];
1697 ["chmod"; "0o755"; "/test-command"];
1698 ["command"; "/test-command"]])],
1699 "run a command from the guest filesystem",
1701 This call runs a command from the guest filesystem. The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters. The list must be
1709 non-empty (ie. must contain a program name). Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1713 The return value is anything printed to I<stdout> by
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message. The error message
1718 string is the content of I<stderr> from the command.
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>. If you require a program from
1722 another location, you should provide the full path in the
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places. It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1731 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732 [InitBasicFS, Always, TestOutputList (
1733 [["upload"; "test-command"; "/test-command"];
1734 ["chmod"; "0o755"; "/test-command"];
1735 ["command_lines"; "/test-command 1"]], ["Result1"]);
1736 InitBasicFS, Always, TestOutputList (
1737 [["upload"; "test-command"; "/test-command"];
1738 ["chmod"; "0o755"; "/test-command"];
1739 ["command_lines"; "/test-command 2"]], ["Result2"]);
1740 InitBasicFS, Always, TestOutputList (
1741 [["upload"; "test-command"; "/test-command"];
1742 ["chmod"; "0o755"; "/test-command"];
1743 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744 InitBasicFS, Always, TestOutputList (
1745 [["upload"; "test-command"; "/test-command"];
1746 ["chmod"; "0o755"; "/test-command"];
1747 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748 InitBasicFS, Always, TestOutputList (
1749 [["upload"; "test-command"; "/test-command"];
1750 ["chmod"; "0o755"; "/test-command"];
1751 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752 InitBasicFS, Always, TestOutputList (
1753 [["upload"; "test-command"; "/test-command"];
1754 ["chmod"; "0o755"; "/test-command"];
1755 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756 InitBasicFS, Always, TestOutputList (
1757 [["upload"; "test-command"; "/test-command"];
1758 ["chmod"; "0o755"; "/test-command"];
1759 ["command_lines"; "/test-command 7"]], []);
1760 InitBasicFS, Always, TestOutputList (
1761 [["upload"; "test-command"; "/test-command"];
1762 ["chmod"; "0o755"; "/test-command"];
1763 ["command_lines"; "/test-command 8"]], [""]);
1764 InitBasicFS, Always, TestOutputList (
1765 [["upload"; "test-command"; "/test-command"];
1766 ["chmod"; "0o755"; "/test-command"];
1767 ["command_lines"; "/test-command 9"]], ["";""]);
1768 InitBasicFS, Always, TestOutputList (
1769 [["upload"; "test-command"; "/test-command"];
1770 ["chmod"; "0o755"; "/test-command"];
1771 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772 InitBasicFS, Always, TestOutputList (
1773 [["upload"; "test-command"; "/test-command"];
1774 ["chmod"; "0o755"; "/test-command"];
1775 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776 "run a command, returning lines",
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1781 See also: C<guestfs_sh_lines>");
1783 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784 [InitISOFS, Always, TestOutputStruct (
1785 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786 "get file information",
1788 Returns file information for the given C<path>.
1790 This is the same as the C<stat(2)> system call.");
1792 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795 "get file information for a symbolic link",
1797 Returns file information for the given C<path>.
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1803 This is the same as the C<lstat(2)> system call.");
1805 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806 [InitISOFS, Always, TestOutputStruct (
1807 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808 "get file system statistics",
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1814 This is the same as the C<statvfs(2)> system call.");
1816 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1818 "get ext2/ext3/ext4 superblock details",
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1823 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1824 manpage for more details. The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1828 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829 [InitEmpty, Always, TestOutputTrue (
1830 [["blockdev_setro"; "/dev/sda"];
1831 ["blockdev_getro"; "/dev/sda"]])],
1832 "set block device to read-only",
1834 Sets the block device named C<device> to read-only.
1836 This uses the L<blockdev(8)> command.");
1838 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839 [InitEmpty, Always, TestOutputFalse (
1840 [["blockdev_setrw"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-write",
1844 Sets the block device named C<device> to read-write.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849 [InitEmpty, Always, TestOutputTrue (
1850 [["blockdev_setro"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "is block device set to read-only",
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getss"; "/dev/sda"]], 512)],
1862 "get sectorsize of block device",
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 This uses the L<blockdev(8)> command.");
1872 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873 [InitEmpty, Always, TestOutputInt (
1874 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875 "get blocksize of block device",
1877 This returns the block size of a device.
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1882 This uses the L<blockdev(8)> command.");
1884 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1886 "set blocksize of block device",
1888 This sets the block size of a device.
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1893 This uses the L<blockdev(8)> command.");
1895 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896 [InitEmpty, Always, TestOutputInt (
1897 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898 "get total size of device in 512-byte sectors",
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1907 This uses the L<blockdev(8)> command.");
1909 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910 [InitEmpty, Always, TestOutputInt (
1911 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912 "get total size of device in bytes",
1914 This returns the size of the device in bytes.
1916 See also C<guestfs_blockdev_getsz>.
1918 This uses the L<blockdev(8)> command.");
1920 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921 [InitEmpty, Always, TestRun
1922 [["blockdev_flushbufs"; "/dev/sda"]]],
1923 "flush device buffers",
1925 This tells the kernel to flush internal buffers associated
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_rereadpt"; "/dev/sda"]]],
1933 "reread partition table",
1935 Reread the partition table on C<device>.
1937 This uses the L<blockdev(8)> command.");
1939 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940 [InitBasicFS, Always, TestOutput (
1941 (* Pick a file from cwd which isn't likely to change. *)
1942 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943 ["checksum"; "md5"; "/COPYING.LIB"]],
1944 Digest.to_hex (Digest.file "COPYING.LIB"))],
1945 "upload a file from the local machine",
1947 Upload local file C<filename> to C<remotefilename> on the
1950 C<filename> can also be a named pipe.
1952 See also C<guestfs_download>.");
1954 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955 [InitBasicFS, Always, TestOutput (
1956 (* Pick a file from cwd which isn't likely to change. *)
1957 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959 ["upload"; "testdownload.tmp"; "/upload"];
1960 ["checksum"; "md5"; "/upload"]],
1961 Digest.to_hex (Digest.file "COPYING.LIB"))],
1962 "download a file to the local machine",
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1967 C<filename> can also be a named pipe.
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1971 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972 [InitISOFS, Always, TestOutput (
1973 [["checksum"; "crc"; "/known-3"]], "2891671662");
1974 InitISOFS, Always, TestLastFail (
1975 [["checksum"; "crc"; "/notexists"]]);
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988 "compute MD5, SHAx or CRC checksum of file",
1990 This call computes the MD5, SHAx or CRC checksum of the
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2005 Compute the MD5 hash (using the C<md5sum> program).
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2029 The checksum is returned as a printable string.
2031 To get the checksum for a device, use C<guestfs_checksum_device>.");
2033 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2034 [InitBasicFS, Always, TestOutput (
2035 [["tar_in"; "../images/helloworld.tar"; "/"];
2036 ["cat"; "/hello"]], "hello\n")],
2037 "unpack tarfile to directory",
2039 This command uploads and unpacks local file C<tarfile> (an
2040 I<uncompressed> tar file) into C<directory>.
2042 To upload a compressed tarball, use C<guestfs_tgz_in>
2043 or C<guestfs_txz_in>.");
2045 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2047 "pack directory into tarfile",
2049 This command packs the contents of C<directory> and downloads
2050 it to local file C<tarfile>.
2052 To download a compressed tarball, use C<guestfs_tgz_out>
2053 or C<guestfs_txz_out>.");
2055 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2056 [InitBasicFS, Always, TestOutput (
2057 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2058 ["cat"; "/hello"]], "hello\n")],
2059 "unpack compressed tarball to directory",
2061 This command uploads and unpacks local file C<tarball> (a
2062 I<gzip compressed> tar file) into C<directory>.
2064 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2066 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2068 "pack directory into compressed tarball",
2070 This command packs the contents of C<directory> and downloads
2071 it to local file C<tarball>.
2073 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2075 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2076 [InitBasicFS, Always, TestLastFail (
2078 ["mount_ro"; "/dev/sda1"; "/"];
2079 ["touch"; "/new"]]);
2080 InitBasicFS, Always, TestOutput (
2081 [["write_file"; "/new"; "data"; "0"];
2083 ["mount_ro"; "/dev/sda1"; "/"];
2084 ["cat"; "/new"]], "data")],
2085 "mount a guest disk, read-only",
2087 This is the same as the C<guestfs_mount> command, but it
2088 mounts the filesystem with the read-only (I<-o ro>) flag.");
2090 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2092 "mount a guest disk with mount options",
2094 This is the same as the C<guestfs_mount> command, but it
2095 allows you to set the mount options as for the
2096 L<mount(8)> I<-o> flag.");
2098 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2100 "mount a guest disk with mount options and vfstype",
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2106 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2108 "debugging and internals",
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2114 There is no comprehensive help for this command. You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2118 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119 [InitEmpty, Always, TestOutputList (
2120 [["part_disk"; "/dev/sda"; "mbr"];
2121 ["pvcreate"; "/dev/sda1"];
2122 ["vgcreate"; "VG"; "/dev/sda1"];
2123 ["lvcreate"; "LV1"; "VG"; "50"];
2124 ["lvcreate"; "LV2"; "VG"; "50"];
2125 ["lvremove"; "/dev/VG/LV1"];
2126 ["lvs"]], ["/dev/VG/LV2"]);
2127 InitEmpty, Always, TestOutputList (
2128 [["part_disk"; "/dev/sda"; "mbr"];
2129 ["pvcreate"; "/dev/sda1"];
2130 ["vgcreate"; "VG"; "/dev/sda1"];
2131 ["lvcreate"; "LV1"; "VG"; "50"];
2132 ["lvcreate"; "LV2"; "VG"; "50"];
2133 ["lvremove"; "/dev/VG"];
2135 InitEmpty, Always, TestOutputList (
2136 [["part_disk"; "/dev/sda"; "mbr"];
2137 ["pvcreate"; "/dev/sda1"];
2138 ["vgcreate"; "VG"; "/dev/sda1"];
2139 ["lvcreate"; "LV1"; "VG"; "50"];
2140 ["lvcreate"; "LV2"; "VG"; "50"];
2141 ["lvremove"; "/dev/VG"];
2143 "remove an LVM logical volume",
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2151 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152 [InitEmpty, Always, TestOutputList (
2153 [["part_disk"; "/dev/sda"; "mbr"];
2154 ["pvcreate"; "/dev/sda1"];
2155 ["vgcreate"; "VG"; "/dev/sda1"];
2156 ["lvcreate"; "LV1"; "VG"; "50"];
2157 ["lvcreate"; "LV2"; "VG"; "50"];
2160 InitEmpty, Always, TestOutputList (
2161 [["part_disk"; "/dev/sda"; "mbr"];
2162 ["pvcreate"; "/dev/sda1"];
2163 ["vgcreate"; "VG"; "/dev/sda1"];
2164 ["lvcreate"; "LV1"; "VG"; "50"];
2165 ["lvcreate"; "LV2"; "VG"; "50"];
2168 "remove an LVM volume group",
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2172 This also forcibly removes all logical volumes in the volume
2175 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
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 InitEmpty, Always, TestOutputListOfDevices (
2195 [["part_disk"; "/dev/sda"; "mbr"];
2196 ["pvcreate"; "/dev/sda1"];
2197 ["vgcreate"; "VG"; "/dev/sda1"];
2198 ["lvcreate"; "LV1"; "VG"; "50"];
2199 ["lvcreate"; "LV2"; "VG"; "50"];
2201 ["pvremove"; "/dev/sda1"];
2203 "remove an LVM physical volume",
2205 This wipes a physical volume C<device> so that LVM will no longer
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2212 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213 [InitBasicFS, Always, TestOutput (
2214 [["set_e2label"; "/dev/sda1"; "testlabel"];
2215 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216 "set the ext2/3/4 filesystem label",
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>. Filesystem labels are limited to
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2225 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2227 "get the ext2/3/4 filesystem label",
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2232 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233 (let uuid = uuidgen () in
2234 [InitBasicFS, Always, TestOutput (
2235 [["set_e2uuid"; "/dev/sda1"; uuid];
2236 ["get_e2uuid"; "/dev/sda1"]], uuid);
2237 InitBasicFS, Always, TestOutput (
2238 [["set_e2uuid"; "/dev/sda1"; "clear"];
2239 ["get_e2uuid"; "/dev/sda1"]], "");
2240 (* We can't predict what UUIDs will be, so just check the commands run. *)
2241 InitBasicFS, Always, TestRun (
2242 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243 InitBasicFS, Always, TestRun (
2244 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245 "set the ext2/3/4 filesystem UUID",
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>. The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2255 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2257 "get the ext2/3/4 filesystem UUID",
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2262 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2263 [InitBasicFS, Always, TestOutputInt (
2264 [["umount"; "/dev/sda1"];
2265 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266 InitBasicFS, Always, TestOutputInt (
2267 [["umount"; "/dev/sda1"];
2268 ["zero"; "/dev/sda1"];
2269 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270 "run the filesystem checker",
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2275 The returned integer is the status. See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2284 Multiple status codes can be summed together.
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2293 Checking or repairing NTFS volumes is not supported
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2300 ("zero", (RErr, [Device "device"]), 85, [],
2301 [InitBasicFS, Always, TestOutput (
2302 [["umount"; "/dev/sda1"];
2303 ["zero"; "/dev/sda1"];
2304 ["file"; "/dev/sda1"]], "data")],
2305 "write zeroes to the device",
2307 This command writes zeroes over the first few blocks of C<device>.
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device). It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2313 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2315 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316 (* Test disabled because grub-install incompatible with virtio-blk driver.
2317 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2319 [InitBasicFS, Disabled, TestOutputTrue (
2320 [["grub_install"; "/"; "/dev/sda1"];
2321 ["is_dir"; "/boot"]])],
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2327 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328 [InitBasicFS, Always, TestOutput (
2329 [["write_file"; "/old"; "file content"; "0"];
2330 ["cp"; "/old"; "/new"];
2331 ["cat"; "/new"]], "file content");
2332 InitBasicFS, Always, TestOutputTrue (
2333 [["write_file"; "/old"; "file content"; "0"];
2334 ["cp"; "/old"; "/new"];
2335 ["is_file"; "/old"]]);
2336 InitBasicFS, Always, TestOutput (
2337 [["write_file"; "/old"; "file content"; "0"];
2339 ["cp"; "/old"; "/dir/new"];
2340 ["cat"; "/dir/new"]], "file content")],
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2346 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347 [InitBasicFS, Always, TestOutput (
2348 [["mkdir"; "/olddir"];
2349 ["mkdir"; "/newdir"];
2350 ["write_file"; "/olddir/file"; "file content"; "0"];
2351 ["cp_a"; "/olddir"; "/newdir"];
2352 ["cat"; "/newdir/olddir/file"]], "file content")],
2353 "copy a file or directory recursively",
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2358 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359 [InitBasicFS, Always, TestOutput (
2360 [["write_file"; "/old"; "file content"; "0"];
2361 ["mv"; "/old"; "/new"];
2362 ["cat"; "/new"]], "file content");
2363 InitBasicFS, Always, TestOutputFalse (
2364 [["write_file"; "/old"; "file content"; "0"];
2365 ["mv"; "/old"; "/new"];
2366 ["is_file"; "/old"]])],
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2372 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373 [InitEmpty, Always, TestRun (
2374 [["drop_caches"; "3"]])],
2375 "drop kernel page cache, dentries and inodes",
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches. The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2382 Setting C<whattodrop> to 3 should drop everything.
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2387 ("dmesg", (RString "kmsgs", []), 91, [],
2388 [InitEmpty, Always, TestRun (
2390 "return kernel messages",
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel. This is sometimes useful for extended
2394 debugging of problems.
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2401 ("ping_daemon", (RErr, []), 92, [],
2402 [InitEmpty, Always, TestRun (
2403 [["ping_daemon"]])],
2404 "ping the guest daemon",
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess. Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2411 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412 [InitBasicFS, Always, TestOutputTrue (
2413 [["write_file"; "/file1"; "contents of a file"; "0"];
2414 ["cp"; "/file1"; "/file2"];
2415 ["equal"; "/file1"; "/file2"]]);
2416 InitBasicFS, Always, TestOutputFalse (
2417 [["write_file"; "/file1"; "contents of a file"; "0"];
2418 ["write_file"; "/file2"; "contents of another file"; "0"];
2419 ["equal"; "/file1"; "/file2"]]);
2420 InitBasicFS, Always, TestLastFail (
2421 [["equal"; "/file1"; "/file2"]])],
2422 "test if two files have equal contents",
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2427 The external L<cmp(1)> program is used for the comparison.");
2429 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430 [InitISOFS, Always, TestOutputList (
2431 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432 InitISOFS, Always, TestOutputList (
2433 [["strings"; "/empty"]], [])],
2434 "print the printable strings in a file",
2436 This runs the L<strings(1)> command on a file and returns
2437 the list of printable strings found.");
2439 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2440 [InitISOFS, Always, TestOutputList (
2441 [["strings_e"; "b"; "/known-5"]], []);
2442 InitBasicFS, Disabled, TestOutputList (
2443 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2444 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2445 "print the printable strings in a file",
2447 This is like the C<guestfs_strings> command, but allows you to
2448 specify the encoding.
2450 See the L<strings(1)> manpage for the full list of encodings.
2452 Commonly useful encodings are C<l> (lower case L) which will
2453 show strings inside Windows/x86 files.
2455 The returned strings are transcoded to UTF-8.");
2457 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2458 [InitISOFS, Always, TestOutput (
2459 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2460 (* Test for RHBZ#501888c2 regression which caused large hexdump
2461 * commands to segfault.
2463 InitISOFS, Always, TestRun (
2464 [["hexdump"; "/100krandom"]])],
2465 "dump a file in hexadecimal",
2467 This runs C<hexdump -C> on the given C<path>. The result is
2468 the human-readable, canonical hex dump of the file.");
2470 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2471 [InitNone, Always, TestOutput (
2472 [["part_disk"; "/dev/sda"; "mbr"];
2473 ["mkfs"; "ext3"; "/dev/sda1"];
2474 ["mount_options"; ""; "/dev/sda1"; "/"];
2475 ["write_file"; "/new"; "test file"; "0"];
2476 ["umount"; "/dev/sda1"];
2477 ["zerofree"; "/dev/sda1"];
2478 ["mount_options"; ""; "/dev/sda1"; "/"];
2479 ["cat"; "/new"]], "test file")],
2480 "zero unused inodes and disk blocks on ext2/3 filesystem",
2482 This runs the I<zerofree> program on C<device>. This program
2483 claims to zero unused inodes and disk blocks on an ext2/3
2484 filesystem, thus making it possible to compress the filesystem
2487 You should B<not> run this program if the filesystem is
2490 It is possible that using this program can damage the filesystem
2491 or data on the filesystem.");
2493 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2495 "resize an LVM physical volume",
2497 This resizes (expands or shrinks) an existing LVM physical
2498 volume to match the new size of the underlying device.");
2500 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2501 Int "cyls"; Int "heads"; Int "sectors";
2502 String "line"]), 99, [DangerWillRobinson],
2504 "modify a single partition on a block device",
2506 This runs L<sfdisk(8)> option to modify just the single
2507 partition C<n> (note: C<n> counts from 1).
2509 For other parameters, see C<guestfs_sfdisk>. You should usually
2510 pass C<0> for the cyls/heads/sectors parameters.
2512 See also: C<guestfs_part_add>");
2514 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2516 "display the partition table",
2518 This displays the partition table on C<device>, in the
2519 human-readable output of the L<sfdisk(8)> command. It is
2520 not intended to be parsed.
2522 See also: C<guestfs_part_list>");
2524 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2526 "display the kernel geometry",
2528 This displays the kernel's idea of the geometry of C<device>.
2530 The result is in human-readable format, and not designed to
2533 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2535 "display the disk geometry from the partition table",
2537 This displays the disk geometry of C<device> read from the
2538 partition table. Especially in the case where the underlying
2539 block device has been resized, this can be different from the
2540 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2542 The result is in human-readable format, and not designed to
2545 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2547 "activate or deactivate all volume groups",
2549 This command activates or (if C<activate> is false) deactivates
2550 all logical volumes in all volume groups.
2551 If activated, then they are made known to the
2552 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2553 then those devices disappear.
2555 This command is the same as running C<vgchange -a y|n>");
2557 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2559 "activate or deactivate some volume groups",
2561 This command activates or (if C<activate> is false) deactivates
2562 all logical volumes in the listed volume groups C<volgroups>.
2563 If activated, then they are made known to the
2564 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2565 then those devices disappear.
2567 This command is the same as running C<vgchange -a y|n volgroups...>
2569 Note that if C<volgroups> is an empty list then B<all> volume groups
2570 are activated or deactivated.");
2572 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2573 [InitNone, Always, TestOutput (
2574 [["part_disk"; "/dev/sda"; "mbr"];
2575 ["pvcreate"; "/dev/sda1"];
2576 ["vgcreate"; "VG"; "/dev/sda1"];
2577 ["lvcreate"; "LV"; "VG"; "10"];
2578 ["mkfs"; "ext2"; "/dev/VG/LV"];
2579 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2580 ["write_file"; "/new"; "test content"; "0"];
2582 ["lvresize"; "/dev/VG/LV"; "20"];
2583 ["e2fsck_f"; "/dev/VG/LV"];
2584 ["resize2fs"; "/dev/VG/LV"];
2585 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2586 ["cat"; "/new"]], "test content")],
2587 "resize an LVM logical volume",
2589 This resizes (expands or shrinks) an existing LVM logical
2590 volume to C<mbytes>. When reducing, data in the reduced part
2593 ("resize2fs", (RErr, [Device "device"]), 106, [],
2594 [], (* lvresize tests this *)
2595 "resize an ext2/ext3 filesystem",
2597 This resizes an ext2 or ext3 filesystem to match the size of
2598 the underlying device.
2600 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2601 on the C<device> before calling this command. For unknown reasons
2602 C<resize2fs> sometimes gives an error about this and sometimes not.
2603 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2604 calling this function.");
2606 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2607 [InitBasicFS, Always, TestOutputList (
2608 [["find"; "/"]], ["lost+found"]);
2609 InitBasicFS, Always, TestOutputList (
2613 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2614 InitBasicFS, Always, TestOutputList (
2615 [["mkdir_p"; "/a/b/c"];
2616 ["touch"; "/a/b/c/d"];
2617 ["find"; "/a/b/"]], ["c"; "c/d"])],
2618 "find all files and directories",
2620 This command lists out all files and directories, recursively,
2621 starting at C<directory>. It is essentially equivalent to
2622 running the shell command C<find directory -print> but some
2623 post-processing happens on the output, described below.
2625 This returns a list of strings I<without any prefix>. Thus
2626 if the directory structure was:
2632 then the returned list from C<guestfs_find> C</tmp> would be
2640 If C<directory> is not a directory, then this command returns
2643 The returned list is sorted.
2645 See also C<guestfs_find0>.");
2647 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2648 [], (* lvresize tests this *)
2649 "check an ext2/ext3 filesystem",
2651 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2652 filesystem checker on C<device>, noninteractively (C<-p>),
2653 even if the filesystem appears to be clean (C<-f>).
2655 This command is only needed because of C<guestfs_resize2fs>
2656 (q.v.). Normally you should use C<guestfs_fsck>.");
2658 ("sleep", (RErr, [Int "secs"]), 109, [],
2659 [InitNone, Always, TestRun (
2661 "sleep for some seconds",
2663 Sleep for C<secs> seconds.");
2665 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2666 [InitNone, Always, TestOutputInt (
2667 [["part_disk"; "/dev/sda"; "mbr"];
2668 ["mkfs"; "ntfs"; "/dev/sda1"];
2669 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2670 InitNone, Always, TestOutputInt (
2671 [["part_disk"; "/dev/sda"; "mbr"];
2672 ["mkfs"; "ext2"; "/dev/sda1"];
2673 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2674 "probe NTFS volume",
2676 This command runs the L<ntfs-3g.probe(8)> command which probes
2677 an NTFS C<device> for mountability. (Not all NTFS volumes can
2678 be mounted read-write, and some cannot be mounted at all).
2680 C<rw> is a boolean flag. Set it to true if you want to test
2681 if the volume can be mounted read-write. Set it to false if
2682 you want to test if the volume can be mounted read-only.
2684 The return value is an integer which C<0> if the operation
2685 would succeed, or some non-zero value documented in the
2686 L<ntfs-3g.probe(8)> manual page.");
2688 ("sh", (RString "output", [String "command"]), 111, [],
2689 [], (* XXX needs tests *)
2690 "run a command via the shell",
2692 This call runs a command from the guest filesystem via the
2695 This is like C<guestfs_command>, but passes the command to:
2697 /bin/sh -c \"command\"
2699 Depending on the guest's shell, this usually results in
2700 wildcards being expanded, shell expressions being interpolated
2703 All the provisos about C<guestfs_command> apply to this call.");
2705 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2706 [], (* XXX needs tests *)
2707 "run a command via the shell returning lines",
2709 This is the same as C<guestfs_sh>, but splits the result
2710 into a list of lines.
2712 See also: C<guestfs_command_lines>");
2714 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2715 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2716 * code in stubs.c, since all valid glob patterns must start with "/".
2717 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2719 [InitBasicFS, Always, TestOutputList (
2720 [["mkdir_p"; "/a/b/c"];
2721 ["touch"; "/a/b/c/d"];
2722 ["touch"; "/a/b/c/e"];
2723 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2724 InitBasicFS, Always, TestOutputList (
2725 [["mkdir_p"; "/a/b/c"];
2726 ["touch"; "/a/b/c/d"];
2727 ["touch"; "/a/b/c/e"];
2728 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2729 InitBasicFS, Always, TestOutputList (
2730 [["mkdir_p"; "/a/b/c"];
2731 ["touch"; "/a/b/c/d"];
2732 ["touch"; "/a/b/c/e"];
2733 ["glob_expand"; "/a/*/x/*"]], [])],
2734 "expand a wildcard path",
2736 This command searches for all the pathnames matching
2737 C<pattern> according to the wildcard expansion rules
2740 If no paths match, then this returns an empty list
2741 (note: not an error).
2743 It is just a wrapper around the C L<glob(3)> function
2744 with flags C<GLOB_MARK|GLOB_BRACE>.
2745 See that manual page for more details.");
2747 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2748 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2749 [["scrub_device"; "/dev/sdc"]])],
2750 "scrub (securely wipe) a device",
2752 This command writes patterns over C<device> to make data retrieval
2755 It is an interface to the L<scrub(1)> program. See that
2756 manual page for more details.");
2758 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2759 [InitBasicFS, Always, TestRun (
2760 [["write_file"; "/file"; "content"; "0"];
2761 ["scrub_file"; "/file"]])],
2762 "scrub (securely wipe) a file",
2764 This command writes patterns over a file to make data retrieval
2767 The file is I<removed> after scrubbing.
2769 It is an interface to the L<scrub(1)> program. See that
2770 manual page for more details.");
2772 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2773 [], (* XXX needs testing *)
2774 "scrub (securely wipe) free space",
2776 This command creates the directory C<dir> and then fills it
2777 with files until the filesystem is full, and scrubs the files
2778 as for C<guestfs_scrub_file>, and deletes them.
2779 The intention is to scrub any free space on the partition
2782 It is an interface to the L<scrub(1)> program. See that
2783 manual page for more details.");
2785 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2786 [InitBasicFS, Always, TestRun (
2788 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2789 "create a temporary directory",
2791 This command creates a temporary directory. The
2792 C<template> parameter should be a full pathname for the
2793 temporary directory name with the final six characters being
2796 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2797 the second one being suitable for Windows filesystems.
2799 The name of the temporary directory that was created
2802 The temporary directory is created with mode 0700
2803 and is owned by root.
2805 The caller is responsible for deleting the temporary
2806 directory and its contents after use.
2808 See also: L<mkdtemp(3)>");
2810 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2811 [InitISOFS, Always, TestOutputInt (
2812 [["wc_l"; "/10klines"]], 10000)],
2813 "count lines in a file",
2815 This command counts the lines in a file, using the
2816 C<wc -l> external command.");
2818 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2819 [InitISOFS, Always, TestOutputInt (
2820 [["wc_w"; "/10klines"]], 10000)],
2821 "count words in a file",
2823 This command counts the words in a file, using the
2824 C<wc -w> external command.");
2826 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2827 [InitISOFS, Always, TestOutputInt (
2828 [["wc_c"; "/100kallspaces"]], 102400)],
2829 "count characters in a file",
2831 This command counts the characters in a file, using the
2832 C<wc -c> external command.");
2834 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2835 [InitISOFS, Always, TestOutputList (
2836 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2837 "return first 10 lines of a file",
2839 This command returns up to the first 10 lines of a file as
2840 a list of strings.");
2842 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2843 [InitISOFS, Always, TestOutputList (
2844 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2845 InitISOFS, Always, TestOutputList (
2846 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2847 InitISOFS, Always, TestOutputList (
2848 [["head_n"; "0"; "/10klines"]], [])],
2849 "return first N lines of a file",
2851 If the parameter C<nrlines> is a positive number, this returns the first
2852 C<nrlines> lines of the file C<path>.
2854 If the parameter C<nrlines> is a negative number, this returns lines
2855 from the file C<path>, excluding the last C<nrlines> lines.
2857 If the parameter C<nrlines> is zero, this returns an empty list.");
2859 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2860 [InitISOFS, Always, TestOutputList (
2861 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2862 "return last 10 lines of a file",
2864 This command returns up to the last 10 lines of a file as
2865 a list of strings.");
2867 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2868 [InitISOFS, Always, TestOutputList (
2869 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2870 InitISOFS, Always, TestOutputList (
2871 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2872 InitISOFS, Always, TestOutputList (
2873 [["tail_n"; "0"; "/10klines"]], [])],
2874 "return last N lines of a file",
2876 If the parameter C<nrlines> is a positive number, this returns the last
2877 C<nrlines> lines of the file C<path>.
2879 If the parameter C<nrlines> is a negative number, this returns lines
2880 from the file C<path>, starting with the C<-nrlines>th line.
2882 If the parameter C<nrlines> is zero, this returns an empty list.");
2884 ("df", (RString "output", []), 125, [],
2885 [], (* XXX Tricky to test because it depends on the exact format
2886 * of the 'df' command and other imponderables.
2888 "report file system disk space usage",
2890 This command runs the C<df> command to report disk space used.
2892 This command is mostly useful for interactive sessions. It
2893 is I<not> intended that you try to parse the output string.
2894 Use C<statvfs> from programs.");
2896 ("df_h", (RString "output", []), 126, [],
2897 [], (* XXX Tricky to test because it depends on the exact format
2898 * of the 'df' command and other imponderables.
2900 "report file system disk space usage (human readable)",
2902 This command runs the C<df -h> command to report disk space used
2903 in human-readable format.
2905 This command is mostly useful for interactive sessions. It
2906 is I<not> intended that you try to parse the output string.
2907 Use C<statvfs> from programs.");
2909 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2910 [InitISOFS, Always, TestOutputInt (
2911 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2912 "estimate file space usage",
2914 This command runs the C<du -s> command to estimate file space
2917 C<path> can be a file or a directory. If C<path> is a directory
2918 then the estimate includes the contents of the directory and all
2919 subdirectories (recursively).
2921 The result is the estimated size in I<kilobytes>
2922 (ie. units of 1024 bytes).");
2924 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2925 [InitISOFS, Always, TestOutputList (
2926 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2927 "list files in an initrd",
2929 This command lists out files contained in an initrd.
2931 The files are listed without any initial C</> character. The
2932 files are listed in the order they appear (not necessarily
2933 alphabetical). Directory names are listed as separate items.
2935 Old Linux kernels (2.4 and earlier) used a compressed ext2
2936 filesystem as initrd. We I<only> support the newer initramfs
2937 format (compressed cpio files).");
2939 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2941 "mount a file using the loop device",
2943 This command lets you mount C<file> (a filesystem image
2944 in a file) on a mount point. It is entirely equivalent to
2945 the command C<mount -o loop file mountpoint>.");
2947 ("mkswap", (RErr, [Device "device"]), 130, [],
2948 [InitEmpty, Always, TestRun (
2949 [["part_disk"; "/dev/sda"; "mbr"];
2950 ["mkswap"; "/dev/sda1"]])],
2951 "create a swap partition",
2953 Create a swap partition on C<device>.");
2955 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2956 [InitEmpty, Always, TestRun (
2957 [["part_disk"; "/dev/sda"; "mbr"];
2958 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2959 "create a swap partition with a label",
2961 Create a swap partition on C<device> with label C<label>.
2963 Note that you cannot attach a swap label to a block device
2964 (eg. C</dev/sda>), just to a partition. This appears to be
2965 a limitation of the kernel or swap tools.");
2967 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2968 (let uuid = uuidgen () in
2969 [InitEmpty, Always, TestRun (
2970 [["part_disk"; "/dev/sda"; "mbr"];
2971 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2972 "create a swap partition with an explicit UUID",
2974 Create a swap partition on C<device> with UUID C<uuid>.");
2976 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2977 [InitBasicFS, Always, TestOutputStruct (
2978 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2979 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2980 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2981 InitBasicFS, Always, TestOutputStruct (
2982 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2983 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2984 "make block, character or FIFO devices",
2986 This call creates block or character special devices, or
2987 named pipes (FIFOs).
2989 The C<mode> parameter should be the mode, using the standard
2990 constants. C<devmajor> and C<devminor> are the
2991 device major and minor numbers, only used when creating block
2992 and character special devices.
2994 Note that, just like L<mknod(2)>, the mode must be bitwise
2995 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2996 just creates a regular file). These constants are
2997 available in the standard Linux header files, or you can use
2998 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
2999 which are wrappers around this command which bitwise OR
3000 in the appropriate constant for you.
3002 The mode actually set is affected by the umask.");
3004 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3005 [InitBasicFS, Always, TestOutputStruct (
3006 [["mkfifo"; "0o777"; "/node"];
3007 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3008 "make FIFO (named pipe)",
3010 This call creates a FIFO (named pipe) called C<path> with
3011 mode C<mode>. It is just a convenient wrapper around
3014 The mode actually set is affected by the umask.");
3016 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3017 [InitBasicFS, Always, TestOutputStruct (
3018 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3019 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3020 "make block device node",
3022 This call creates a block device node called C<path> with
3023 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3024 It is just a convenient wrapper around C<guestfs_mknod>.
3026 The mode actually set is affected by the umask.");
3028 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3029 [InitBasicFS, Always, TestOutputStruct (
3030 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3031 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3032 "make char device node",
3034 This call creates a char device node called C<path> with
3035 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3036 It is just a convenient wrapper around C<guestfs_mknod>.
3038 The mode actually set is affected by the umask.");
3040 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3041 [InitEmpty, Always, TestOutputInt (
3042 [["umask"; "0o22"]], 0o22)],
3043 "set file mode creation mask (umask)",
3045 This function sets the mask used for creating new files and
3046 device nodes to C<mask & 0777>.
3048 Typical umask values would be C<022> which creates new files
3049 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3050 C<002> which creates new files with permissions like
3051 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3053 The default umask is C<022>. This is important because it
3054 means that directories and device nodes will be created with
3055 C<0644> or C<0755> mode even if you specify C<0777>.
3057 See also C<guestfs_get_umask>,
3058 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3060 This call returns the previous umask.");
3062 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3064 "read directories entries",
3066 This returns the list of directory entries in directory C<dir>.
3068 All entries in the directory are returned, including C<.> and
3069 C<..>. The entries are I<not> sorted, but returned in the same
3070 order as the underlying filesystem.
3072 Also this call returns basic file type information about each
3073 file. The C<ftyp> field will contain one of the following characters:
3111 The L<readdir(3)> returned a C<d_type> field with an
3116 This function is primarily intended for use by programs. To
3117 get a simple list of names, use C<guestfs_ls>. To get a printable
3118 directory for human consumption, use C<guestfs_ll>.");
3120 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3122 "create partitions on a block device",
3124 This is a simplified interface to the C<guestfs_sfdisk>
3125 command, where partition sizes are specified in megabytes
3126 only (rounded to the nearest cylinder) and you don't need
3127 to specify the cyls, heads and sectors parameters which
3128 were rarely if ever used anyway.
3130 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3131 and C<guestfs_part_disk>");
3133 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3135 "determine file type inside a compressed file",
3137 This command runs C<file> after first decompressing C<path>
3140 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3142 Since 1.0.63, use C<guestfs_file> instead which can now
3143 process compressed files.");
3145 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3147 "list extended attributes of a file or directory",
3149 This call lists the extended attributes of the file or directory
3152 At the system call level, this is a combination of the
3153 L<listxattr(2)> and L<getxattr(2)> calls.
3155 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3157 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3159 "list extended attributes of a file or directory",
3161 This is the same as C<guestfs_getxattrs>, but if C<path>
3162 is a symbolic link, then it returns the extended attributes
3163 of the link itself.");
3165 ("setxattr", (RErr, [String "xattr";
3166 String "val"; Int "vallen"; (* will be BufferIn *)
3167 Pathname "path"]), 143, [Optional "linuxxattrs"],
3169 "set extended attribute of a file or directory",
3171 This call sets the extended attribute named C<xattr>
3172 of the file C<path> to the value C<val> (of length C<vallen>).
3173 The value is arbitrary 8 bit data.
3175 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3177 ("lsetxattr", (RErr, [String "xattr";
3178 String "val"; Int "vallen"; (* will be BufferIn *)
3179 Pathname "path"]), 144, [Optional "linuxxattrs"],
3181 "set extended attribute of a file or directory",
3183 This is the same as C<guestfs_setxattr>, but if C<path>
3184 is a symbolic link, then it sets an extended attribute
3185 of the link itself.");
3187 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3189 "remove extended attribute of a file or directory",
3191 This call removes the extended attribute named C<xattr>
3192 of the file C<path>.
3194 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3196 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3198 "remove extended attribute of a file or directory",
3200 This is the same as C<guestfs_removexattr>, but if C<path>
3201 is a symbolic link, then it removes an extended attribute
3202 of the link itself.");
3204 ("mountpoints", (RHashtable "mps", []), 147, [],
3208 This call is similar to C<guestfs_mounts>. That call returns
3209 a list of devices. This one returns a hash table (map) of
3210 device name to directory where the device is mounted.");
3212 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3213 (* This is a special case: while you would expect a parameter
3214 * of type "Pathname", that doesn't work, because it implies
3215 * NEED_ROOT in the generated calling code in stubs.c, and
3216 * this function cannot use NEED_ROOT.
3219 "create a mountpoint",
3221 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3222 specialized calls that can be used to create extra mountpoints
3223 before mounting the first filesystem.
3225 These calls are I<only> necessary in some very limited circumstances,
3226 mainly the case where you want to mount a mix of unrelated and/or
3227 read-only filesystems together.
3229 For example, live CDs often contain a \"Russian doll\" nest of
3230 filesystems, an ISO outer layer, with a squashfs image inside, with
3231 an ext2/3 image inside that. You can unpack this as follows
3234 add-ro Fedora-11-i686-Live.iso
3237 mkmountpoint /squash
3240 mount-loop /cd/LiveOS/squashfs.img /squash
3241 mount-loop /squash/LiveOS/ext3fs.img /ext3
3243 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3245 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3247 "remove a mountpoint",
3249 This calls removes a mountpoint that was previously created
3250 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3251 for full details.");
3253 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3254 [InitISOFS, Always, TestOutputBuffer (
3255 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3258 This calls returns the contents of the file C<path> as a
3261 Unlike C<guestfs_cat>, this function can correctly
3262 handle files that contain embedded ASCII NUL characters.
3263 However unlike C<guestfs_download>, this function is limited
3264 in the total size of file that can be handled.");
3266 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3267 [InitISOFS, Always, TestOutputList (
3268 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3269 InitISOFS, Always, TestOutputList (
3270 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3271 "return lines matching a pattern",
3273 This calls the external C<grep> program and returns the
3276 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3277 [InitISOFS, Always, TestOutputList (
3278 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3279 "return lines matching a pattern",
3281 This calls the external C<egrep> program and returns the
3284 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3285 [InitISOFS, Always, TestOutputList (
3286 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3287 "return lines matching a pattern",
3289 This calls the external C<fgrep> program and returns the
3292 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3293 [InitISOFS, Always, TestOutputList (
3294 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3295 "return lines matching a pattern",
3297 This calls the external C<grep -i> program and returns the
3300 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3301 [InitISOFS, Always, TestOutputList (
3302 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3303 "return lines matching a pattern",
3305 This calls the external C<egrep -i> program and returns the
3308 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3309 [InitISOFS, Always, TestOutputList (
3310 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3311 "return lines matching a pattern",
3313 This calls the external C<fgrep -i> program and returns the
3316 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3317 [InitISOFS, Always, TestOutputList (
3318 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3319 "return lines matching a pattern",
3321 This calls the external C<zgrep> program and returns the
3324 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3325 [InitISOFS, Always, TestOutputList (
3326 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3327 "return lines matching a pattern",
3329 This calls the external C<zegrep> program and returns the
3332 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3333 [InitISOFS, Always, TestOutputList (
3334 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3335 "return lines matching a pattern",
3337 This calls the external C<zfgrep> program and returns the
3340 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3341 [InitISOFS, Always, TestOutputList (
3342 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3343 "return lines matching a pattern",
3345 This calls the external C<zgrep -i> program and returns the
3348 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3349 [InitISOFS, Always, TestOutputList (
3350 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3351 "return lines matching a pattern",
3353 This calls the external C<zegrep -i> program and returns the
3356 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3357 [InitISOFS, Always, TestOutputList (
3358 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3359 "return lines matching a pattern",
3361 This calls the external C<zfgrep -i> program and returns the
3364 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3365 [InitISOFS, Always, TestOutput (
3366 [["realpath"; "/../directory"]], "/directory")],
3367 "canonicalized absolute pathname",
3369 Return the canonicalized absolute pathname of C<path>. The
3370 returned path has no C<.>, C<..> or symbolic link path elements.");
3372 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3373 [InitBasicFS, Always, TestOutputStruct (
3376 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3377 "create a hard link",
3379 This command creates a hard link using the C<ln> command.");
3381 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3382 [InitBasicFS, Always, TestOutputStruct (
3385 ["ln_f"; "/a"; "/b"];
3386 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3387 "create a hard link",
3389 This command creates a hard link using the C<ln -f> command.
3390 The C<-f> option removes the link (C<linkname>) if it exists already.");
3392 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3393 [InitBasicFS, Always, TestOutputStruct (
3395 ["ln_s"; "a"; "/b"];
3396 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3397 "create a symbolic link",
3399 This command creates a symbolic link using the C<ln -s> command.");
3401 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3402 [InitBasicFS, Always, TestOutput (
3403 [["mkdir_p"; "/a/b"];
3404 ["touch"; "/a/b/c"];
3405 ["ln_sf"; "../d"; "/a/b/c"];
3406 ["readlink"; "/a/b/c"]], "../d")],
3407 "create a symbolic link",
3409 This command creates a symbolic link using the C<ln -sf> command,
3410 The C<-f> option removes the link (C<linkname>) if it exists already.");
3412 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3413 [] (* XXX tested above *),
3414 "read the target of a symbolic link",
3416 This command reads the target of a symbolic link.");
3418 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3419 [InitBasicFS, Always, TestOutputStruct (
3420 [["fallocate"; "/a"; "1000000"];
3421 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3422 "preallocate a file in the guest filesystem",
3424 This command preallocates a file (containing zero bytes) named
3425 C<path> of size C<len> bytes. If the file exists already, it
3428 Do not confuse this with the guestfish-specific
3429 C<alloc> command which allocates a file in the host and
3430 attaches it as a device.");
3432 ("swapon_device", (RErr, [Device "device"]), 170, [],
3433 [InitPartition, Always, TestRun (
3434 [["mkswap"; "/dev/sda1"];
3435 ["swapon_device"; "/dev/sda1"];
3436 ["swapoff_device"; "/dev/sda1"]])],
3437 "enable swap on device",
3439 This command enables the libguestfs appliance to use the
3440 swap device or partition named C<device>. The increased
3441 memory is made available for all commands, for example
3442 those run using C<guestfs_command> or C<guestfs_sh>.
3444 Note that you should not swap to existing guest swap
3445 partitions unless you know what you are doing. They may
3446 contain hibernation information, or other information that
3447 the guest doesn't want you to trash. You also risk leaking
3448 information about the host to the guest this way. Instead,
3449 attach a new host device to the guest and swap on that.");
3451 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3452 [], (* XXX tested by swapon_device *)
3453 "disable swap on device",
3455 This command disables the libguestfs appliance swap
3456 device or partition named C<device>.
3457 See C<guestfs_swapon_device>.");
3459 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3460 [InitBasicFS, Always, TestRun (
3461 [["fallocate"; "/swap"; "8388608"];
3462 ["mkswap_file"; "/swap"];
3463 ["swapon_file"; "/swap"];
3464 ["swapoff_file"; "/swap"]])],
3465 "enable swap on file",
3467 This command enables swap to a file.
3468 See C<guestfs_swapon_device> for other notes.");
3470 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3471 [], (* XXX tested by swapon_file *)
3472 "disable swap on file",
3474 This command disables the libguestfs appliance swap on file.");
3476 ("swapon_label", (RErr, [String "label"]), 174, [],
3477 [InitEmpty, Always, TestRun (
3478 [["part_disk"; "/dev/sdb"; "mbr"];
3479 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3480 ["swapon_label"; "swapit"];
3481 ["swapoff_label"; "swapit"];
3482 ["zero"; "/dev/sdb"];
3483 ["blockdev_rereadpt"; "/dev/sdb"]])],
3484 "enable swap on labeled swap partition",
3486 This command enables swap to a labeled swap partition.
3487 See C<guestfs_swapon_device> for other notes.");
3489 ("swapoff_label", (RErr, [String "label"]), 175, [],
3490 [], (* XXX tested by swapon_label *)
3491 "disable swap on labeled swap partition",
3493 This command disables the libguestfs appliance swap on
3494 labeled swap partition.");
3496 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3497 (let uuid = uuidgen () in
3498 [InitEmpty, Always, TestRun (
3499 [["mkswap_U"; uuid; "/dev/sdb"];
3500 ["swapon_uuid"; uuid];
3501 ["swapoff_uuid"; uuid]])]),
3502 "enable swap on swap partition by UUID",
3504 This command enables swap to a swap partition with the given UUID.
3505 See C<guestfs_swapon_device> for other notes.");
3507 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3508 [], (* XXX tested by swapon_uuid *)
3509 "disable swap on swap partition by UUID",
3511 This command disables the libguestfs appliance swap partition
3512 with the given UUID.");
3514 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3515 [InitBasicFS, Always, TestRun (
3516 [["fallocate"; "/swap"; "8388608"];
3517 ["mkswap_file"; "/swap"]])],
3518 "create a swap file",
3522 This command just writes a swap file signature to an existing
3523 file. To create the file itself, use something like C<guestfs_fallocate>.");
3525 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3526 [InitISOFS, Always, TestRun (
3527 [["inotify_init"; "0"]])],
3528 "create an inotify handle",
3530 This command creates a new inotify handle.
3531 The inotify subsystem can be used to notify events which happen to
3532 objects in the guest filesystem.
3534 C<maxevents> is the maximum number of events which will be
3535 queued up between calls to C<guestfs_inotify_read> or
3536 C<guestfs_inotify_files>.
3537 If this is passed as C<0>, then the kernel (or previously set)
3538 default is used. For Linux 2.6.29 the default was 16384 events.
3539 Beyond this limit, the kernel throws away events, but records
3540 the fact that it threw them away by setting a flag
3541 C<IN_Q_OVERFLOW> in the returned structure list (see
3542 C<guestfs_inotify_read>).
3544 Before any events are generated, you have to add some
3545 watches to the internal watch list. See:
3546 C<guestfs_inotify_add_watch>,
3547 C<guestfs_inotify_rm_watch> and
3548 C<guestfs_inotify_watch_all>.
3550 Queued up events should be read periodically by calling
3551 C<guestfs_inotify_read>
3552 (or C<guestfs_inotify_files> which is just a helpful
3553 wrapper around C<guestfs_inotify_read>). If you don't
3554 read the events out often enough then you risk the internal
3557 The handle should be closed after use by calling
3558 C<guestfs_inotify_close>. This also removes any
3559 watches automatically.
3561 See also L<inotify(7)> for an overview of the inotify interface
3562 as exposed by the Linux kernel, which is roughly what we expose
3563 via libguestfs. Note that there is one global inotify handle
3564 per libguestfs instance.");
3566 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3567 [InitBasicFS, Always, TestOutputList (
3568 [["inotify_init"; "0"];
3569 ["inotify_add_watch"; "/"; "1073741823"];
3572 ["inotify_files"]], ["a"; "b"])],
3573 "add an inotify watch",
3575 Watch C<path> for the events listed in C<mask>.
3577 Note that if C<path> is a directory then events within that
3578 directory are watched, but this does I<not> happen recursively
3579 (in subdirectories).
3581 Note for non-C or non-Linux callers: the inotify events are
3582 defined by the Linux kernel ABI and are listed in
3583 C</usr/include/sys/inotify.h>.");
3585 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3587 "remove an inotify watch",
3589 Remove a previously defined inotify watch.
3590 See C<guestfs_inotify_add_watch>.");
3592 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3594 "return list of inotify events",
3596 Return the complete queue of events that have happened
3597 since the previous read call.
3599 If no events have happened, this returns an empty list.
3601 I<Note>: In order to make sure that all events have been
3602 read, you must call this function repeatedly until it
3603 returns an empty list. The reason is that the call will
3604 read events up to the maximum appliance-to-host message
3605 size and leave remaining events in the queue.");
3607 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3609 "return list of watched files that had events",
3611 This function is a helpful wrapper around C<guestfs_inotify_read>
3612 which just returns a list of pathnames of objects that were
3613 touched. The returned pathnames are sorted and deduplicated.");
3615 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3617 "close the inotify handle",
3619 This closes the inotify handle which was previously
3620 opened by inotify_init. It removes all watches, throws
3621 away any pending events, and deallocates all resources.");
3623 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3625 "set SELinux security context",
3627 This sets the SELinux security context of the daemon
3628 to the string C<context>.
3630 See the documentation about SELINUX in L<guestfs(3)>.");
3632 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3634 "get SELinux security context",
3636 This gets the SELinux security context of the daemon.
3638 See the documentation about SELINUX in L<guestfs(3)>,
3639 and C<guestfs_setcon>");
3641 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3642 [InitEmpty, Always, TestOutput (
3643 [["part_disk"; "/dev/sda"; "mbr"];
3644 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3645 ["mount_options"; ""; "/dev/sda1"; "/"];
3646 ["write_file"; "/new"; "new file contents"; "0"];
3647 ["cat"; "/new"]], "new file contents")],
3648 "make a filesystem with block size",
3650 This call is similar to C<guestfs_mkfs>, but it allows you to
3651 control the block size of the resulting filesystem. Supported
3652 block sizes depend on the filesystem type, but typically they
3653 are C<1024>, C<2048> or C<4096> only.");
3655 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3656 [InitEmpty, Always, TestOutput (
3657 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3658 ["mke2journal"; "4096"; "/dev/sda1"];
3659 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3660 ["mount_options"; ""; "/dev/sda2"; "/"];
3661 ["write_file"; "/new"; "new file contents"; "0"];
3662 ["cat"; "/new"]], "new file contents")],
3663 "make ext2/3/4 external journal",
3665 This creates an ext2 external journal on C<device>. It is equivalent
3668 mke2fs -O journal_dev -b blocksize device");
3670 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3671 [InitEmpty, Always, TestOutput (
3672 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3673 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3674 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3675 ["mount_options"; ""; "/dev/sda2"; "/"];
3676 ["write_file"; "/new"; "new file contents"; "0"];
3677 ["cat"; "/new"]], "new file contents")],
3678 "make ext2/3/4 external journal with label",
3680 This creates an ext2 external journal on C<device> with label C<label>.");
3682 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3683 (let uuid = uuidgen () in
3684 [InitEmpty, Always, TestOutput (
3685 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3686 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3687 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3688 ["mount_options"; ""; "/dev/sda2"; "/"];
3689 ["write_file"; "/new"; "new file contents"; "0"];
3690 ["cat"; "/new"]], "new file contents")]),
3691 "make ext2/3/4 external journal with UUID",
3693 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3695 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3697 "make ext2/3/4 filesystem with external journal",
3699 This creates an ext2/3/4 filesystem on C<device> with
3700 an external journal on C<journal>. It is equivalent
3703 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3705 See also C<guestfs_mke2journal>.");
3707 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3709 "make ext2/3/4 filesystem with external journal",
3711 This creates an ext2/3/4 filesystem on C<device> with
3712 an external journal on the journal labeled C<label>.
3714 See also C<guestfs_mke2journal_L>.");
3716 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3718 "make ext2/3/4 filesystem with external journal",
3720 This creates an ext2/3/4 filesystem on C<device> with
3721 an external journal on the journal with UUID C<uuid>.
3723 See also C<guestfs_mke2journal_U>.");
3725 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3726 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3727 "load a kernel module",
3729 This loads a kernel module in the appliance.
3731 The kernel module must have been whitelisted when libguestfs
3732 was built (see C<appliance/kmod.whitelist.in> in the source).");
3734 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3735 [InitNone, Always, TestOutput (
3736 [["echo_daemon"; "This is a test"]], "This is a test"
3738 "echo arguments back to the client",
3740 This command concatenate the list of C<words> passed with single spaces between
3741 them and returns the resulting string.
3743 You can use this command to test the connection through to the daemon.
3745 See also C<guestfs_ping_daemon>.");
3747 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3748 [], (* There is a regression test for this. *)
3749 "find all files and directories, returning NUL-separated list",
3751 This command lists out all files and directories, recursively,
3752 starting at C<directory>, placing the resulting list in the
3753 external file called C<files>.
3755 This command works the same way as C<guestfs_find> with the
3756 following exceptions:
3762 The resulting list is written to an external file.
3766 Items (filenames) in the result are separated
3767 by C<\\0> characters. See L<find(1)> option I<-print0>.
3771 This command is not limited in the number of names that it
3776 The result list is not sorted.
3780 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3781 [InitISOFS, Always, TestOutput (
3782 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3783 InitISOFS, Always, TestOutput (
3784 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3785 InitISOFS, Always, TestOutput (
3786 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3787 InitISOFS, Always, TestLastFail (
3788 [["case_sensitive_path"; "/Known-1/"]]);
3789 InitBasicFS, Always, TestOutput (
3791 ["mkdir"; "/a/bbb"];
3792 ["touch"; "/a/bbb/c"];
3793 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3794 InitBasicFS, Always, TestOutput (
3796 ["mkdir"; "/a/bbb"];
3797 ["touch"; "/a/bbb/c"];
3798 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3799 InitBasicFS, Always, TestLastFail (
3801 ["mkdir"; "/a/bbb"];
3802 ["touch"; "/a/bbb/c"];
3803 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3804 "return true path on case-insensitive filesystem",
3806 This can be used to resolve case insensitive paths on
3807 a filesystem which is case sensitive. The use case is
3808 to resolve paths which you have read from Windows configuration
3809 files or the Windows Registry, to the true path.
3811 The command handles a peculiarity of the Linux ntfs-3g
3812 filesystem driver (and probably others), which is that although
3813 the underlying filesystem is case-insensitive, the driver
3814 exports the filesystem to Linux as case-sensitive.
3816 One consequence of this is that special directories such
3817 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3818 (or other things) depending on the precise details of how
3819 they were created. In Windows itself this would not be
3822 Bug or feature? You decide:
3823 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3825 This function resolves the true case of each element in the
3826 path and returns the case-sensitive path.
3828 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3829 might return C<\"/WINDOWS/system32\"> (the exact return value
3830 would depend on details of how the directories were originally
3831 created under Windows).
3834 This function does not handle drive names, backslashes etc.
3836 See also C<guestfs_realpath>.");
3838 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3839 [InitBasicFS, Always, TestOutput (
3840 [["vfs_type"; "/dev/sda1"]], "ext2")],
3841 "get the Linux VFS type corresponding to a mounted device",
3843 This command gets the block device type corresponding to
3844 a mounted device called C<device>.
3846 Usually the result is the name of the Linux VFS module that
3847 is used to mount this device (probably determined automatically
3848 if you used the C<guestfs_mount> call).");
3850 ("truncate", (RErr, [Pathname "path"]), 199, [],
3851 [InitBasicFS, Always, TestOutputStruct (
3852 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3853 ["truncate"; "/test"];
3854 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3855 "truncate a file to zero size",
3857 This command truncates C<path> to a zero-length file. The
3858 file must exist already.");
3860 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3861 [InitBasicFS, Always, TestOutputStruct (
3862 [["touch"; "/test"];
3863 ["truncate_size"; "/test"; "1000"];
3864 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3865 "truncate a file to a particular size",
3867 This command truncates C<path> to size C<size> bytes. The file
3868 must exist already. If the file is smaller than C<size> then
3869 the file is extended to the required size with null bytes.");
3871 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3872 [InitBasicFS, Always, TestOutputStruct (
3873 [["touch"; "/test"];
3874 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3875 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3876 "set timestamp of a file with nanosecond precision",
3878 This command sets the timestamps of a file with nanosecond
3881 C<atsecs, atnsecs> are the last access time (atime) in secs and
3882 nanoseconds from the epoch.
3884 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3885 secs and nanoseconds from the epoch.
3887 If the C<*nsecs> field contains the special value C<-1> then
3888 the corresponding timestamp is set to the current time. (The
3889 C<*secs> field is ignored in this case).
3891 If the C<*nsecs> field contains the special value C<-2> then
3892 the corresponding timestamp is left unchanged. (The
3893 C<*secs> field is ignored in this case).");
3895 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3896 [InitBasicFS, Always, TestOutputStruct (
3897 [["mkdir_mode"; "/test"; "0o111"];
3898 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3899 "create a directory with a particular mode",
3901 This command creates a directory, setting the initial permissions
3902 of the directory to C<mode>.
3904 For common Linux filesystems, the actual mode which is set will
3905 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3906 interpret the mode in other ways.
3908 See also C<guestfs_mkdir>, C<guestfs_umask>");
3910 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3912 "change file owner and group",
3914 Change the file owner to C<owner> and group to C<group>.
3915 This is like C<guestfs_chown> but if C<path> is a symlink then
3916 the link itself is changed, not the target.
3918 Only numeric uid and gid are supported. If you want to use
3919 names, you will need to locate and parse the password file
3920 yourself (Augeas support makes this relatively easy).");
3922 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3924 "lstat on multiple files",
3926 This call allows you to perform the C<guestfs_lstat> operation
3927 on multiple files, where all files are in the directory C<path>.
3928 C<names> is the list of files from this directory.
3930 On return you get a list of stat structs, with a one-to-one
3931 correspondence to the C<names> list. If any name did not exist
3932 or could not be lstat'd, then the C<ino> field of that structure
3935 This call is intended for programs that want to efficiently
3936 list a directory contents without making many round-trips.
3937 See also C<guestfs_lxattrlist> for a similarly efficient call
3938 for getting extended attributes. Very long directory listings
3939 might cause the protocol message size to be exceeded, causing
3940 this call to fail. The caller must split up such requests
3941 into smaller groups of names.");
3943 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3945 "lgetxattr on multiple files",
3947 This call allows you to get the extended attributes
3948 of multiple files, where all files are in the directory C<path>.
3949 C<names> is the list of files from this directory.
3951 On return you get a flat list of xattr structs which must be
3952 interpreted sequentially. The first xattr struct always has a zero-length
3953 C<attrname>. C<attrval> in this struct is zero-length
3954 to indicate there was an error doing C<lgetxattr> for this
3955 file, I<or> is a C string which is a decimal number
3956 (the number of following attributes for this file, which could
3957 be C<\"0\">). Then after the first xattr struct are the
3958 zero or more attributes for the first named file.
3959 This repeats for the second and subsequent files.
3961 This call is intended for programs that want to efficiently
3962 list a directory contents without making many round-trips.
3963 See also C<guestfs_lstatlist> for a similarly efficient call
3964 for getting standard stats. Very long directory listings
3965 might cause the protocol message size to be exceeded, causing
3966 this call to fail. The caller must split up such requests
3967 into smaller groups of names.");
3969 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3971 "readlink on multiple files",
3973 This call allows you to do a C<readlink> operation
3974 on multiple files, where all files are in the directory C<path>.
3975 C<names> is the list of files from this directory.
3977 On return you get a list of strings, with a one-to-one
3978 correspondence to the C<names> list. Each string is the
3979 value of the symbol link.
3981 If the C<readlink(2)> operation fails on any name, then
3982 the corresponding result string is the empty string C<\"\">.
3983 However the whole operation is completed even if there
3984 were C<readlink(2)> errors, and so you can call this
3985 function with names where you don't know if they are
3986 symbolic links already (albeit slightly less efficient).
3988 This call is intended for programs that want to efficiently
3989 list a directory contents without making many round-trips.
3990 Very long directory listings might cause the protocol
3991 message size to be exceeded, causing
3992 this call to fail. The caller must split up such requests
3993 into smaller groups of names.");
3995 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3996 [InitISOFS, Always, TestOutputBuffer (
3997 [["pread"; "/known-4"; "1"; "3"]], "\n");
3998 InitISOFS, Always, TestOutputBuffer (
3999 [["pread"; "/empty"; "0"; "100"]], "")],
4000 "read part of a file",
4002 This command lets you read part of a file. It reads C<count>
4003 bytes of the file, starting at C<offset>, from file C<path>.
4005 This may read fewer bytes than requested. For further details
4006 see the L<pread(2)> system call.");
4008 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4009 [InitEmpty, Always, TestRun (
4010 [["part_init"; "/dev/sda"; "gpt"]])],
4011 "create an empty partition table",
4013 This creates an empty partition table on C<device> of one of the
4014 partition types listed below. Usually C<parttype> should be
4015 either C<msdos> or C<gpt> (for large disks).
4017 Initially there are no partitions. Following this, you should
4018 call C<guestfs_part_add> for each partition required.
4020 Possible values for C<parttype> are:
4024 =item B<efi> | B<gpt>
4026 Intel EFI / GPT partition table.
4028 This is recommended for >= 2 TB partitions that will be accessed
4029 from Linux and Intel-based Mac OS X. It also has limited backwards
4030 compatibility with the C<mbr> format.
4032 =item B<mbr> | B<msdos>
4034 The standard PC \"Master Boot Record\" (MBR) format used
4035 by MS-DOS and Windows. This partition type will B<only> work
4036 for device sizes up to 2 TB. For large disks we recommend
4041 Other partition table types that may work but are not
4050 =item B<amiga> | B<rdb>
4052 Amiga \"Rigid Disk Block\" format.
4060 DASD, used on IBM mainframes.
4068 Old Mac partition format. Modern Macs use C<gpt>.
4072 NEC PC-98 format, common in Japan apparently.
4080 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4081 [InitEmpty, Always, TestRun (
4082 [["part_init"; "/dev/sda"; "mbr"];
4083 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4084 InitEmpty, Always, TestRun (
4085 [["part_init"; "/dev/sda"; "gpt"];
4086 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4087 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4088 InitEmpty, Always, TestRun (
4089 [["part_init"; "/dev/sda"; "mbr"];
4090 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4091 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4092 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4093 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4094 "add a partition to the device",
4096 This command adds a partition to C<device>. If there is no partition
4097 table on the device, call C<guestfs_part_init> first.
4099 The C<prlogex> parameter is the type of partition. Normally you
4100 should pass C<p> or C<primary> here, but MBR partition tables also
4101 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4104 C<startsect> and C<endsect> are the start and end of the partition
4105 in I<sectors>. C<endsect> may be negative, which means it counts
4106 backwards from the end of the disk (C<-1> is the last sector).
4108 Creating a partition which covers the whole disk is not so easy.
4109 Use C<guestfs_part_disk> to do that.");
4111 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4112 [InitEmpty, Always, TestRun (
4113 [["part_disk"; "/dev/sda"; "mbr"]]);
4114 InitEmpty, Always, TestRun (
4115 [["part_disk"; "/dev/sda"; "gpt"]])],
4116 "partition whole disk with a single primary partition",
4118 This command is simply a combination of C<guestfs_part_init>
4119 followed by C<guestfs_part_add> to create a single primary partition
4120 covering the whole disk.
4122 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4123 but other possible values are described in C<guestfs_part_init>.");
4125 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4126 [InitEmpty, Always, TestRun (
4127 [["part_disk"; "/dev/sda"; "mbr"];
4128 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4129 "make a partition bootable",
4131 This sets the bootable flag on partition numbered C<partnum> on
4132 device C<device>. Note that partitions are numbered from 1.
4134 The bootable flag is used by some operating systems (notably
4135 Windows) to determine which partition to boot from. It is by
4136 no means universally recognized.");
4138 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4139 [InitEmpty, Always, TestRun (
4140 [["part_disk"; "/dev/sda"; "gpt"];
4141 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4142 "set partition name",
4144 This sets the partition name on partition numbered C<partnum> on
4145 device C<device>. Note that partitions are numbered from 1.
4147 The partition name can only be set on certain types of partition
4148 table. This works on C<gpt> but not on C<mbr> partitions.");
4150 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4151 [], (* XXX Add a regression test for this. *)
4152 "list partitions on a device",
4154 This command parses the partition table on C<device> and
4155 returns the list of partitions found.
4157 The fields in the returned structure are:
4163 Partition number, counting from 1.
4167 Start of the partition I<in bytes>. To get sectors you have to
4168 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4172 End of the partition in bytes.
4176 Size of the partition in bytes.
4180 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4181 [InitEmpty, Always, TestOutput (
4182 [["part_disk"; "/dev/sda"; "gpt"];
4183 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4184 "get the partition table type",
4186 This command examines the partition table on C<device> and
4187 returns the partition table type (format) being used.
4189 Common return values include: C<msdos> (a DOS/Windows style MBR
4190 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4191 values are possible, although unusual. See C<guestfs_part_init>
4194 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4195 [InitBasicFS, Always, TestOutputBuffer (
4196 [["fill"; "0x63"; "10"; "/test"];
4197 ["read_file"; "/test"]], "cccccccccc")],
4198 "fill a file with octets",
4200 This command creates a new file called C<path>. The initial
4201 content of the file is C<len> octets of C<c>, where C<c>
4202 must be a number in the range C<[0..255]>.
4204 To fill a file with zero bytes (sparsely), it is
4205 much more efficient to use C<guestfs_truncate_size>.");
4207 ("available", (RErr, [StringList "groups"]), 216, [],
4208 [InitNone, Always, TestRun [["available"; ""]]],
4209 "test availability of some parts of the API",
4211 This command is used to check the availability of some
4212 groups of functionality in the appliance, which not all builds of
4213 the libguestfs appliance will be able to provide.
4215 The libguestfs groups, and the functions that those
4216 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4218 The argument C<groups> is a list of group names, eg:
4219 C<[\"inotify\", \"augeas\"]> would check for the availability of
4220 the Linux inotify functions and Augeas (configuration file
4223 The command returns no error if I<all> requested groups are available.
4225 It fails with an error if one or more of the requested
4226 groups is unavailable in the appliance.
4228 If an unknown group name is included in the
4229 list of groups then an error is always returned.
4237 You must call C<guestfs_launch> before calling this function.
4239 The reason is because we don't know what groups are
4240 supported by the appliance/daemon until it is running and can
4245 If a group of functions is available, this does not necessarily
4246 mean that they will work. You still have to check for errors
4247 when calling individual API functions even if they are
4252 It is usually the job of distro packagers to build
4253 complete functionality into the libguestfs appliance.
4254 Upstream libguestfs, if built from source with all
4255 requirements satisfied, will support everything.
4259 This call was added in version C<1.0.80>. In previous
4260 versions of libguestfs all you could do would be to speculatively
4261 execute a command to find out if the daemon implemented it.
4262 See also C<guestfs_version>.
4266 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4267 [InitBasicFS, Always, TestOutputBuffer (
4268 [["write_file"; "/src"; "hello, world"; "0"];
4269 ["dd"; "/src"; "/dest"];
4270 ["read_file"; "/dest"]], "hello, world")],
4271 "copy from source to destination using dd",
4273 This command copies from one source device or file C<src>
4274 to another destination device or file C<dest>. Normally you
4275 would use this to copy to or from a device or partition, for
4276 example to duplicate a filesystem.
4278 If the destination is a device, it must be as large or larger
4279 than the source file or device, otherwise the copy will fail.
4280 This command cannot do partial copies (see C<guestfs_copy_size>).");
4282 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4283 [InitBasicFS, Always, TestOutputInt (
4284 [["write_file"; "/file"; "hello, world"; "0"];
4285 ["filesize"; "/file"]], 12)],
4286 "return the size of the file in bytes",
4288 This command returns the size of C<file> in bytes.
4290 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4291 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4292 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4294 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4295 [InitBasicFSonLVM, Always, TestOutputList (
4296 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4297 ["lvs"]], ["/dev/VG/LV2"])],
4298 "rename an LVM logical volume",
4300 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4302 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4303 [InitBasicFSonLVM, Always, TestOutputList (
4305 ["vg_activate"; "false"; "VG"];
4306 ["vgrename"; "VG"; "VG2"];
4307 ["vg_activate"; "true"; "VG2"];
4308 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4309 ["vgs"]], ["VG2"])],
4310 "rename an LVM volume group",
4312 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4314 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4315 [InitISOFS, Always, TestOutputBuffer (
4316 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4317 "list the contents of a single file in an initrd",
4319 This command unpacks the file C<filename> from the initrd file
4320 called C<initrdpath>. The filename must be given I<without> the
4321 initial C</> character.
4323 For example, in guestfish you could use the following command
4324 to examine the boot script (usually called C</init>)
4325 contained in a Linux initrd or initramfs image:
4327 initrd-cat /boot/initrd-<version>.img init
4329 See also C<guestfs_initrd_list>.");
4331 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4333 "get the UUID of a physical volume",
4335 This command returns the UUID of the LVM PV C<device>.");
4337 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4339 "get the UUID of a volume group",
4341 This command returns the UUID of the LVM VG named C<vgname>.");
4343 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4345 "get the UUID of a logical volume",
4347 This command returns the UUID of the LVM LV C<device>.");
4349 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4351 "get the PV UUIDs containing the volume group",
4353 Given a VG called C<vgname>, this returns the UUIDs of all
4354 the physical volumes that this volume group resides on.
4356 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4357 calls to associate physical volumes and volume groups.
4359 See also C<guestfs_vglvuuids>.");
4361 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4363 "get the LV UUIDs of all LVs in the volume group",
4365 Given a VG called C<vgname>, this returns the UUIDs of all
4366 the logical volumes created in this volume group.
4368 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4369 calls to associate logical volumes and volume groups.
4371 See also C<guestfs_vgpvuuids>.");
4373 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4374 [InitBasicFS, Always, TestOutputBuffer (
4375 [["write_file"; "/src"; "hello, world"; "0"];
4376 ["copy_size"; "/src"; "/dest"; "5"];
4377 ["read_file"; "/dest"]], "hello")],
4378 "copy size bytes from source to destination using dd",
4380 This command copies exactly C<size> bytes from one source device
4381 or file C<src> to another destination device or file C<dest>.
4383 Note this will fail if the source is too short or if the destination
4384 is not large enough.");
4386 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4387 [InitBasicFSonLVM, Always, TestRun (
4388 [["zero_device"; "/dev/VG/LV"]])],
4389 "write zeroes to an entire device",
4391 This command writes zeroes over the entire C<device>. Compare
4392 with C<guestfs_zero> which just zeroes the first few blocks of
4395 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4396 [InitBasicFS, Always, TestOutput (
4397 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4398 ["cat"; "/hello"]], "hello\n")],
4399 "unpack compressed tarball to directory",
4401 This command uploads and unpacks local file C<tarball> (an
4402 I<xz compressed> tar file) into C<directory>.");
4404 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4406 "pack directory into compressed tarball",
4408 This command packs the contents of C<directory> and downloads
4409 it to local file C<tarball> (as an xz compressed tar archive).");
4411 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4413 "resize an NTFS filesystem",
4415 This command resizes an NTFS filesystem, expanding or
4416 shrinking it to the size of the underlying device.
4417 See also L<ntfsresize(8)>.");
4419 ("vgscan", (RErr, []), 232, [],
4420 [InitEmpty, Always, TestRun (
4422 "rescan for LVM physical volumes, volume groups and logical volumes",
4424 This rescans all block devices and rebuilds the list of LVM
4425 physical volumes, volume groups and logical volumes.");
4427 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4428 [InitEmpty, Always, TestRun (
4429 [["part_init"; "/dev/sda"; "mbr"];
4430 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4431 ["part_del"; "/dev/sda"; "1"]])],
4432 "delete a partition",
4434 This command deletes the partition numbered C<partnum> on C<device>.
4436 Note that in the case of MBR partitioning, deleting an
4437 extended partition also deletes any logical partitions
4440 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4441 [InitEmpty, Always, TestOutputTrue (
4442 [["part_init"; "/dev/sda"; "mbr"];
4443 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4444 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4445 ["part_get_bootable"; "/dev/sda"; "1"]])],
4446 "return true if a partition is bootable",
4448 This command returns true if the partition C<partnum> on
4449 C<device> has the bootable flag set.
4451 See also C<guestfs_part_set_bootable>.");
4453 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4454 [InitEmpty, Always, TestOutputInt (
4455 [["part_init"; "/dev/sda"; "mbr"];
4456 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4457 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4458 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4459 "get the MBR type byte (ID byte) from a partition",
4461 Returns the MBR type byte (also known as the ID byte) from
4462 the numbered partition C<partnum>.
4464 Note that only MBR (old DOS-style) partitions have type bytes.
4465 You will get undefined results for other partition table
4466 types (see C<guestfs_part_get_parttype>).");
4468 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4469 [], (* tested by part_get_mbr_id *)
4470 "set the MBR type byte (ID byte) of a partition",
4472 Sets the MBR type byte (also known as the ID byte) of
4473 the numbered partition C<partnum> to C<idbyte>. Note
4474 that the type bytes quoted in most documentation are
4475 in fact hexadecimal numbers, but usually documented
4476 without any leading \"0x\" which might be confusing.
4478 Note that only MBR (old DOS-style) partitions have type bytes.
4479 You will get undefined results for other partition table
4480 types (see C<guestfs_part_get_parttype>).");
4482 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4483 [InitISOFS, Always, TestOutput (
4484 [["checksum_device"; "md5"; "/dev/sdd"]],
4485 (Digest.to_hex (Digest.file "images/test.iso")))],
4486 "compute MD5, SHAx or CRC checksum of the contents of a device",
4488 This call computes the MD5, SHAx or CRC checksum of the
4489 contents of the device named C<device>. For the types of
4490 checksums supported see the C<guestfs_checksum> command.");
4492 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4493 [InitNone, Always, TestRun (
4494 [["part_disk"; "/dev/sda"; "mbr"];
4495 ["pvcreate"; "/dev/sda1"];
4496 ["vgcreate"; "VG"; "/dev/sda1"];
4497 ["lvcreate"; "LV"; "VG"; "10"];
4498 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4499 "expand an LV to fill free space",
4501 This expands an existing logical volume C<lv> so that it fills
4502 C<pc>% of the remaining free space in the volume group. Commonly
4503 you would call this with pc = 100 which expands the logical volume
4504 as much as possible, using all remaining free space in the volume
4507 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4508 [], (* XXX Augeas code needs tests. *)
4509 "clear Augeas path",
4511 Set the value associated with C<path> to C<NULL>. This
4512 is the same as the L<augtool(1)> C<clear> command.");
4514 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4515 [InitEmpty, Always, TestOutputInt (
4516 [["get_umask"]], 0o22)],
4517 "get the current umask",
4519 Return the current umask. By default the umask is C<022>
4520 unless it has been set by calling C<guestfs_umask>.");
4522 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4524 "upload a file to the appliance (internal use only)",
4526 The C<guestfs_debug_upload> command uploads a file to
4527 the libguestfs appliance.
4529 There is no comprehensive help for this command. You have
4530 to look at the file C<daemon/debug.c> in the libguestfs source
4531 to find out what it is for.");
4533 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4534 [InitBasicFS, Always, TestOutput (
4535 [["base64_in"; "../images/hello.b64"; "/hello"];
4536 ["cat"; "/hello"]], "hello\n")],
4537 "upload base64-encoded data to file",
4539 This command uploads base64-encoded data from C<base64file>
4542 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4544 "download file and encode as base64",
4546 This command downloads the contents of C<filename>, writing
4547 it out to local file C<base64file> encoded as base64.");
4551 let all_functions = non_daemon_functions @ daemon_functions
4553 (* In some places we want the functions to be displayed sorted
4554 * alphabetically, so this is useful:
4556 let all_functions_sorted =
4557 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4558 compare n1 n2) all_functions
4560 (* Field types for structures. *)
4562 | FChar (* C 'char' (really, a 7 bit byte). *)
4563 | FString (* nul-terminated ASCII string, NOT NULL. *)
4564 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4569 | FBytes (* Any int measure that counts bytes. *)
4570 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4571 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4573 (* Because we generate extra parsing code for LVM command line tools,
4574 * we have to pull out the LVM columns separately here.
4584 "pv_attr", FString (* XXX *);
4585 "pv_pe_count", FInt64;
4586 "pv_pe_alloc_count", FInt64;
4589 "pv_mda_count", FInt64;
4590 "pv_mda_free", FBytes;
4591 (* Not in Fedora 10:
4592 "pv_mda_size", FBytes;
4599 "vg_attr", FString (* XXX *);
4602 "vg_sysid", FString;
4603 "vg_extent_size", FBytes;
4604 "vg_extent_count", FInt64;
4605 "vg_free_count", FInt64;
4610 "snap_count", FInt64;
4613 "vg_mda_count", FInt64;
4614 "vg_mda_free", FBytes;
4615 (* Not in Fedora 10:
4616 "vg_mda_size", FBytes;
4622 "lv_attr", FString (* XXX *);
4625 "lv_kernel_major", FInt64;
4626 "lv_kernel_minor", FInt64;
4628 "seg_count", FInt64;
4630 "snap_percent", FOptPercent;
4631 "copy_percent", FOptPercent;
4634 "mirror_log", FString;
4638 (* Names and fields in all structures (in RStruct and RStructList)
4642 (* The old RIntBool return type, only ever used for aug_defnode. Do
4643 * not use this struct in any new code.
4646 "i", FInt32; (* for historical compatibility *)
4647 "b", FInt32; (* for historical compatibility *)
4650 (* LVM PVs, VGs, LVs. *)
4651 "lvm_pv", lvm_pv_cols;
4652 "lvm_vg", lvm_vg_cols;
4653 "lvm_lv", lvm_lv_cols;
4655 (* Column names and types from stat structures.
4656 * NB. Can't use things like 'st_atime' because glibc header files
4657 * define some of these as macros. Ugh.
4688 (* Column names in dirent structure. *)
4691 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4696 (* Version numbers. *)
4704 (* Extended attribute. *)
4706 "attrname", FString;
4710 (* Inotify events. *)
4714 "in_cookie", FUInt32;
4718 (* Partition table entry. *)
4721 "part_start", FBytes;
4723 "part_size", FBytes;
4725 ] (* end of structs *)
4727 (* Ugh, Java has to be different ..
4728 * These names are also used by the Haskell bindings.
4730 let java_structs = [
4731 "int_bool", "IntBool";
4736 "statvfs", "StatVFS";
4738 "version", "Version";
4740 "inotify_event", "INotifyEvent";
4741 "partition", "Partition";
4744 (* What structs are actually returned. *)
4745 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4747 (* Returns a list of RStruct/RStructList structs that are returned
4748 * by any function. Each element of returned list is a pair:
4750 * (structname, RStructOnly)
4751 * == there exists function which returns RStruct (_, structname)
4752 * (structname, RStructListOnly)
4753 * == there exists function which returns RStructList (_, structname)
4754 * (structname, RStructAndList)
4755 * == there are functions returning both RStruct (_, structname)
4756 * and RStructList (_, structname)
4758 let rstructs_used_by functions =
4759 (* ||| is a "logical OR" for rstructs_used_t *)
4763 | _, RStructAndList -> RStructAndList
4764 | RStructOnly, RStructListOnly
4765 | RStructListOnly, RStructOnly -> RStructAndList
4766 | RStructOnly, RStructOnly -> RStructOnly
4767 | RStructListOnly, RStructListOnly -> RStructListOnly
4770 let h = Hashtbl.create 13 in
4772 (* if elem->oldv exists, update entry using ||| operator,
4773 * else just add elem->newv to the hash
4775 let update elem newv =
4776 try let oldv = Hashtbl.find h elem in
4777 Hashtbl.replace h elem (newv ||| oldv)
4778 with Not_found -> Hashtbl.add h elem newv
4782 fun (_, style, _, _, _, _, _) ->
4783 match fst style with
4784 | RStruct (_, structname) -> update structname RStructOnly
4785 | RStructList (_, structname) -> update structname RStructListOnly
4789 (* return key->values as a list of (key,value) *)
4790 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4792 (* Used for testing language bindings. *)
4794 | CallString of string
4795 | CallOptString of string option
4796 | CallStringList of string list
4798 | CallInt64 of int64
4801 (* Used to memoize the result of pod2text. *)
4802 let pod2text_memo_filename = "src/.pod2text.data"
4803 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4805 let chan = open_in pod2text_memo_filename in
4806 let v = input_value chan in
4810 _ -> Hashtbl.create 13
4811 let pod2text_memo_updated () =
4812 let chan = open_out pod2text_memo_filename in
4813 output_value chan pod2text_memo;
4816 (* Useful functions.
4817 * Note we don't want to use any external OCaml libraries which
4818 * makes this a bit harder than it should be.
4820 module StringMap = Map.Make (String)
4822 let failwithf fs = ksprintf failwith fs
4824 let unique = let i = ref 0 in fun () -> incr i; !i
4826 let replace_char s c1 c2 =
4827 let s2 = String.copy s in
4828 let r = ref false in
4829 for i = 0 to String.length s2 - 1 do
4830 if String.unsafe_get s2 i = c1 then (
4831 String.unsafe_set s2 i c2;
4835 if not !r then s else s2
4839 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4841 let triml ?(test = isspace) str =
4843 let n = ref (String.length str) in
4844 while !n > 0 && test str.[!i]; do
4849 else String.sub str !i !n
4851 let trimr ?(test = isspace) str =
4852 let n = ref (String.length str) in
4853 while !n > 0 && test str.[!n-1]; do
4856 if !n = String.length str then str
4857 else String.sub str 0 !n
4859 let trim ?(test = isspace) str =
4860 trimr ~test (triml ~test str)
4862 let rec find s sub =
4863 let len = String.length s in
4864 let sublen = String.length sub in
4866 if i <= len-sublen then (
4868 if j < sublen then (
4869 if s.[i+j] = sub.[j] then loop2 (j+1)
4875 if r = -1 then loop (i+1) else r
4881 let rec replace_str s s1 s2 =
4882 let len = String.length s in
4883 let sublen = String.length s1 in
4884 let i = find s s1 in
4887 let s' = String.sub s 0 i in
4888 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4889 s' ^ s2 ^ replace_str s'' s1 s2
4892 let rec string_split sep str =
4893 let len = String.length str in
4894 let seplen = String.length sep in
4895 let i = find str sep in
4896 if i = -1 then [str]
4898 let s' = String.sub str 0 i in
4899 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4900 s' :: string_split sep s''
4903 let files_equal n1 n2 =
4904 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4905 match Sys.command cmd with
4908 | i -> failwithf "%s: failed with error code %d" cmd i
4910 let rec filter_map f = function
4914 | Some y -> y :: filter_map f xs
4915 | None -> filter_map f xs
4917 let rec find_map f = function
4918 | [] -> raise Not_found
4922 | None -> find_map f xs
4925 let rec loop i = function
4927 | x :: xs -> f i x; loop (i+1) xs
4932 let rec loop i = function
4934 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4938 let count_chars c str =
4939 let count = ref 0 in
4940 for i = 0 to String.length str - 1 do
4941 if c = String.unsafe_get str i then incr count
4945 let name_of_argt = function
4946 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4947 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4948 | FileIn n | FileOut n -> n
4950 let java_name_of_struct typ =
4951 try List.assoc typ java_structs
4954 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4956 let cols_of_struct typ =
4957 try List.assoc typ structs
4959 failwithf "cols_of_struct: unknown struct %s" typ
4961 let seq_of_test = function
4962 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4963 | TestOutputListOfDevices (s, _)
4964 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4965 | TestOutputTrue s | TestOutputFalse s
4966 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4967 | TestOutputStruct (s, _)
4968 | TestLastFail s -> s
4970 (* Handling for function flags. *)
4971 let protocol_limit_warning =
4972 "Because of the message protocol, there is a transfer limit
4973 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4975 let danger_will_robinson =
4976 "B<This command is dangerous. Without careful use you
4977 can easily destroy all your data>."
4979 let deprecation_notice flags =
4982 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4984 sprintf "This function is deprecated.
4985 In new code, use the C<%s> call instead.
4987 Deprecated functions will not be removed from the API, but the
4988 fact that they are deprecated indicates that there are problems
4989 with correct use of these functions." alt in
4994 (* Create list of optional groups. *)
4996 let h = Hashtbl.create 13 in
4998 fun (name, _, _, flags, _, _, _) ->
5002 let names = try Hashtbl.find h group with Not_found -> [] in
5003 Hashtbl.replace h group (name :: names)
5007 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5010 fun group -> group, List.sort compare (Hashtbl.find h group)
5012 List.sort (fun x y -> compare (fst x) (fst y)) groups
5014 (* Check function names etc. for consistency. *)
5015 let check_functions () =
5016 let contains_uppercase str =
5017 let len = String.length str in
5019 if i >= len then false
5022 if c >= 'A' && c <= 'Z' then true
5029 (* Check function names. *)
5031 fun (name, _, _, _, _, _, _) ->
5032 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5033 failwithf "function name %s does not need 'guestfs' prefix" name;
5035 failwithf "function name is empty";
5036 if name.[0] < 'a' || name.[0] > 'z' then
5037 failwithf "function name %s must start with lowercase a-z" name;
5038 if String.contains name '-' then
5039 failwithf "function name %s should not contain '-', use '_' instead."
5043 (* Check function parameter/return names. *)
5045 fun (name, style, _, _, _, _, _) ->
5046 let check_arg_ret_name n =
5047 if contains_uppercase n then
5048 failwithf "%s param/ret %s should not contain uppercase chars"
5050 if String.contains n '-' || String.contains n '_' then
5051 failwithf "%s param/ret %s should not contain '-' or '_'"
5054 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;
5055 if n = "int" || n = "char" || n = "short" || n = "long" then
5056 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5057 if n = "i" || n = "n" then
5058 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5059 if n = "argv" || n = "args" then
5060 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5062 (* List Haskell, OCaml and C keywords here.
5063 * http://www.haskell.org/haskellwiki/Keywords
5064 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5065 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5066 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5067 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5068 * Omitting _-containing words, since they're handled above.
5069 * Omitting the OCaml reserved word, "val", is ok,
5070 * and saves us from renaming several parameters.
5073 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5074 "char"; "class"; "const"; "constraint"; "continue"; "data";
5075 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5076 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5077 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5078 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5079 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5081 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5082 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5083 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5084 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5085 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5086 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5087 "volatile"; "when"; "where"; "while";
5089 if List.mem n reserved then
5090 failwithf "%s has param/ret using reserved word %s" name n;
5093 (match fst style with
5095 | RInt n | RInt64 n | RBool n
5096 | RConstString n | RConstOptString n | RString n
5097 | RStringList n | RStruct (n, _) | RStructList (n, _)
5098 | RHashtable n | RBufferOut n ->
5099 check_arg_ret_name n
5101 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5104 (* Check short descriptions. *)
5106 fun (name, _, _, _, _, shortdesc, _) ->
5107 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5108 failwithf "short description of %s should begin with lowercase." name;
5109 let c = shortdesc.[String.length shortdesc-1] in
5110 if c = '\n' || c = '.' then
5111 failwithf "short description of %s should not end with . or \\n." name
5114 (* Check long descriptions. *)
5116 fun (name, _, _, _, _, _, longdesc) ->
5117 if longdesc.[String.length longdesc-1] = '\n' then
5118 failwithf "long description of %s should not end with \\n." name
5121 (* Check proc_nrs. *)
5123 fun (name, _, proc_nr, _, _, _, _) ->
5124 if proc_nr <= 0 then
5125 failwithf "daemon function %s should have proc_nr > 0" name
5129 fun (name, _, proc_nr, _, _, _, _) ->
5130 if proc_nr <> -1 then
5131 failwithf "non-daemon function %s should have proc_nr -1" name
5132 ) non_daemon_functions;
5135 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5138 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5139 let rec loop = function
5142 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5144 | (name1,nr1) :: (name2,nr2) :: _ ->
5145 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5153 (* Ignore functions that have no tests. We generate a
5154 * warning when the user does 'make check' instead.
5156 | name, _, _, _, [], _, _ -> ()
5157 | name, _, _, _, tests, _, _ ->
5161 match seq_of_test test with
5163 failwithf "%s has a test containing an empty sequence" name
5164 | cmds -> List.map List.hd cmds
5166 let funcs = List.flatten funcs in
5168 let tested = List.mem name funcs in
5171 failwithf "function %s has tests but does not test itself" name
5174 (* 'pr' prints to the current output file. *)
5175 let chan = ref Pervasives.stdout
5180 let i = count_chars '\n' str in
5181 lines := !lines + i;
5182 output_string !chan str
5185 let copyright_years =
5186 let this_year = 1900 + (localtime (time ())).tm_year in
5187 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5189 (* Generate a header block in a number of standard styles. *)
5190 type comment_style =
5191 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5192 type license = GPLv2plus | LGPLv2plus
5194 let generate_header ?(extra_inputs = []) comment license =
5195 let inputs = "src/generator.ml" :: extra_inputs in
5196 let c = match comment with
5197 | CStyle -> pr "/* "; " *"
5198 | CPlusPlusStyle -> pr "// "; "//"
5199 | HashStyle -> pr "# "; "#"
5200 | OCamlStyle -> pr "(* "; " *"
5201 | HaskellStyle -> pr "{- "; " " in
5202 pr "libguestfs generated file\n";
5203 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5204 List.iter (pr "%s %s\n" c) inputs;
5205 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5207 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5211 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5212 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5213 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5214 pr "%s (at your option) any later version.\n" c;
5216 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5217 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5218 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5219 pr "%s GNU General Public License for more details.\n" c;
5221 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5222 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5223 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5226 pr "%s This library is free software; you can redistribute it and/or\n" c;
5227 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5228 pr "%s License as published by the Free Software Foundation; either\n" c;
5229 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5231 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5232 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5233 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5234 pr "%s Lesser General Public License for more details.\n" c;
5236 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5237 pr "%s License along with this library; if not, write to the Free Software\n" c;
5238 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5241 | CStyle -> pr " */\n"
5244 | OCamlStyle -> pr " *)\n"
5245 | HaskellStyle -> pr "-}\n"
5249 (* Start of main code generation functions below this line. *)
5251 (* Generate the pod documentation for the C API. *)
5252 let rec generate_actions_pod () =
5254 fun (shortname, style, _, flags, _, _, longdesc) ->
5255 if not (List.mem NotInDocs flags) then (
5256 let name = "guestfs_" ^ shortname in
5257 pr "=head2 %s\n\n" name;
5259 generate_prototype ~extern:false ~handle:"g" name style;
5261 pr "%s\n\n" longdesc;
5262 (match fst style with
5264 pr "This function returns 0 on success or -1 on error.\n\n"
5266 pr "On error this function returns -1.\n\n"
5268 pr "On error this function returns -1.\n\n"
5270 pr "This function returns a C truth value on success or -1 on error.\n\n"
5272 pr "This function returns a string, or NULL on error.
5273 The string is owned by the guest handle and must I<not> be freed.\n\n"
5274 | RConstOptString _ ->
5275 pr "This function returns a string which may be NULL.
5276 There is way to return an error from this function.
5277 The string is owned by the guest handle and must I<not> be freed.\n\n"
5279 pr "This function returns a string, or NULL on error.
5280 I<The caller must free the returned string after use>.\n\n"
5282 pr "This function returns a NULL-terminated array of strings
5283 (like L<environ(3)>), or NULL if there was an error.
5284 I<The caller must free the strings and the array after use>.\n\n"
5285 | RStruct (_, typ) ->
5286 pr "This function returns a C<struct guestfs_%s *>,
5287 or NULL if there was an error.
5288 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5289 | RStructList (_, typ) ->
5290 pr "This function returns a C<struct guestfs_%s_list *>
5291 (see E<lt>guestfs-structs.hE<gt>),
5292 or NULL if there was an error.
5293 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5295 pr "This function returns a NULL-terminated array of
5296 strings, or NULL if there was an error.
5297 The array of strings will always have length C<2n+1>, where
5298 C<n> keys and values alternate, followed by the trailing NULL entry.
5299 I<The caller must free the strings and the array after use>.\n\n"
5301 pr "This function returns a buffer, or NULL on error.
5302 The size of the returned buffer is written to C<*size_r>.
5303 I<The caller must free the returned buffer after use>.\n\n"
5305 if List.mem ProtocolLimitWarning flags then
5306 pr "%s\n\n" protocol_limit_warning;
5307 if List.mem DangerWillRobinson flags then
5308 pr "%s\n\n" danger_will_robinson;
5309 match deprecation_notice flags with
5311 | Some txt -> pr "%s\n\n" txt
5313 ) all_functions_sorted
5315 and generate_structs_pod () =
5316 (* Structs documentation. *)
5319 pr "=head2 guestfs_%s\n" typ;
5321 pr " struct guestfs_%s {\n" typ;
5324 | name, FChar -> pr " char %s;\n" name
5325 | name, FUInt32 -> pr " uint32_t %s;\n" name
5326 | name, FInt32 -> pr " int32_t %s;\n" name
5327 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5328 | name, FInt64 -> pr " int64_t %s;\n" name
5329 | name, FString -> pr " char *%s;\n" name
5331 pr " /* The next two fields describe a byte array. */\n";
5332 pr " uint32_t %s_len;\n" name;
5333 pr " char *%s;\n" name
5335 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5336 pr " char %s[32];\n" name
5337 | name, FOptPercent ->
5338 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5339 pr " float %s;\n" name
5343 pr " struct guestfs_%s_list {\n" typ;
5344 pr " uint32_t len; /* Number of elements in list. */\n";
5345 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5348 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5349 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5354 and generate_availability_pod () =
5355 (* Availability documentation. *)
5359 fun (group, functions) ->
5360 pr "=item B<%s>\n" group;
5362 pr "The following functions:\n";
5363 List.iter (pr "L</guestfs_%s>\n") functions;
5369 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5370 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5372 * We have to use an underscore instead of a dash because otherwise
5373 * rpcgen generates incorrect code.
5375 * This header is NOT exported to clients, but see also generate_structs_h.
5377 and generate_xdr () =
5378 generate_header CStyle LGPLv2plus;
5380 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5381 pr "typedef string str<>;\n";
5384 (* Internal structures. *)
5388 pr "struct guestfs_int_%s {\n" typ;
5390 | name, FChar -> pr " char %s;\n" name
5391 | name, FString -> pr " string %s<>;\n" name
5392 | name, FBuffer -> pr " opaque %s<>;\n" name
5393 | name, FUUID -> pr " opaque %s[32];\n" name
5394 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5395 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5396 | name, FOptPercent -> pr " float %s;\n" name
5400 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5405 fun (shortname, style, _, _, _, _, _) ->
5406 let name = "guestfs_" ^ shortname in
5408 (match snd style with
5411 pr "struct %s_args {\n" name;
5414 | Pathname n | Device n | Dev_or_Path n | String n ->
5415 pr " string %s<>;\n" n
5416 | OptString n -> pr " str *%s;\n" n
5417 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5418 | Bool n -> pr " bool %s;\n" n
5419 | Int n -> pr " int %s;\n" n
5420 | Int64 n -> pr " hyper %s;\n" n
5421 | FileIn _ | FileOut _ -> ()
5425 (match fst style with
5428 pr "struct %s_ret {\n" name;
5432 pr "struct %s_ret {\n" name;
5433 pr " hyper %s;\n" n;
5436 pr "struct %s_ret {\n" name;
5439 | RConstString _ | RConstOptString _ ->
5440 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5442 pr "struct %s_ret {\n" name;
5443 pr " string %s<>;\n" n;
5446 pr "struct %s_ret {\n" name;
5447 pr " str %s<>;\n" n;
5449 | RStruct (n, typ) ->
5450 pr "struct %s_ret {\n" name;
5451 pr " guestfs_int_%s %s;\n" typ n;
5453 | RStructList (n, typ) ->
5454 pr "struct %s_ret {\n" name;
5455 pr " guestfs_int_%s_list %s;\n" typ n;
5458 pr "struct %s_ret {\n" name;
5459 pr " str %s<>;\n" n;
5462 pr "struct %s_ret {\n" name;
5463 pr " opaque %s<>;\n" n;
5468 (* Table of procedure numbers. *)
5469 pr "enum guestfs_procedure {\n";
5471 fun (shortname, _, proc_nr, _, _, _, _) ->
5472 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5474 pr " GUESTFS_PROC_NR_PROCS\n";
5478 (* Having to choose a maximum message size is annoying for several
5479 * reasons (it limits what we can do in the API), but it (a) makes
5480 * the protocol a lot simpler, and (b) provides a bound on the size
5481 * of the daemon which operates in limited memory space.
5483 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5486 (* Message header, etc. *)
5488 /* The communication protocol is now documented in the guestfs(3)
5492 const GUESTFS_PROGRAM = 0x2000F5F5;
5493 const GUESTFS_PROTOCOL_VERSION = 1;
5495 /* These constants must be larger than any possible message length. */
5496 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5497 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5499 enum guestfs_message_direction {
5500 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5501 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5504 enum guestfs_message_status {
5505 GUESTFS_STATUS_OK = 0,
5506 GUESTFS_STATUS_ERROR = 1
5509 const GUESTFS_ERROR_LEN = 256;
5511 struct guestfs_message_error {
5512 string error_message<GUESTFS_ERROR_LEN>;
5515 struct guestfs_message_header {
5516 unsigned prog; /* GUESTFS_PROGRAM */
5517 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5518 guestfs_procedure proc; /* GUESTFS_PROC_x */
5519 guestfs_message_direction direction;
5520 unsigned serial; /* message serial number */
5521 guestfs_message_status status;
5524 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5526 struct guestfs_chunk {
5527 int cancel; /* if non-zero, transfer is cancelled */
5528 /* data size is 0 bytes if the transfer has finished successfully */
5529 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5533 (* Generate the guestfs-structs.h file. *)
5534 and generate_structs_h () =
5535 generate_header CStyle LGPLv2plus;
5537 (* This is a public exported header file containing various
5538 * structures. The structures are carefully written to have
5539 * exactly the same in-memory format as the XDR structures that
5540 * we use on the wire to the daemon. The reason for creating
5541 * copies of these structures here is just so we don't have to
5542 * export the whole of guestfs_protocol.h (which includes much
5543 * unrelated and XDR-dependent stuff that we don't want to be
5544 * public, or required by clients).
5546 * To reiterate, we will pass these structures to and from the
5547 * client with a simple assignment or memcpy, so the format
5548 * must be identical to what rpcgen / the RFC defines.
5551 (* Public structures. *)
5554 pr "struct guestfs_%s {\n" typ;
5557 | name, FChar -> pr " char %s;\n" name
5558 | name, FString -> pr " char *%s;\n" name
5560 pr " uint32_t %s_len;\n" name;
5561 pr " char *%s;\n" name
5562 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5563 | name, FUInt32 -> pr " uint32_t %s;\n" name
5564 | name, FInt32 -> pr " int32_t %s;\n" name
5565 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5566 | name, FInt64 -> pr " int64_t %s;\n" name
5567 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5571 pr "struct guestfs_%s_list {\n" typ;
5572 pr " uint32_t len;\n";
5573 pr " struct guestfs_%s *val;\n" typ;
5576 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5577 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5581 (* Generate the guestfs-actions.h file. *)
5582 and generate_actions_h () =
5583 generate_header CStyle LGPLv2plus;
5585 fun (shortname, style, _, _, _, _, _) ->
5586 let name = "guestfs_" ^ shortname in
5587 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5591 (* Generate the guestfs-internal-actions.h file. *)
5592 and generate_internal_actions_h () =
5593 generate_header CStyle LGPLv2plus;
5595 fun (shortname, style, _, _, _, _, _) ->
5596 let name = "guestfs__" ^ shortname in
5597 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5599 ) non_daemon_functions
5601 (* Generate the client-side dispatch stubs. *)
5602 and generate_client_actions () =
5603 generate_header CStyle LGPLv2plus;
5610 #include <inttypes.h>
5612 #include \"guestfs.h\"
5613 #include \"guestfs-internal.h\"
5614 #include \"guestfs-internal-actions.h\"
5615 #include \"guestfs_protocol.h\"
5617 #define error guestfs_error
5618 //#define perrorf guestfs_perrorf
5619 #define safe_malloc guestfs_safe_malloc
5620 #define safe_realloc guestfs_safe_realloc
5621 //#define safe_strdup guestfs_safe_strdup
5622 #define safe_memdup guestfs_safe_memdup
5624 /* Check the return message from a call for validity. */
5626 check_reply_header (guestfs_h *g,
5627 const struct guestfs_message_header *hdr,
5628 unsigned int proc_nr, unsigned int serial)
5630 if (hdr->prog != GUESTFS_PROGRAM) {
5631 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5634 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5635 error (g, \"wrong protocol version (%%d/%%d)\",
5636 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5639 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5640 error (g, \"unexpected message direction (%%d/%%d)\",
5641 hdr->direction, GUESTFS_DIRECTION_REPLY);
5644 if (hdr->proc != proc_nr) {
5645 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5648 if (hdr->serial != serial) {
5649 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5656 /* Check we are in the right state to run a high-level action. */
5658 check_state (guestfs_h *g, const char *caller)
5660 if (!guestfs__is_ready (g)) {
5661 if (guestfs__is_config (g) || guestfs__is_launching (g))
5662 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5665 error (g, \"%%s called from the wrong state, %%d != READY\",
5666 caller, guestfs__get_state (g));
5674 (* Generate code to generate guestfish call traces. *)
5675 let trace_call shortname style =
5676 pr " if (guestfs__get_trace (g)) {\n";
5679 List.exists (function
5680 | StringList _ | DeviceList _ -> true
5681 | _ -> false) (snd style) in
5687 pr " printf (\"%s\");\n" shortname;
5690 | String n (* strings *)
5696 (* guestfish doesn't support string escaping, so neither do we *)
5697 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5698 | OptString n -> (* string option *)
5699 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5700 pr " else printf (\" null\");\n"
5702 | DeviceList n -> (* string list *)
5703 pr " putchar (' ');\n";
5704 pr " putchar ('\"');\n";
5705 pr " for (i = 0; %s[i]; ++i) {\n" n;
5706 pr " if (i > 0) putchar (' ');\n";
5707 pr " fputs (%s[i], stdout);\n" n;
5709 pr " putchar ('\"');\n";
5710 | Bool n -> (* boolean *)
5711 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5712 | Int n -> (* int *)
5713 pr " printf (\" %%d\", %s);\n" n
5715 pr " printf (\" %%\" PRIi64, %s);\n" n
5717 pr " putchar ('\\n');\n";
5722 (* For non-daemon functions, generate a wrapper around each function. *)
5724 fun (shortname, style, _, _, _, _, _) ->
5725 let name = "guestfs_" ^ shortname in
5727 generate_prototype ~extern:false ~semicolon:false ~newline:true
5728 ~handle:"g" name style;
5730 trace_call shortname style;
5731 pr " return guestfs__%s " shortname;
5732 generate_c_call_args ~handle:"g" style;
5736 ) non_daemon_functions;
5738 (* Client-side stubs for each function. *)
5740 fun (shortname, style, _, _, _, _, _) ->
5741 let name = "guestfs_" ^ shortname in
5743 (* Generate the action stub. *)
5744 generate_prototype ~extern:false ~semicolon:false ~newline:true
5745 ~handle:"g" name style;
5748 match fst style with
5749 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5750 | RConstString _ | RConstOptString _ ->
5751 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5752 | RString _ | RStringList _
5753 | RStruct _ | RStructList _
5754 | RHashtable _ | RBufferOut _ ->
5759 (match snd style with
5761 | _ -> pr " struct %s_args args;\n" name
5764 pr " guestfs_message_header hdr;\n";
5765 pr " guestfs_message_error err;\n";
5767 match fst style with
5769 | RConstString _ | RConstOptString _ ->
5770 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5772 | RBool _ | RString _ | RStringList _
5773 | RStruct _ | RStructList _
5774 | RHashtable _ | RBufferOut _ ->
5775 pr " struct %s_ret ret;\n" name;
5778 pr " int serial;\n";
5781 trace_call shortname style;
5782 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5783 shortname error_code;
5784 pr " guestfs___set_busy (g);\n";
5787 (* Send the main header and arguments. *)
5788 (match snd style with
5790 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5791 (String.uppercase shortname)
5795 | Pathname n | Device n | Dev_or_Path n | String n ->
5796 pr " args.%s = (char *) %s;\n" n n
5798 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5799 | StringList n | DeviceList n ->
5800 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5801 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5803 pr " args.%s = %s;\n" n n
5805 pr " args.%s = %s;\n" n n
5807 pr " args.%s = %s;\n" n n
5808 | FileIn _ | FileOut _ -> ()
5810 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5811 (String.uppercase shortname);
5812 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5815 pr " if (serial == -1) {\n";
5816 pr " guestfs___end_busy (g);\n";
5817 pr " return %s;\n" error_code;
5821 (* Send any additional files (FileIn) requested. *)
5822 let need_read_reply_label = ref false in
5826 pr " r = guestfs___send_file (g, %s);\n" n;
5827 pr " if (r == -1) {\n";
5828 pr " guestfs___end_busy (g);\n";
5829 pr " return %s;\n" error_code;
5831 pr " if (r == -2) /* daemon cancelled */\n";
5832 pr " goto read_reply;\n";
5833 need_read_reply_label := true;
5838 (* Wait for the reply from the remote end. *)
5839 if !need_read_reply_label then pr " read_reply:\n";
5840 pr " memset (&hdr, 0, sizeof hdr);\n";
5841 pr " memset (&err, 0, sizeof err);\n";
5842 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5844 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5848 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5851 pr " if (r == -1) {\n";
5852 pr " guestfs___end_busy (g);\n";
5853 pr " return %s;\n" error_code;
5857 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5858 (String.uppercase shortname);
5859 pr " guestfs___end_busy (g);\n";
5860 pr " return %s;\n" error_code;
5864 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5865 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5866 pr " free (err.error_message);\n";
5867 pr " guestfs___end_busy (g);\n";
5868 pr " return %s;\n" error_code;
5872 (* Expecting to receive further files (FileOut)? *)
5876 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5877 pr " guestfs___end_busy (g);\n";
5878 pr " return %s;\n" error_code;
5884 pr " guestfs___end_busy (g);\n";
5886 (match fst style with
5887 | RErr -> pr " return 0;\n"
5888 | RInt n | RInt64 n | RBool n ->
5889 pr " return ret.%s;\n" n
5890 | RConstString _ | RConstOptString _ ->
5891 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5893 pr " return ret.%s; /* caller will free */\n" n
5894 | RStringList n | RHashtable n ->
5895 pr " /* caller will free this, but we need to add a NULL entry */\n";
5896 pr " ret.%s.%s_val =\n" n n;
5897 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5898 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5900 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5901 pr " return ret.%s.%s_val;\n" n n
5903 pr " /* caller will free this */\n";
5904 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5905 | RStructList (n, _) ->
5906 pr " /* caller will free this */\n";
5907 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5909 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5910 pr " * _val might be NULL here. To make the API saner for\n";
5911 pr " * callers, we turn this case into a unique pointer (using\n";
5912 pr " * malloc(1)).\n";
5914 pr " if (ret.%s.%s_len > 0) {\n" n n;
5915 pr " *size_r = ret.%s.%s_len;\n" n n;
5916 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5918 pr " free (ret.%s.%s_val);\n" n n;
5919 pr " char *p = safe_malloc (g, 1);\n";
5920 pr " *size_r = ret.%s.%s_len;\n" n n;
5928 (* Functions to free structures. *)
5929 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5930 pr " * structure format is identical to the XDR format. See note in\n";
5931 pr " * generator.ml.\n";
5938 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5940 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5946 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5948 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5955 (* Generate daemon/actions.h. *)
5956 and generate_daemon_actions_h () =
5957 generate_header CStyle GPLv2plus;
5959 pr "#include \"../src/guestfs_protocol.h\"\n";
5963 fun (name, style, _, _, _, _, _) ->
5965 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5969 (* Generate the linker script which controls the visibility of
5970 * symbols in the public ABI and ensures no other symbols get
5971 * exported accidentally.
5973 and generate_linker_script () =
5974 generate_header HashStyle GPLv2plus;
5979 "guestfs_get_error_handler";
5980 "guestfs_get_out_of_memory_handler";
5981 "guestfs_last_error";
5982 "guestfs_set_error_handler";
5983 "guestfs_set_launch_done_callback";
5984 "guestfs_set_log_message_callback";
5985 "guestfs_set_out_of_memory_handler";
5986 "guestfs_set_subprocess_quit_callback";
5988 (* Unofficial parts of the API: the bindings code use these
5989 * functions, so it is useful to export them.
5991 "guestfs_safe_calloc";
5992 "guestfs_safe_malloc";
5995 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5999 List.map (fun (typ, _) ->
6000 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6003 let globals = List.sort compare (globals @ functions @ structs) in
6007 List.iter (pr " %s;\n") globals;
6014 (* Generate the server-side stubs. *)
6015 and generate_daemon_actions () =
6016 generate_header CStyle GPLv2plus;
6018 pr "#include <config.h>\n";
6020 pr "#include <stdio.h>\n";
6021 pr "#include <stdlib.h>\n";
6022 pr "#include <string.h>\n";
6023 pr "#include <inttypes.h>\n";
6024 pr "#include <rpc/types.h>\n";
6025 pr "#include <rpc/xdr.h>\n";
6027 pr "#include \"daemon.h\"\n";
6028 pr "#include \"c-ctype.h\"\n";
6029 pr "#include \"../src/guestfs_protocol.h\"\n";
6030 pr "#include \"actions.h\"\n";
6034 fun (name, style, _, _, _, _, _) ->
6035 (* Generate server-side stubs. *)
6036 pr "static void %s_stub (XDR *xdr_in)\n" name;
6039 match fst style with
6040 | RErr | RInt _ -> pr " int r;\n"; "-1"
6041 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6042 | RBool _ -> pr " int r;\n"; "-1"
6043 | RConstString _ | RConstOptString _ ->
6044 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6045 | RString _ -> pr " char *r;\n"; "NULL"
6046 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6047 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6048 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6050 pr " size_t size = 1;\n";
6054 (match snd style with
6057 pr " struct guestfs_%s_args args;\n" name;
6060 | Device n | Dev_or_Path n
6063 | OptString n -> pr " char *%s;\n" n
6064 | StringList n | DeviceList n -> pr " char **%s;\n" n
6065 | Bool n -> pr " int %s;\n" n
6066 | Int n -> pr " int %s;\n" n
6067 | Int64 n -> pr " int64_t %s;\n" n
6068 | FileIn _ | FileOut _ -> ()
6074 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6076 (match snd style with
6079 pr " memset (&args, 0, sizeof args);\n";
6081 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6083 pr " cancel_receive ();\n";
6084 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6088 pr " char *%s = args.%s;\n" n n
6090 let pr_list_handling_code n =
6091 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6092 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6093 pr " if (%s == NULL) {\n" n;
6095 pr " cancel_receive ();\n";
6096 pr " reply_with_perror (\"realloc\");\n";
6099 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6100 pr " args.%s.%s_val = %s;\n" n n n;
6106 pr " ABS_PATH (%s, %s, goto done);\n"
6107 n (if is_filein then "cancel_receive ()" else "");
6110 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6111 n (if is_filein then "cancel_receive ()" else "");
6114 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6115 n (if is_filein then "cancel_receive ()" else "");
6116 | String n -> pr_args n
6117 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6119 pr_list_handling_code n;
6121 pr_list_handling_code n;
6122 pr " /* Ensure that each is a device,\n";
6123 pr " * and perform device name translation. */\n";
6124 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6125 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6126 (if is_filein then "cancel_receive ()" else "");
6128 | Bool n -> pr " %s = args.%s;\n" n n
6129 | Int n -> pr " %s = args.%s;\n" n n
6130 | Int64 n -> pr " %s = args.%s;\n" n n
6131 | FileIn _ | FileOut _ -> ()
6137 (* this is used at least for do_equal *)
6138 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6139 (* Emit NEED_ROOT just once, even when there are two or
6140 more Pathname args *)
6141 pr " NEED_ROOT (%s, goto done);\n"
6142 (if is_filein then "cancel_receive ()" else "");
6145 (* Don't want to call the impl with any FileIn or FileOut
6146 * parameters, since these go "outside" the RPC protocol.
6149 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6151 pr " r = do_%s " name;
6152 generate_c_call_args (fst style, args');
6155 (match fst style with
6156 | RErr | RInt _ | RInt64 _ | RBool _
6157 | RConstString _ | RConstOptString _
6158 | RString _ | RStringList _ | RHashtable _
6159 | RStruct (_, _) | RStructList (_, _) ->
6160 pr " if (r == %s)\n" error_code;
6161 pr " /* do_%s has already called reply_with_error */\n" name;
6165 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6166 pr " * an ordinary zero-length buffer), so be careful ...\n";
6168 pr " if (size == 1 && r == %s)\n" error_code;
6169 pr " /* do_%s has already called reply_with_error */\n" name;
6174 (* If there are any FileOut parameters, then the impl must
6175 * send its own reply.
6178 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6180 pr " /* do_%s has already sent a reply */\n" name
6182 match fst style with
6183 | RErr -> pr " reply (NULL, NULL);\n"
6184 | RInt n | RInt64 n | RBool n ->
6185 pr " struct guestfs_%s_ret ret;\n" name;
6186 pr " ret.%s = r;\n" n;
6187 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6189 | RConstString _ | RConstOptString _ ->
6190 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6192 pr " struct guestfs_%s_ret ret;\n" name;
6193 pr " ret.%s = r;\n" n;
6194 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6197 | RStringList n | RHashtable n ->
6198 pr " struct guestfs_%s_ret ret;\n" name;
6199 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6200 pr " ret.%s.%s_val = r;\n" n n;
6201 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6203 pr " free_strings (r);\n"
6205 pr " struct guestfs_%s_ret ret;\n" name;
6206 pr " ret.%s = *r;\n" n;
6207 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6209 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6211 | RStructList (n, _) ->
6212 pr " struct guestfs_%s_ret ret;\n" name;
6213 pr " ret.%s = *r;\n" n;
6214 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6216 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6219 pr " struct guestfs_%s_ret ret;\n" name;
6220 pr " ret.%s.%s_val = r;\n" n n;
6221 pr " ret.%s.%s_len = size;\n" n n;
6222 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6227 (* Free the args. *)
6229 (match snd style with
6232 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6239 (* Dispatch function. *)
6240 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6242 pr " switch (proc_nr) {\n";
6245 fun (name, style, _, _, _, _, _) ->
6246 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6247 pr " %s_stub (xdr_in);\n" name;
6252 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";
6257 (* LVM columns and tokenization functions. *)
6258 (* XXX This generates crap code. We should rethink how we
6264 pr "static const char *lvm_%s_cols = \"%s\";\n"
6265 typ (String.concat "," (List.map fst cols));
6268 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6270 pr " char *tok, *p, *next;\n";
6274 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6277 pr " if (!str) {\n";
6278 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6281 pr " if (!*str || c_isspace (*str)) {\n";
6282 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6287 fun (name, coltype) ->
6288 pr " if (!tok) {\n";
6289 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6292 pr " p = strchrnul (tok, ',');\n";
6293 pr " if (*p) next = p+1; else next = NULL;\n";
6294 pr " *p = '\\0';\n";
6297 pr " r->%s = strdup (tok);\n" name;
6298 pr " if (r->%s == NULL) {\n" name;
6299 pr " perror (\"strdup\");\n";
6303 pr " for (i = j = 0; i < 32; ++j) {\n";
6304 pr " if (tok[j] == '\\0') {\n";
6305 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6307 pr " } else if (tok[j] != '-')\n";
6308 pr " r->%s[i++] = tok[j];\n" name;
6311 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6312 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6316 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6317 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6321 pr " if (tok[0] == '\\0')\n";
6322 pr " r->%s = -1;\n" name;
6323 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6324 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6327 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6328 assert false (* can never be an LVM column *)
6330 pr " tok = next;\n";
6333 pr " if (tok != NULL) {\n";
6334 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6341 pr "guestfs_int_lvm_%s_list *\n" typ;
6342 pr "parse_command_line_%ss (void)\n" typ;
6344 pr " char *out, *err;\n";
6345 pr " char *p, *pend;\n";
6347 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6348 pr " void *newp;\n";
6350 pr " ret = malloc (sizeof *ret);\n";
6351 pr " if (!ret) {\n";
6352 pr " reply_with_perror (\"malloc\");\n";
6353 pr " return NULL;\n";
6356 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6357 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6359 pr " r = command (&out, &err,\n";
6360 pr " \"lvm\", \"%ss\",\n" typ;
6361 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6362 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6363 pr " if (r == -1) {\n";
6364 pr " reply_with_error (\"%%s\", err);\n";
6365 pr " free (out);\n";
6366 pr " free (err);\n";
6367 pr " free (ret);\n";
6368 pr " return NULL;\n";
6371 pr " free (err);\n";
6373 pr " /* Tokenize each line of the output. */\n";
6376 pr " while (p) {\n";
6377 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6378 pr " if (pend) {\n";
6379 pr " *pend = '\\0';\n";
6383 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6386 pr " if (!*p) { /* Empty line? Skip it. */\n";
6391 pr " /* Allocate some space to store this next entry. */\n";
6392 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6393 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6394 pr " if (newp == NULL) {\n";
6395 pr " reply_with_perror (\"realloc\");\n";
6396 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6397 pr " free (ret);\n";
6398 pr " free (out);\n";
6399 pr " return NULL;\n";
6401 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6403 pr " /* Tokenize the next entry. */\n";
6404 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6405 pr " if (r == -1) {\n";
6406 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6407 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6408 pr " free (ret);\n";
6409 pr " free (out);\n";
6410 pr " return NULL;\n";
6417 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6419 pr " free (out);\n";
6420 pr " return ret;\n";
6423 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6425 (* Generate a list of function names, for debugging in the daemon.. *)
6426 and generate_daemon_names () =
6427 generate_header CStyle GPLv2plus;
6429 pr "#include <config.h>\n";
6431 pr "#include \"daemon.h\"\n";
6434 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6435 pr "const char *function_names[] = {\n";
6437 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6441 (* Generate the optional groups for the daemon to implement
6442 * guestfs_available.
6444 and generate_daemon_optgroups_c () =
6445 generate_header CStyle GPLv2plus;
6447 pr "#include <config.h>\n";
6449 pr "#include \"daemon.h\"\n";
6450 pr "#include \"optgroups.h\"\n";
6453 pr "struct optgroup optgroups[] = {\n";
6456 pr " { \"%s\", optgroup_%s_available },\n" group group
6458 pr " { NULL, NULL }\n";
6461 and generate_daemon_optgroups_h () =
6462 generate_header CStyle GPLv2plus;
6466 pr "extern int optgroup_%s_available (void);\n" group
6469 (* Generate the tests. *)
6470 and generate_tests () =
6471 generate_header CStyle GPLv2plus;
6478 #include <sys/types.h>
6481 #include \"guestfs.h\"
6482 #include \"guestfs-internal.h\"
6484 static guestfs_h *g;
6485 static int suppress_error = 0;
6487 static void print_error (guestfs_h *g, void *data, const char *msg)
6489 if (!suppress_error)
6490 fprintf (stderr, \"%%s\\n\", msg);
6493 /* FIXME: nearly identical code appears in fish.c */
6494 static void print_strings (char *const *argv)
6498 for (argc = 0; argv[argc] != NULL; ++argc)
6499 printf (\"\\t%%s\\n\", argv[argc]);
6503 static void print_table (char const *const *argv)
6507 for (i = 0; argv[i] != NULL; i += 2)
6508 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6514 (* Generate a list of commands which are not tested anywhere. *)
6515 pr "static void no_test_warnings (void)\n";
6518 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6520 fun (_, _, _, _, tests, _, _) ->
6521 let tests = filter_map (
6523 | (_, (Always|If _|Unless _), test) -> Some test
6524 | (_, Disabled, _) -> None
6526 let seq = List.concat (List.map seq_of_test tests) in
6527 let cmds_tested = List.map List.hd seq in
6528 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6532 fun (name, _, _, _, _, _, _) ->
6533 if not (Hashtbl.mem hash name) then
6534 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6540 (* Generate the actual tests. Note that we generate the tests
6541 * in reverse order, deliberately, so that (in general) the
6542 * newest tests run first. This makes it quicker and easier to
6547 fun (name, _, _, flags, tests, _, _) ->
6548 mapi (generate_one_test name flags) tests
6549 ) (List.rev all_functions) in
6550 let test_names = List.concat test_names in
6551 let nr_tests = List.length test_names in
6554 int main (int argc, char *argv[])
6557 unsigned long int n_failed = 0;
6558 const char *filename;
6560 int nr_tests, test_num = 0;
6562 setbuf (stdout, NULL);
6564 no_test_warnings ();
6566 g = guestfs_create ();
6568 printf (\"guestfs_create FAILED\\n\");
6569 exit (EXIT_FAILURE);
6572 guestfs_set_error_handler (g, print_error, NULL);
6574 guestfs_set_path (g, \"../appliance\");
6576 filename = \"test1.img\";
6577 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6580 exit (EXIT_FAILURE);
6582 if (lseek (fd, %d, SEEK_SET) == -1) {
6586 exit (EXIT_FAILURE);
6588 if (write (fd, &c, 1) == -1) {
6592 exit (EXIT_FAILURE);
6594 if (close (fd) == -1) {
6597 exit (EXIT_FAILURE);
6599 if (guestfs_add_drive (g, filename) == -1) {
6600 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6601 exit (EXIT_FAILURE);
6604 filename = \"test2.img\";
6605 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6608 exit (EXIT_FAILURE);
6610 if (lseek (fd, %d, SEEK_SET) == -1) {
6614 exit (EXIT_FAILURE);
6616 if (write (fd, &c, 1) == -1) {
6620 exit (EXIT_FAILURE);
6622 if (close (fd) == -1) {
6625 exit (EXIT_FAILURE);
6627 if (guestfs_add_drive (g, filename) == -1) {
6628 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6629 exit (EXIT_FAILURE);
6632 filename = \"test3.img\";
6633 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6636 exit (EXIT_FAILURE);
6638 if (lseek (fd, %d, SEEK_SET) == -1) {
6642 exit (EXIT_FAILURE);
6644 if (write (fd, &c, 1) == -1) {
6648 exit (EXIT_FAILURE);
6650 if (close (fd) == -1) {
6653 exit (EXIT_FAILURE);
6655 if (guestfs_add_drive (g, filename) == -1) {
6656 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6657 exit (EXIT_FAILURE);
6660 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6661 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6662 exit (EXIT_FAILURE);
6665 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6668 if (guestfs_launch (g) == -1) {
6669 printf (\"guestfs_launch FAILED\\n\");
6670 exit (EXIT_FAILURE);
6673 /* Cancel previous alarm. */
6678 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6682 pr " test_num++;\n";
6683 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6684 pr " if (%s () == -1) {\n" test_name;
6685 pr " printf (\"%s FAILED\\n\");\n" test_name;
6686 pr " n_failed++;\n";
6691 pr " guestfs_close (g);\n";
6692 pr " unlink (\"test1.img\");\n";
6693 pr " unlink (\"test2.img\");\n";
6694 pr " unlink (\"test3.img\");\n";
6697 pr " if (n_failed > 0) {\n";
6698 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6699 pr " exit (EXIT_FAILURE);\n";
6703 pr " exit (EXIT_SUCCESS);\n";
6706 and generate_one_test name flags i (init, prereq, test) =
6707 let test_name = sprintf "test_%s_%d" name i in
6710 static int %s_skip (void)
6714 str = getenv (\"TEST_ONLY\");
6716 return strstr (str, \"%s\") == NULL;
6717 str = getenv (\"SKIP_%s\");
6718 if (str && STREQ (str, \"1\")) return 1;
6719 str = getenv (\"SKIP_TEST_%s\");
6720 if (str && STREQ (str, \"1\")) return 1;
6724 " test_name name (String.uppercase test_name) (String.uppercase name);
6727 | Disabled | Always -> ()
6728 | If code | Unless code ->
6729 pr "static int %s_prereq (void)\n" test_name;
6737 static int %s (void)
6740 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6744 " test_name test_name test_name;
6746 (* Optional functions should only be tested if the relevant
6747 * support is available in the daemon.
6753 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6755 pr " suppress_error = 1;\n";
6756 pr " r = guestfs_available (g, (char **) groups);\n";
6757 pr " suppress_error = 0;\n";
6758 pr " if (r == -1) {\n";
6759 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6768 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6770 pr " if (! %s_prereq ()) {\n" test_name;
6771 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6775 generate_one_test_body name i test_name init test;
6777 pr " if (%s_prereq ()) {\n" test_name;
6778 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6782 generate_one_test_body name i test_name init test;
6784 generate_one_test_body name i test_name init test
6792 and generate_one_test_body name i test_name init test =
6794 | InitNone (* XXX at some point, InitNone and InitEmpty became
6795 * folded together as the same thing. Really we should
6796 * make InitNone do nothing at all, but the tests may
6797 * need to be checked to make sure this is OK.
6800 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6801 List.iter (generate_test_command_call test_name)
6802 [["blockdev_setrw"; "/dev/sda"];
6806 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6807 List.iter (generate_test_command_call test_name)
6808 [["blockdev_setrw"; "/dev/sda"];
6811 ["part_disk"; "/dev/sda"; "mbr"]]
6813 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6814 List.iter (generate_test_command_call test_name)
6815 [["blockdev_setrw"; "/dev/sda"];
6818 ["part_disk"; "/dev/sda"; "mbr"];
6819 ["mkfs"; "ext2"; "/dev/sda1"];
6820 ["mount_options"; ""; "/dev/sda1"; "/"]]
6821 | InitBasicFSonLVM ->
6822 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6824 List.iter (generate_test_command_call test_name)
6825 [["blockdev_setrw"; "/dev/sda"];
6828 ["part_disk"; "/dev/sda"; "mbr"];
6829 ["pvcreate"; "/dev/sda1"];
6830 ["vgcreate"; "VG"; "/dev/sda1"];
6831 ["lvcreate"; "LV"; "VG"; "8"];
6832 ["mkfs"; "ext2"; "/dev/VG/LV"];
6833 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6835 pr " /* InitISOFS for %s */\n" test_name;
6836 List.iter (generate_test_command_call test_name)
6837 [["blockdev_setrw"; "/dev/sda"];
6840 ["mount_ro"; "/dev/sdd"; "/"]]
6843 let get_seq_last = function
6845 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6848 let seq = List.rev seq in
6849 List.rev (List.tl seq), List.hd seq
6854 pr " /* TestRun for %s (%d) */\n" name i;
6855 List.iter (generate_test_command_call test_name) seq
6856 | TestOutput (seq, expected) ->
6857 pr " /* TestOutput for %s (%d) */\n" name i;
6858 pr " const char *expected = \"%s\";\n" (c_quote expected);
6859 let seq, last = get_seq_last seq in
6861 pr " if (STRNEQ (r, expected)) {\n";
6862 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6866 List.iter (generate_test_command_call test_name) seq;
6867 generate_test_command_call ~test test_name last
6868 | TestOutputList (seq, expected) ->
6869 pr " /* TestOutputList for %s (%d) */\n" name i;
6870 let seq, last = get_seq_last seq in
6874 pr " if (!r[%d]) {\n" i;
6875 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6876 pr " print_strings (r);\n";
6880 pr " const char *expected = \"%s\";\n" (c_quote str);
6881 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6882 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6887 pr " if (r[%d] != NULL) {\n" (List.length expected);
6888 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6890 pr " print_strings (r);\n";
6894 List.iter (generate_test_command_call test_name) seq;
6895 generate_test_command_call ~test test_name last
6896 | TestOutputListOfDevices (seq, expected) ->
6897 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6898 let seq, last = get_seq_last seq in
6902 pr " if (!r[%d]) {\n" i;
6903 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6904 pr " print_strings (r);\n";
6908 pr " const char *expected = \"%s\";\n" (c_quote str);
6909 pr " r[%d][5] = 's';\n" i;
6910 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6911 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6916 pr " if (r[%d] != NULL) {\n" (List.length expected);
6917 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6919 pr " print_strings (r);\n";
6923 List.iter (generate_test_command_call test_name) seq;
6924 generate_test_command_call ~test test_name last
6925 | TestOutputInt (seq, expected) ->
6926 pr " /* TestOutputInt for %s (%d) */\n" name i;
6927 let seq, last = get_seq_last seq in
6929 pr " if (r != %d) {\n" expected;
6930 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6936 List.iter (generate_test_command_call test_name) seq;
6937 generate_test_command_call ~test test_name last
6938 | TestOutputIntOp (seq, op, expected) ->
6939 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6940 let seq, last = get_seq_last seq in
6942 pr " if (! (r %s %d)) {\n" op expected;
6943 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6944 test_name op expected;
6949 List.iter (generate_test_command_call test_name) seq;
6950 generate_test_command_call ~test test_name last
6951 | TestOutputTrue seq ->
6952 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6953 let seq, last = get_seq_last seq in
6956 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6961 List.iter (generate_test_command_call test_name) seq;
6962 generate_test_command_call ~test test_name last
6963 | TestOutputFalse seq ->
6964 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6965 let seq, last = get_seq_last seq in
6968 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6973 List.iter (generate_test_command_call test_name) seq;
6974 generate_test_command_call ~test test_name last
6975 | TestOutputLength (seq, expected) ->
6976 pr " /* TestOutputLength for %s (%d) */\n" name i;
6977 let seq, last = get_seq_last seq in
6980 pr " for (j = 0; j < %d; ++j)\n" expected;
6981 pr " if (r[j] == NULL) {\n";
6982 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
6984 pr " print_strings (r);\n";
6987 pr " if (r[j] != NULL) {\n";
6988 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
6990 pr " print_strings (r);\n";
6994 List.iter (generate_test_command_call test_name) seq;
6995 generate_test_command_call ~test test_name last
6996 | TestOutputBuffer (seq, expected) ->
6997 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
6998 pr " const char *expected = \"%s\";\n" (c_quote expected);
6999 let seq, last = get_seq_last seq in
7000 let len = String.length expected in
7002 pr " if (size != %d) {\n" len;
7003 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7006 pr " if (STRNEQLEN (r, expected, size)) {\n";
7007 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7011 List.iter (generate_test_command_call test_name) seq;
7012 generate_test_command_call ~test test_name last
7013 | TestOutputStruct (seq, checks) ->
7014 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7015 let seq, last = get_seq_last seq in
7019 | CompareWithInt (field, expected) ->
7020 pr " if (r->%s != %d) {\n" field expected;
7021 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7022 test_name field expected;
7023 pr " (int) r->%s);\n" field;
7026 | CompareWithIntOp (field, op, expected) ->
7027 pr " if (!(r->%s %s %d)) {\n" field op expected;
7028 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7029 test_name field op expected;
7030 pr " (int) r->%s);\n" field;
7033 | CompareWithString (field, expected) ->
7034 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7035 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7036 test_name field expected;
7037 pr " r->%s);\n" field;
7040 | CompareFieldsIntEq (field1, field2) ->
7041 pr " if (r->%s != r->%s) {\n" field1 field2;
7042 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7043 test_name field1 field2;
7044 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7047 | CompareFieldsStrEq (field1, field2) ->
7048 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7049 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7050 test_name field1 field2;
7051 pr " r->%s, r->%s);\n" field1 field2;
7056 List.iter (generate_test_command_call test_name) seq;
7057 generate_test_command_call ~test test_name last
7058 | TestLastFail seq ->
7059 pr " /* TestLastFail for %s (%d) */\n" name i;
7060 let seq, last = get_seq_last seq in
7061 List.iter (generate_test_command_call test_name) seq;
7062 generate_test_command_call test_name ~expect_error:true last
7064 (* Generate the code to run a command, leaving the result in 'r'.
7065 * If you expect to get an error then you should set expect_error:true.
7067 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7069 | [] -> assert false
7071 (* Look up the command to find out what args/ret it has. *)
7074 let _, style, _, _, _, _, _ =
7075 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7078 failwithf "%s: in test, command %s was not found" test_name name in
7080 if List.length (snd style) <> List.length args then
7081 failwithf "%s: in test, wrong number of args given to %s"
7088 | OptString n, "NULL" -> ()
7091 | Dev_or_Path n, arg
7093 | OptString n, arg ->
7094 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7098 | FileIn _, _ | FileOut _, _ -> ()
7099 | StringList n, "" | DeviceList n, "" ->
7100 pr " const char *const %s[1] = { NULL };\n" n
7101 | StringList n, arg | DeviceList n, arg ->
7102 let strs = string_split " " arg in
7105 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7107 pr " const char *const %s[] = {\n" n;
7109 fun i _ -> pr " %s_%d,\n" n i
7113 ) (List.combine (snd style) args);
7116 match fst style with
7117 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7118 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7119 | RConstString _ | RConstOptString _ ->
7120 pr " const char *r;\n"; "NULL"
7121 | RString _ -> pr " char *r;\n"; "NULL"
7122 | RStringList _ | RHashtable _ ->
7126 | RStruct (_, typ) ->
7127 pr " struct guestfs_%s *r;\n" typ; "NULL"
7128 | RStructList (_, typ) ->
7129 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7132 pr " size_t size;\n";
7135 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7136 pr " r = guestfs_%s (g" name;
7138 (* Generate the parameters. *)
7141 | OptString _, "NULL" -> pr ", NULL"
7143 | Device n, _ | Dev_or_Path n, _
7147 | FileIn _, arg | FileOut _, arg ->
7148 pr ", \"%s\"" (c_quote arg)
7149 | StringList n, _ | DeviceList n, _ ->
7150 pr ", (char **) %s" n
7153 try int_of_string arg
7154 with Failure "int_of_string" ->
7155 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7159 try Int64.of_string arg
7160 with Failure "int_of_string" ->
7161 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7164 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7165 ) (List.combine (snd style) args);
7167 (match fst style with
7168 | RBufferOut _ -> pr ", &size"
7174 if not expect_error then
7175 pr " if (r == %s)\n" error_code
7177 pr " if (r != %s)\n" error_code;
7180 (* Insert the test code. *)
7186 (match fst style with
7187 | RErr | RInt _ | RInt64 _ | RBool _
7188 | RConstString _ | RConstOptString _ -> ()
7189 | RString _ | RBufferOut _ -> pr " free (r);\n"
7190 | RStringList _ | RHashtable _ ->
7191 pr " for (i = 0; r[i] != NULL; ++i)\n";
7192 pr " free (r[i]);\n";
7194 | RStruct (_, typ) ->
7195 pr " guestfs_free_%s (r);\n" typ
7196 | RStructList (_, typ) ->
7197 pr " guestfs_free_%s_list (r);\n" typ
7203 let str = replace_str str "\r" "\\r" in
7204 let str = replace_str str "\n" "\\n" in
7205 let str = replace_str str "\t" "\\t" in
7206 let str = replace_str str "\000" "\\0" in
7209 (* Generate a lot of different functions for guestfish. *)
7210 and generate_fish_cmds () =
7211 generate_header CStyle GPLv2plus;
7215 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7217 let all_functions_sorted =
7219 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7220 ) all_functions_sorted in
7222 pr "#include <config.h>\n";
7224 pr "#include <stdio.h>\n";
7225 pr "#include <stdlib.h>\n";
7226 pr "#include <string.h>\n";
7227 pr "#include <inttypes.h>\n";
7229 pr "#include <guestfs.h>\n";
7230 pr "#include \"c-ctype.h\"\n";
7231 pr "#include \"full-write.h\"\n";
7232 pr "#include \"xstrtol.h\"\n";
7233 pr "#include \"fish.h\"\n";
7236 (* list_commands function, which implements guestfish -h *)
7237 pr "void list_commands (void)\n";
7239 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7240 pr " list_builtin_commands ();\n";
7242 fun (name, _, _, flags, _, shortdesc, _) ->
7243 let name = replace_char name '_' '-' in
7244 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7246 ) all_functions_sorted;
7247 pr " printf (\" %%s\\n\",";
7248 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7252 (* display_command function, which implements guestfish -h cmd *)
7253 pr "void display_command (const char *cmd)\n";
7256 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7257 let name2 = replace_char name '_' '-' in
7259 try find_map (function FishAlias n -> Some n | _ -> None) flags
7260 with Not_found -> name in
7261 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7263 match snd style with
7267 name2 (String.concat " " (List.map name_of_argt args)) in
7270 if List.mem ProtocolLimitWarning flags then
7271 ("\n\n" ^ protocol_limit_warning)
7274 (* For DangerWillRobinson commands, we should probably have
7275 * guestfish prompt before allowing you to use them (especially
7276 * in interactive mode). XXX
7280 if List.mem DangerWillRobinson flags then
7281 ("\n\n" ^ danger_will_robinson)
7286 match deprecation_notice flags with
7288 | Some txt -> "\n\n" ^ txt in
7290 let describe_alias =
7291 if name <> alias then
7292 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7296 pr "STRCASEEQ (cmd, \"%s\")" name;
7297 if name <> name2 then
7298 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7299 if name <> alias then
7300 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7302 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7304 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7305 "=head1 DESCRIPTION\n\n" ^
7306 longdesc ^ warnings ^ describe_alias);
7309 pr " display_builtin_command (cmd);\n";
7313 let emit_print_list_function typ =
7314 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7317 pr " unsigned int i;\n";
7319 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7320 pr " printf (\"[%%d] = {\\n\", i);\n";
7321 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7322 pr " printf (\"}\\n\");\n";
7328 (* print_* functions *)
7332 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7334 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7337 pr " unsigned int i;\n";
7343 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7345 pr " printf (\"%%s%s: \", indent);\n" name;
7346 pr " for (i = 0; i < 32; ++i)\n";
7347 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7348 pr " printf (\"\\n\");\n"
7350 pr " printf (\"%%s%s: \", indent);\n" name;
7351 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7352 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7353 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7355 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7356 pr " printf (\"\\n\");\n"
7357 | name, (FUInt64|FBytes) ->
7358 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7361 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7364 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7367 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7370 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7372 | name, FOptPercent ->
7373 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7374 typ name name typ name;
7375 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7381 (* Emit a print_TYPE_list function definition only if that function is used. *)
7384 | typ, (RStructListOnly | RStructAndList) ->
7385 (* generate the function for typ *)
7386 emit_print_list_function typ
7387 | typ, _ -> () (* empty *)
7388 ) (rstructs_used_by all_functions);
7390 (* Emit a print_TYPE function definition only if that function is used. *)
7393 | typ, (RStructOnly | RStructAndList) ->
7394 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7396 pr " print_%s_indent (%s, \"\");\n" typ typ;
7399 | typ, _ -> () (* empty *)
7400 ) (rstructs_used_by all_functions);
7402 (* run_<action> actions *)
7404 fun (name, style, _, flags, _, _, _) ->
7405 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7407 (match fst style with
7410 | RBool _ -> pr " int r;\n"
7411 | RInt64 _ -> pr " int64_t r;\n"
7412 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7413 | RString _ -> pr " char *r;\n"
7414 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7415 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7416 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7419 pr " size_t size;\n";
7425 | OptString n -> pr " const char *%s;\n" n
7429 | FileOut n -> pr " char *%s;\n" n
7430 | StringList n | DeviceList n -> pr " char **%s;\n" n
7431 | Bool n -> pr " int %s;\n" n
7432 | Int n -> pr " int %s;\n" n
7433 | Int64 n -> pr " int64_t %s;\n" n
7436 (* Check and convert parameters. *)
7437 let argc_expected = List.length (snd style) in
7438 pr " if (argc != %d) {\n" argc_expected;
7439 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7441 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7445 let parse_integer fn fntyp rtyp range name i =
7447 pr " strtol_error xerr;\n";
7448 pr " %s r;\n" fntyp;
7450 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7451 pr " if (xerr != LONGINT_OK) {\n";
7452 pr " fprintf (stderr,\n";
7453 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7454 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7459 | Some (min, max, comment) ->
7460 pr " /* %s */\n" comment;
7461 pr " if (r < %s || r > %s) {\n" min max;
7462 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7466 pr " /* The check above should ensure this assignment does not overflow. */\n";
7468 pr " %s = r;\n" name;
7477 pr " %s = argv[%d];\n" name i
7479 | Dev_or_Path name ->
7480 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7481 pr " if (%s == NULL) return -1;\n" name
7483 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7486 pr " %s = file_in (argv[%d]);\n" name i;
7487 pr " if (%s == NULL) return -1;\n" name
7489 pr " %s = file_out (argv[%d]);\n" name i;
7490 pr " if (%s == NULL) return -1;\n" name
7491 | StringList name | DeviceList name ->
7492 pr " %s = parse_string_list (argv[%d]);\n" name i;
7493 pr " if (%s == NULL) return -1;\n" name;
7495 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7498 let min = "(-(2LL<<30))"
7499 and max = "((2LL<<30)-1)"
7501 "The Int type in the generator is a signed 31 bit int." in
7502 Some (min, max, comment) in
7503 parse_integer "xstrtoll" "long long" "int" range name i
7505 parse_integer "xstrtoll" "long long" "int64_t" None name i
7508 (* Call C API function. *)
7510 try find_map (function FishAction n -> Some n | _ -> None) flags
7511 with Not_found -> sprintf "guestfs_%s" name in
7513 generate_c_call_args ~handle:"g" style;
7518 | Device name | String name
7519 | OptString name | Bool name
7520 | Int name | Int64 name -> ()
7521 | Pathname name | Dev_or_Path name | FileOut name ->
7522 pr " free (%s);\n" name
7524 pr " free_file_in (%s);\n" name
7525 | StringList name | DeviceList name ->
7526 pr " free_strings (%s);\n" name
7529 (* Any output flags? *)
7531 let flags = filter_map (
7532 function FishOutput flag -> Some flag | _ -> None
7538 failwithf "%s: more than one FishOutput flag is not allowed" name in
7540 (* Check return value for errors and display command results. *)
7541 (match fst style with
7542 | RErr -> pr " return r;\n"
7544 pr " if (r == -1) return -1;\n";
7545 (match fish_output with
7547 pr " printf (\"%%d\\n\", r);\n";
7548 | Some FishOutputOctal ->
7549 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7550 | Some FishOutputHexadecimal ->
7551 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7554 pr " if (r == -1) return -1;\n";
7555 (match fish_output with
7557 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7558 | Some FishOutputOctal ->
7559 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7560 | Some FishOutputHexadecimal ->
7561 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7564 pr " if (r == -1) return -1;\n";
7565 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7568 pr " if (r == NULL) return -1;\n";
7569 pr " printf (\"%%s\\n\", r);\n";
7571 | RConstOptString _ ->
7572 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7575 pr " if (r == NULL) return -1;\n";
7576 pr " printf (\"%%s\\n\", r);\n";
7580 pr " if (r == NULL) return -1;\n";
7581 pr " print_strings (r);\n";
7582 pr " free_strings (r);\n";
7584 | RStruct (_, typ) ->
7585 pr " if (r == NULL) return -1;\n";
7586 pr " print_%s (r);\n" typ;
7587 pr " guestfs_free_%s (r);\n" typ;
7589 | RStructList (_, typ) ->
7590 pr " if (r == NULL) return -1;\n";
7591 pr " print_%s_list (r);\n" typ;
7592 pr " guestfs_free_%s_list (r);\n" typ;
7595 pr " if (r == NULL) return -1;\n";
7596 pr " print_table (r);\n";
7597 pr " free_strings (r);\n";
7600 pr " if (r == NULL) return -1;\n";
7601 pr " if (full_write (1, r, size) != size) {\n";
7602 pr " perror (\"write\");\n";
7613 (* run_action function *)
7614 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7617 fun (name, _, _, flags, _, _, _) ->
7618 let name2 = replace_char name '_' '-' in
7620 try find_map (function FishAlias n -> Some n | _ -> None) flags
7621 with Not_found -> name in
7623 pr "STRCASEEQ (cmd, \"%s\")" name;
7624 if name <> name2 then
7625 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7626 if name <> alias then
7627 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7629 pr " return run_%s (cmd, argc, argv);\n" name;
7633 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7634 pr " if (command_num == 1)\n";
7635 pr " extended_help_message ();\n";
7642 (* Readline completion for guestfish. *)
7643 and generate_fish_completion () =
7644 generate_header CStyle GPLv2plus;
7648 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7658 #ifdef HAVE_LIBREADLINE
7659 #include <readline/readline.h>
7664 #ifdef HAVE_LIBREADLINE
7666 static const char *const commands[] = {
7667 BUILTIN_COMMANDS_FOR_COMPLETION,
7670 (* Get the commands, including the aliases. They don't need to be
7671 * sorted - the generator() function just does a dumb linear search.
7675 fun (name, _, _, flags, _, _, _) ->
7676 let name2 = replace_char name '_' '-' in
7678 try find_map (function FishAlias n -> Some n | _ -> None) flags
7679 with Not_found -> name in
7681 if name <> alias then [name2; alias] else [name2]
7683 let commands = List.flatten commands in
7685 List.iter (pr " \"%s\",\n") commands;
7691 generator (const char *text, int state)
7693 static int index, len;
7698 len = strlen (text);
7701 rl_attempted_completion_over = 1;
7703 while ((name = commands[index]) != NULL) {
7705 if (STRCASEEQLEN (name, text, len))
7706 return strdup (name);
7712 #endif /* HAVE_LIBREADLINE */
7714 #ifdef HAVE_RL_COMPLETION_MATCHES
7715 #define RL_COMPLETION_MATCHES rl_completion_matches
7717 #ifdef HAVE_COMPLETION_MATCHES
7718 #define RL_COMPLETION_MATCHES completion_matches
7720 #endif /* else just fail if we don't have either symbol */
7723 do_completion (const char *text, int start, int end)
7725 char **matches = NULL;
7727 #ifdef HAVE_LIBREADLINE
7728 rl_completion_append_character = ' ';
7731 matches = RL_COMPLETION_MATCHES (text, generator);
7732 else if (complete_dest_paths)
7733 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7740 (* Generate the POD documentation for guestfish. *)
7741 and generate_fish_actions_pod () =
7742 let all_functions_sorted =
7744 fun (_, _, _, flags, _, _, _) ->
7745 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7746 ) all_functions_sorted in
7748 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7751 fun (name, style, _, flags, _, _, longdesc) ->
7753 Str.global_substitute rex (
7756 try Str.matched_group 1 s
7758 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7759 "C<" ^ replace_char sub '_' '-' ^ ">"
7761 let name = replace_char name '_' '-' in
7763 try find_map (function FishAlias n -> Some n | _ -> None) flags
7764 with Not_found -> name in
7766 pr "=head2 %s" name;
7767 if name <> alias then
7774 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7775 | OptString n -> pr " %s" n
7776 | StringList n | DeviceList n -> pr " '%s ...'" n
7777 | Bool _ -> pr " true|false"
7778 | Int n -> pr " %s" n
7779 | Int64 n -> pr " %s" n
7780 | FileIn n | FileOut n -> pr " (%s|-)" n
7784 pr "%s\n\n" longdesc;
7786 if List.exists (function FileIn _ | FileOut _ -> true
7787 | _ -> false) (snd style) then
7788 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7790 if List.mem ProtocolLimitWarning flags then
7791 pr "%s\n\n" protocol_limit_warning;
7793 if List.mem DangerWillRobinson flags then
7794 pr "%s\n\n" danger_will_robinson;
7796 match deprecation_notice flags with
7798 | Some txt -> pr "%s\n\n" txt
7799 ) all_functions_sorted
7801 (* Generate a C function prototype. *)
7802 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7803 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7805 ?handle name style =
7806 if extern then pr "extern ";
7807 if static then pr "static ";
7808 (match fst style with
7810 | RInt _ -> pr "int "
7811 | RInt64 _ -> pr "int64_t "
7812 | RBool _ -> pr "int "
7813 | RConstString _ | RConstOptString _ -> pr "const char *"
7814 | RString _ | RBufferOut _ -> pr "char *"
7815 | RStringList _ | RHashtable _ -> pr "char **"
7816 | RStruct (_, typ) ->
7817 if not in_daemon then pr "struct guestfs_%s *" typ
7818 else pr "guestfs_int_%s *" typ
7819 | RStructList (_, typ) ->
7820 if not in_daemon then pr "struct guestfs_%s_list *" typ
7821 else pr "guestfs_int_%s_list *" typ
7823 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7824 pr "%s%s (" prefix name;
7825 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7828 let comma = ref false in
7831 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7835 if single_line then pr ", " else pr ",\n\t\t"
7842 | Device n | Dev_or_Path n
7846 pr "const char *%s" n
7847 | StringList n | DeviceList n ->
7849 pr "char *const *%s" n
7850 | Bool n -> next (); pr "int %s" n
7851 | Int n -> next (); pr "int %s" n
7852 | Int64 n -> next (); pr "int64_t %s" n
7855 if not in_daemon then (next (); pr "const char *%s" n)
7857 if is_RBufferOut then (next (); pr "size_t *size_r");
7860 if semicolon then pr ";";
7861 if newline then pr "\n"
7863 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7864 and generate_c_call_args ?handle ?(decl = false) style =
7866 let comma = ref false in
7868 if !comma then pr ", ";
7873 | Some handle -> pr "%s" handle; comma := true
7878 pr "%s" (name_of_argt arg)
7880 (* For RBufferOut calls, add implicit &size parameter. *)
7882 match fst style with
7890 (* Generate the OCaml bindings interface. *)
7891 and generate_ocaml_mli () =
7892 generate_header OCamlStyle LGPLv2plus;
7895 (** For API documentation you should refer to the C API
7896 in the guestfs(3) manual page. The OCaml API uses almost
7897 exactly the same calls. *)
7900 (** A [guestfs_h] handle. *)
7902 exception Error of string
7903 (** This exception is raised when there is an error. *)
7905 exception Handle_closed of string
7906 (** This exception is raised if you use a {!Guestfs.t} handle
7907 after calling {!close} on it. The string is the name of
7910 val create : unit -> t
7911 (** Create a {!Guestfs.t} handle. *)
7913 val close : t -> unit
7914 (** Close the {!Guestfs.t} handle and free up all resources used
7917 Handles are closed by the garbage collector when they become
7918 unreferenced, but callers can call this in order to provide
7919 predictable cleanup. *)
7922 generate_ocaml_structure_decls ();
7926 fun (name, style, _, _, _, shortdesc, _) ->
7927 generate_ocaml_prototype name style;
7928 pr "(** %s *)\n" shortdesc;
7930 ) all_functions_sorted
7932 (* Generate the OCaml bindings implementation. *)
7933 and generate_ocaml_ml () =
7934 generate_header OCamlStyle LGPLv2plus;
7939 exception Error of string
7940 exception Handle_closed of string
7942 external create : unit -> t = \"ocaml_guestfs_create\"
7943 external close : t -> unit = \"ocaml_guestfs_close\"
7945 (* Give the exceptions names, so they can be raised from the C code. *)
7947 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7948 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7952 generate_ocaml_structure_decls ();
7956 fun (name, style, _, _, _, shortdesc, _) ->
7957 generate_ocaml_prototype ~is_external:true name style;
7958 ) all_functions_sorted
7960 (* Generate the OCaml bindings C implementation. *)
7961 and generate_ocaml_c () =
7962 generate_header CStyle LGPLv2plus;
7969 #include <caml/config.h>
7970 #include <caml/alloc.h>
7971 #include <caml/callback.h>
7972 #include <caml/fail.h>
7973 #include <caml/memory.h>
7974 #include <caml/mlvalues.h>
7975 #include <caml/signals.h>
7977 #include <guestfs.h>
7979 #include \"guestfs_c.h\"
7981 /* Copy a hashtable of string pairs into an assoc-list. We return
7982 * the list in reverse order, but hashtables aren't supposed to be
7985 static CAMLprim value
7986 copy_table (char * const * argv)
7989 CAMLlocal5 (rv, pairv, kv, vv, cons);
7993 for (i = 0; argv[i] != NULL; i += 2) {
7994 kv = caml_copy_string (argv[i]);
7995 vv = caml_copy_string (argv[i+1]);
7996 pairv = caml_alloc (2, 0);
7997 Store_field (pairv, 0, kv);
7998 Store_field (pairv, 1, vv);
7999 cons = caml_alloc (2, 0);
8000 Store_field (cons, 1, rv);
8002 Store_field (cons, 0, pairv);
8010 (* Struct copy functions. *)
8012 let emit_ocaml_copy_list_function typ =
8013 pr "static CAMLprim value\n";
8014 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8016 pr " CAMLparam0 ();\n";
8017 pr " CAMLlocal2 (rv, v);\n";
8018 pr " unsigned int i;\n";
8020 pr " if (%ss->len == 0)\n" typ;
8021 pr " CAMLreturn (Atom (0));\n";
8023 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8024 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8025 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8026 pr " caml_modify (&Field (rv, i), v);\n";
8028 pr " CAMLreturn (rv);\n";
8036 let has_optpercent_col =
8037 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8039 pr "static CAMLprim value\n";
8040 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8042 pr " CAMLparam0 ();\n";
8043 if has_optpercent_col then
8044 pr " CAMLlocal3 (rv, v, v2);\n"
8046 pr " CAMLlocal2 (rv, v);\n";
8048 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8053 pr " v = caml_copy_string (%s->%s);\n" typ name
8055 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8056 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8059 pr " v = caml_alloc_string (32);\n";
8060 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8061 | name, (FBytes|FInt64|FUInt64) ->
8062 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8063 | name, (FInt32|FUInt32) ->
8064 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8065 | name, FOptPercent ->
8066 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8067 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8068 pr " v = caml_alloc (1, 0);\n";
8069 pr " Store_field (v, 0, v2);\n";
8070 pr " } else /* None */\n";
8071 pr " v = Val_int (0);\n";
8073 pr " v = Val_int (%s->%s);\n" typ name
8075 pr " Store_field (rv, %d, v);\n" i
8077 pr " CAMLreturn (rv);\n";
8082 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8085 | typ, (RStructListOnly | RStructAndList) ->
8086 (* generate the function for typ *)
8087 emit_ocaml_copy_list_function typ
8088 | typ, _ -> () (* empty *)
8089 ) (rstructs_used_by all_functions);
8093 fun (name, style, _, _, _, _, _) ->
8094 pr "/* Automatically generated wrapper for function\n";
8096 generate_ocaml_prototype name style;
8101 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8103 let needs_extra_vs =
8104 match fst style with RConstOptString _ -> true | _ -> false in
8106 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8107 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8108 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8111 pr "CAMLprim value\n";
8112 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8113 List.iter (pr ", value %s") (List.tl params);
8118 | [p1; p2; p3; p4; p5] ->
8119 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8120 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8121 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8122 pr " CAMLxparam%d (%s);\n"
8123 (List.length rest) (String.concat ", " rest)
8125 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8127 if not needs_extra_vs then
8128 pr " CAMLlocal1 (rv);\n"
8130 pr " CAMLlocal3 (rv, v, v2);\n";
8133 pr " guestfs_h *g = Guestfs_val (gv);\n";
8134 pr " if (g == NULL)\n";
8135 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8141 | Device n | Dev_or_Path n
8145 pr " const char *%s = String_val (%sv);\n" n n
8147 pr " const char *%s =\n" n;
8148 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8150 | StringList n | DeviceList n ->
8151 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8153 pr " int %s = Bool_val (%sv);\n" n n
8155 pr " int %s = Int_val (%sv);\n" n n
8157 pr " int64_t %s = Int64_val (%sv);\n" n n
8160 match fst style with
8161 | RErr -> pr " int r;\n"; "-1"
8162 | RInt _ -> pr " int r;\n"; "-1"
8163 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8164 | RBool _ -> pr " int r;\n"; "-1"
8165 | RConstString _ | RConstOptString _ ->
8166 pr " const char *r;\n"; "NULL"
8167 | RString _ -> pr " char *r;\n"; "NULL"
8172 | RStruct (_, typ) ->
8173 pr " struct guestfs_%s *r;\n" typ; "NULL"
8174 | RStructList (_, typ) ->
8175 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8182 pr " size_t size;\n";
8186 pr " caml_enter_blocking_section ();\n";
8187 pr " r = guestfs_%s " name;
8188 generate_c_call_args ~handle:"g" style;
8190 pr " caml_leave_blocking_section ();\n";
8194 | StringList n | DeviceList n ->
8195 pr " ocaml_guestfs_free_strings (%s);\n" n;
8196 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8197 | Bool _ | Int _ | Int64 _
8198 | FileIn _ | FileOut _ -> ()
8201 pr " if (r == %s)\n" error_code;
8202 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8205 (match fst style with
8206 | RErr -> pr " rv = Val_unit;\n"
8207 | RInt _ -> pr " rv = Val_int (r);\n"
8209 pr " rv = caml_copy_int64 (r);\n"
8210 | RBool _ -> pr " rv = Val_bool (r);\n"
8212 pr " rv = caml_copy_string (r);\n"
8213 | RConstOptString _ ->
8214 pr " if (r) { /* Some string */\n";
8215 pr " v = caml_alloc (1, 0);\n";
8216 pr " v2 = caml_copy_string (r);\n";
8217 pr " Store_field (v, 0, v2);\n";
8218 pr " } else /* None */\n";
8219 pr " v = Val_int (0);\n";
8221 pr " rv = caml_copy_string (r);\n";
8224 pr " rv = caml_copy_string_array ((const char **) r);\n";
8225 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8227 | RStruct (_, typ) ->
8228 pr " rv = copy_%s (r);\n" typ;
8229 pr " guestfs_free_%s (r);\n" typ;
8230 | RStructList (_, typ) ->
8231 pr " rv = copy_%s_list (r);\n" typ;
8232 pr " guestfs_free_%s_list (r);\n" typ;
8234 pr " rv = copy_table (r);\n";
8235 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8238 pr " rv = caml_alloc_string (size);\n";
8239 pr " memcpy (String_val (rv), r, size);\n";
8242 pr " CAMLreturn (rv);\n";
8246 if List.length params > 5 then (
8247 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8248 pr "CAMLprim value ";
8249 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8250 pr "CAMLprim value\n";
8251 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8253 pr " return ocaml_guestfs_%s (argv[0]" name;
8254 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8259 ) all_functions_sorted
8261 and generate_ocaml_structure_decls () =
8264 pr "type %s = {\n" typ;
8267 | name, FString -> pr " %s : string;\n" name
8268 | name, FBuffer -> pr " %s : string;\n" name
8269 | name, FUUID -> pr " %s : string;\n" name
8270 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8271 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8272 | name, FChar -> pr " %s : char;\n" name
8273 | name, FOptPercent -> pr " %s : float option;\n" name
8279 and generate_ocaml_prototype ?(is_external = false) name style =
8280 if is_external then pr "external " else pr "val ";
8281 pr "%s : t -> " name;
8284 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8285 | OptString _ -> pr "string option -> "
8286 | StringList _ | DeviceList _ -> pr "string array -> "
8287 | Bool _ -> pr "bool -> "
8288 | Int _ -> pr "int -> "
8289 | Int64 _ -> pr "int64 -> "
8291 (match fst style with
8292 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8293 | RInt _ -> pr "int"
8294 | RInt64 _ -> pr "int64"
8295 | RBool _ -> pr "bool"
8296 | RConstString _ -> pr "string"
8297 | RConstOptString _ -> pr "string option"
8298 | RString _ | RBufferOut _ -> pr "string"
8299 | RStringList _ -> pr "string array"
8300 | RStruct (_, typ) -> pr "%s" typ
8301 | RStructList (_, typ) -> pr "%s array" typ
8302 | RHashtable _ -> pr "(string * string) list"
8304 if is_external then (
8306 if List.length (snd style) + 1 > 5 then
8307 pr "\"ocaml_guestfs_%s_byte\" " name;
8308 pr "\"ocaml_guestfs_%s\"" name
8312 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8313 and generate_perl_xs () =
8314 generate_header CStyle LGPLv2plus;
8317 #include \"EXTERN.h\"
8321 #include <guestfs.h>
8324 #define PRId64 \"lld\"
8328 my_newSVll(long long val) {
8329 #ifdef USE_64_BIT_ALL
8330 return newSViv(val);
8334 len = snprintf(buf, 100, \"%%\" PRId64, val);
8335 return newSVpv(buf, len);
8340 #define PRIu64 \"llu\"
8344 my_newSVull(unsigned long long val) {
8345 #ifdef USE_64_BIT_ALL
8346 return newSVuv(val);
8350 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8351 return newSVpv(buf, len);
8355 /* http://www.perlmonks.org/?node_id=680842 */
8357 XS_unpack_charPtrPtr (SV *arg) {
8362 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8363 croak (\"array reference expected\");
8365 av = (AV *)SvRV (arg);
8366 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8368 croak (\"malloc failed\");
8370 for (i = 0; i <= av_len (av); i++) {
8371 SV **elem = av_fetch (av, i, 0);
8373 if (!elem || !*elem)
8374 croak (\"missing element in list\");
8376 ret[i] = SvPV_nolen (*elem);
8384 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8391 RETVAL = guestfs_create ();
8393 croak (\"could not create guestfs handle\");
8394 guestfs_set_error_handler (RETVAL, NULL, NULL);
8407 fun (name, style, _, _, _, _, _) ->
8408 (match fst style with
8409 | RErr -> pr "void\n"
8410 | RInt _ -> pr "SV *\n"
8411 | RInt64 _ -> pr "SV *\n"
8412 | RBool _ -> pr "SV *\n"
8413 | RConstString _ -> pr "SV *\n"
8414 | RConstOptString _ -> pr "SV *\n"
8415 | RString _ -> pr "SV *\n"
8416 | RBufferOut _ -> pr "SV *\n"
8418 | RStruct _ | RStructList _
8420 pr "void\n" (* all lists returned implictly on the stack *)
8422 (* Call and arguments. *)
8424 generate_c_call_args ~handle:"g" ~decl:true style;
8426 pr " guestfs_h *g;\n";
8430 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8433 (* http://www.perlmonks.org/?node_id=554277
8434 * Note that the implicit handle argument means we have
8435 * to add 1 to the ST(x) operator.
8437 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8438 | StringList n | DeviceList n -> pr " char **%s;\n" n
8439 | Bool n -> pr " int %s;\n" n
8440 | Int n -> pr " int %s;\n" n
8441 | Int64 n -> pr " int64_t %s;\n" n
8444 let do_cleanups () =
8447 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8448 | Bool _ | Int _ | Int64 _
8449 | FileIn _ | FileOut _ -> ()
8450 | StringList n | DeviceList n -> pr " free (%s);\n" n
8455 (match fst style with
8460 pr " r = guestfs_%s " name;
8461 generate_c_call_args ~handle:"g" style;
8464 pr " if (r == -1)\n";
8465 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8471 pr " %s = guestfs_%s " n name;
8472 generate_c_call_args ~handle:"g" style;
8475 pr " if (%s == -1)\n" n;
8476 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8477 pr " RETVAL = newSViv (%s);\n" n;
8482 pr " int64_t %s;\n" n;
8484 pr " %s = guestfs_%s " n name;
8485 generate_c_call_args ~handle:"g" style;
8488 pr " if (%s == -1)\n" n;
8489 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8490 pr " RETVAL = my_newSVll (%s);\n" n;
8495 pr " const char *%s;\n" n;
8497 pr " %s = guestfs_%s " n name;
8498 generate_c_call_args ~handle:"g" style;
8501 pr " if (%s == NULL)\n" n;
8502 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8503 pr " RETVAL = newSVpv (%s, 0);\n" n;
8506 | RConstOptString n ->
8508 pr " const char *%s;\n" n;
8510 pr " %s = guestfs_%s " n name;
8511 generate_c_call_args ~handle:"g" style;
8514 pr " if (%s == NULL)\n" n;
8515 pr " RETVAL = &PL_sv_undef;\n";
8517 pr " RETVAL = newSVpv (%s, 0);\n" n;
8522 pr " char *%s;\n" n;
8524 pr " %s = guestfs_%s " n name;
8525 generate_c_call_args ~handle:"g" style;
8528 pr " if (%s == NULL)\n" n;
8529 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8530 pr " RETVAL = newSVpv (%s, 0);\n" n;
8531 pr " free (%s);\n" n;
8534 | RStringList n | RHashtable n ->
8536 pr " char **%s;\n" n;
8539 pr " %s = guestfs_%s " n name;
8540 generate_c_call_args ~handle:"g" style;
8543 pr " if (%s == NULL)\n" n;
8544 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8545 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8546 pr " EXTEND (SP, n);\n";
8547 pr " for (i = 0; i < n; ++i) {\n";
8548 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8549 pr " free (%s[i]);\n" n;
8551 pr " free (%s);\n" n;
8552 | RStruct (n, typ) ->
8553 let cols = cols_of_struct typ in
8554 generate_perl_struct_code typ cols name style n do_cleanups
8555 | RStructList (n, typ) ->
8556 let cols = cols_of_struct typ in
8557 generate_perl_struct_list_code typ cols name style n do_cleanups
8560 pr " char *%s;\n" n;
8561 pr " size_t size;\n";
8563 pr " %s = guestfs_%s " n name;
8564 generate_c_call_args ~handle:"g" style;
8567 pr " if (%s == NULL)\n" n;
8568 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8569 pr " RETVAL = newSVpvn (%s, size);\n" n;
8570 pr " free (%s);\n" n;
8578 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8580 pr " struct guestfs_%s_list *%s;\n" typ n;
8584 pr " %s = guestfs_%s " n name;
8585 generate_c_call_args ~handle:"g" style;
8588 pr " if (%s == NULL)\n" n;
8589 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8590 pr " EXTEND (SP, %s->len);\n" n;
8591 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8592 pr " hv = newHV ();\n";
8596 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8597 name (String.length name) n name
8599 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8600 name (String.length name) n name
8602 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8603 name (String.length name) n name n name
8604 | name, (FBytes|FUInt64) ->
8605 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8606 name (String.length name) n name
8608 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8609 name (String.length name) n name
8610 | name, (FInt32|FUInt32) ->
8611 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8612 name (String.length name) n name
8614 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8615 name (String.length name) n name
8616 | name, FOptPercent ->
8617 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8618 name (String.length name) n name
8620 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8622 pr " guestfs_free_%s_list (%s);\n" typ n
8624 and generate_perl_struct_code typ cols name style n do_cleanups =
8626 pr " struct guestfs_%s *%s;\n" typ n;
8628 pr " %s = guestfs_%s " n name;
8629 generate_c_call_args ~handle:"g" style;
8632 pr " if (%s == NULL)\n" n;
8633 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8634 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8636 fun ((name, _) as col) ->
8637 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8641 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8644 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8647 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8649 | name, (FBytes|FUInt64) ->
8650 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8653 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8655 | name, (FInt32|FUInt32) ->
8656 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8659 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8661 | name, FOptPercent ->
8662 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8665 pr " free (%s);\n" n
8667 (* Generate Sys/Guestfs.pm. *)
8668 and generate_perl_pm () =
8669 generate_header HashStyle LGPLv2plus;
8676 Sys::Guestfs - Perl bindings for libguestfs
8682 my $h = Sys::Guestfs->new ();
8683 $h->add_drive ('guest.img');
8685 $h->mount ('/dev/sda1', '/');
8686 $h->touch ('/hello');
8691 The C<Sys::Guestfs> module provides a Perl XS binding to the
8692 libguestfs API for examining and modifying virtual machine
8695 Amongst the things this is good for: making batch configuration
8696 changes to guests, getting disk used/free statistics (see also:
8697 virt-df), migrating between virtualization systems (see also:
8698 virt-p2v), performing partial backups, performing partial guest
8699 clones, cloning guests and changing registry/UUID/hostname info, and
8702 Libguestfs uses Linux kernel and qemu code, and can access any type of
8703 guest filesystem that Linux and qemu can, including but not limited
8704 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8705 schemes, qcow, qcow2, vmdk.
8707 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8708 LVs, what filesystem is in each LV, etc.). It can also run commands
8709 in the context of the guest. Also you can access filesystems over
8712 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8713 functions for using libguestfs from Perl, including integration
8718 All errors turn into calls to C<croak> (see L<Carp(3)>).
8726 package Sys::Guestfs;
8732 XSLoader::load ('Sys::Guestfs');
8734 =item $h = Sys::Guestfs->new ();
8736 Create a new guestfs handle.
8742 my $class = ref ($proto) || $proto;
8744 my $self = Sys::Guestfs::_create ();
8745 bless $self, $class;
8751 (* Actions. We only need to print documentation for these as
8752 * they are pulled in from the XS code automatically.
8755 fun (name, style, _, flags, _, _, longdesc) ->
8756 if not (List.mem NotInDocs flags) then (
8757 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8759 generate_perl_prototype name style;
8761 pr "%s\n\n" longdesc;
8762 if List.mem ProtocolLimitWarning flags then
8763 pr "%s\n\n" protocol_limit_warning;
8764 if List.mem DangerWillRobinson flags then
8765 pr "%s\n\n" danger_will_robinson;
8766 match deprecation_notice flags with
8768 | Some txt -> pr "%s\n\n" txt
8770 ) all_functions_sorted;
8782 Copyright (C) %s Red Hat Inc.
8786 Please see the file COPYING.LIB for the full license.
8792 L<http://libguestfs.org>,
8793 L<Sys::Guestfs::Lib(3)>.
8798 and generate_perl_prototype name style =
8799 (match fst style with
8807 | RBufferOut n -> pr "$%s = " n
8809 | RHashtable n -> pr "%%%s = " n
8811 | RStructList (n,_) -> pr "@%s = " n
8814 let comma = ref false in
8817 if !comma then pr ", ";
8820 | Pathname n | Device n | Dev_or_Path n | String n
8821 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8823 | StringList n | DeviceList n ->
8828 (* Generate Python C module. *)
8829 and generate_python_c () =
8830 generate_header CStyle LGPLv2plus;
8839 #include \"guestfs.h\"
8847 get_handle (PyObject *obj)
8850 assert (obj != Py_None);
8851 return ((Pyguestfs_Object *) obj)->g;
8855 put_handle (guestfs_h *g)
8859 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8862 /* This list should be freed (but not the strings) after use. */
8864 get_string_list (PyObject *obj)
8871 if (!PyList_Check (obj)) {
8872 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8876 len = PyList_Size (obj);
8877 r = malloc (sizeof (char *) * (len+1));
8879 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8883 for (i = 0; i < len; ++i)
8884 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8891 put_string_list (char * const * const argv)
8896 for (argc = 0; argv[argc] != NULL; ++argc)
8899 list = PyList_New (argc);
8900 for (i = 0; i < argc; ++i)
8901 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8907 put_table (char * const * const argv)
8909 PyObject *list, *item;
8912 for (argc = 0; argv[argc] != NULL; ++argc)
8915 list = PyList_New (argc >> 1);
8916 for (i = 0; i < argc; i += 2) {
8917 item = PyTuple_New (2);
8918 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8919 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8920 PyList_SetItem (list, i >> 1, item);
8927 free_strings (char **argv)
8931 for (argc = 0; argv[argc] != NULL; ++argc)
8937 py_guestfs_create (PyObject *self, PyObject *args)
8941 g = guestfs_create ();
8943 PyErr_SetString (PyExc_RuntimeError,
8944 \"guestfs.create: failed to allocate handle\");
8947 guestfs_set_error_handler (g, NULL, NULL);
8948 return put_handle (g);
8952 py_guestfs_close (PyObject *self, PyObject *args)
8957 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8959 g = get_handle (py_g);
8963 Py_INCREF (Py_None);
8969 let emit_put_list_function typ =
8970 pr "static PyObject *\n";
8971 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8973 pr " PyObject *list;\n";
8976 pr " list = PyList_New (%ss->len);\n" typ;
8977 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8978 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8979 pr " return list;\n";
8984 (* Structures, turned into Python dictionaries. *)
8987 pr "static PyObject *\n";
8988 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8990 pr " PyObject *dict;\n";
8992 pr " dict = PyDict_New ();\n";
8996 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
8997 pr " PyString_FromString (%s->%s));\n"
9000 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9001 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9004 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9005 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9007 | name, (FBytes|FUInt64) ->
9008 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9009 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9012 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9013 pr " PyLong_FromLongLong (%s->%s));\n"
9016 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9017 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9020 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9021 pr " PyLong_FromLong (%s->%s));\n"
9023 | name, FOptPercent ->
9024 pr " if (%s->%s >= 0)\n" typ name;
9025 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9026 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9029 pr " Py_INCREF (Py_None);\n";
9030 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9033 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9034 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9036 pr " return dict;\n";
9042 (* Emit a put_TYPE_list function definition only if that function is used. *)
9045 | typ, (RStructListOnly | RStructAndList) ->
9046 (* generate the function for typ *)
9047 emit_put_list_function typ
9048 | typ, _ -> () (* empty *)
9049 ) (rstructs_used_by all_functions);
9051 (* Python wrapper functions. *)
9053 fun (name, style, _, _, _, _, _) ->
9054 pr "static PyObject *\n";
9055 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9058 pr " PyObject *py_g;\n";
9059 pr " guestfs_h *g;\n";
9060 pr " PyObject *py_r;\n";
9063 match fst style with
9064 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9065 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9066 | RConstString _ | RConstOptString _ ->
9067 pr " const char *r;\n"; "NULL"
9068 | RString _ -> pr " char *r;\n"; "NULL"
9069 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9070 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9071 | RStructList (_, typ) ->
9072 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9075 pr " size_t size;\n";
9080 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9081 pr " const char *%s;\n" n
9082 | OptString n -> pr " const char *%s;\n" n
9083 | StringList n | DeviceList n ->
9084 pr " PyObject *py_%s;\n" n;
9085 pr " char **%s;\n" n
9086 | Bool n -> pr " int %s;\n" n
9087 | Int n -> pr " int %s;\n" n
9088 | Int64 n -> pr " long long %s;\n" n
9093 (* Convert the parameters. *)
9094 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9097 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9098 | OptString _ -> pr "z"
9099 | StringList _ | DeviceList _ -> pr "O"
9100 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9102 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9103 * emulate C's int/long/long long in Python?
9106 pr ":guestfs_%s\",\n" name;
9110 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9111 | OptString n -> pr ", &%s" n
9112 | StringList n | DeviceList n -> pr ", &py_%s" n
9113 | Bool n -> pr ", &%s" n
9114 | Int n -> pr ", &%s" n
9115 | Int64 n -> pr ", &%s" n
9119 pr " return NULL;\n";
9121 pr " g = get_handle (py_g);\n";
9124 | Pathname _ | Device _ | Dev_or_Path _ | String _
9125 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9126 | StringList n | DeviceList n ->
9127 pr " %s = get_string_list (py_%s);\n" n n;
9128 pr " if (!%s) return NULL;\n" n
9133 pr " r = guestfs_%s " name;
9134 generate_c_call_args ~handle:"g" style;
9139 | Pathname _ | Device _ | Dev_or_Path _ | String _
9140 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9141 | StringList n | DeviceList n ->
9142 pr " free (%s);\n" n
9145 pr " if (r == %s) {\n" error_code;
9146 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9147 pr " return NULL;\n";
9151 (match fst style with
9153 pr " Py_INCREF (Py_None);\n";
9154 pr " py_r = Py_None;\n"
9156 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9157 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9158 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9159 | RConstOptString _ ->
9161 pr " py_r = PyString_FromString (r);\n";
9163 pr " Py_INCREF (Py_None);\n";
9164 pr " py_r = Py_None;\n";
9167 pr " py_r = PyString_FromString (r);\n";
9170 pr " py_r = put_string_list (r);\n";
9171 pr " free_strings (r);\n"
9172 | RStruct (_, typ) ->
9173 pr " py_r = put_%s (r);\n" typ;
9174 pr " guestfs_free_%s (r);\n" typ
9175 | RStructList (_, typ) ->
9176 pr " py_r = put_%s_list (r);\n" typ;
9177 pr " guestfs_free_%s_list (r);\n" typ
9179 pr " py_r = put_table (r);\n";
9180 pr " free_strings (r);\n"
9182 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9186 pr " return py_r;\n";
9191 (* Table of functions. *)
9192 pr "static PyMethodDef methods[] = {\n";
9193 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9194 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9196 fun (name, _, _, _, _, _, _) ->
9197 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9200 pr " { NULL, NULL, 0, NULL }\n";
9204 (* Init function. *)
9207 initlibguestfsmod (void)
9209 static int initialized = 0;
9211 if (initialized) return;
9212 Py_InitModule ((char *) \"libguestfsmod\", methods);
9217 (* Generate Python module. *)
9218 and generate_python_py () =
9219 generate_header HashStyle LGPLv2plus;
9222 u\"\"\"Python bindings for libguestfs
9225 g = guestfs.GuestFS ()
9226 g.add_drive (\"guest.img\")
9228 parts = g.list_partitions ()
9230 The guestfs module provides a Python binding to the libguestfs API
9231 for examining and modifying virtual machine disk images.
9233 Amongst the things this is good for: making batch configuration
9234 changes to guests, getting disk used/free statistics (see also:
9235 virt-df), migrating between virtualization systems (see also:
9236 virt-p2v), performing partial backups, performing partial guest
9237 clones, cloning guests and changing registry/UUID/hostname info, and
9240 Libguestfs uses Linux kernel and qemu code, and can access any type of
9241 guest filesystem that Linux and qemu can, including but not limited
9242 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9243 schemes, qcow, qcow2, vmdk.
9245 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9246 LVs, what filesystem is in each LV, etc.). It can also run commands
9247 in the context of the guest. Also you can access filesystems over
9250 Errors which happen while using the API are turned into Python
9251 RuntimeError exceptions.
9253 To create a guestfs handle you usually have to perform the following
9256 # Create the handle, call add_drive at least once, and possibly
9257 # several times if the guest has multiple block devices:
9258 g = guestfs.GuestFS ()
9259 g.add_drive (\"guest.img\")
9261 # Launch the qemu subprocess and wait for it to become ready:
9264 # Now you can issue commands, for example:
9269 import libguestfsmod
9272 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9274 def __init__ (self):
9275 \"\"\"Create a new libguestfs handle.\"\"\"
9276 self._o = libguestfsmod.create ()
9279 libguestfsmod.close (self._o)
9284 fun (name, style, _, flags, _, _, longdesc) ->
9286 generate_py_call_args ~handle:"self" (snd style);
9289 if not (List.mem NotInDocs flags) then (
9290 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9292 match fst style with
9293 | RErr | RInt _ | RInt64 _ | RBool _
9294 | RConstOptString _ | RConstString _
9295 | RString _ | RBufferOut _ -> doc
9297 doc ^ "\n\nThis function returns a list of strings."
9298 | RStruct (_, typ) ->
9299 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9300 | RStructList (_, typ) ->
9301 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9303 doc ^ "\n\nThis function returns a dictionary." in
9305 if List.mem ProtocolLimitWarning flags then
9306 doc ^ "\n\n" ^ protocol_limit_warning
9309 if List.mem DangerWillRobinson flags then
9310 doc ^ "\n\n" ^ danger_will_robinson
9313 match deprecation_notice flags with
9315 | Some txt -> doc ^ "\n\n" ^ txt in
9316 let doc = pod2text ~width:60 name doc in
9317 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9318 let doc = String.concat "\n " doc in
9319 pr " u\"\"\"%s\"\"\"\n" doc;
9321 pr " return libguestfsmod.%s " name;
9322 generate_py_call_args ~handle:"self._o" (snd style);
9327 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9328 and generate_py_call_args ~handle args =
9330 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9333 (* Useful if you need the longdesc POD text as plain text. Returns a
9336 * Because this is very slow (the slowest part of autogeneration),
9337 * we memoize the results.
9339 and pod2text ~width name longdesc =
9340 let key = width, name, longdesc in
9341 try Hashtbl.find pod2text_memo key
9343 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9344 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9346 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9347 let chan = open_process_in cmd in
9348 let lines = ref [] in
9350 let line = input_line chan in
9351 if i = 1 then (* discard the first line of output *)
9354 let line = triml line in
9355 lines := line :: !lines;
9358 let lines = try loop 1 with End_of_file -> List.rev !lines in
9360 (match close_process_in chan with
9363 failwithf "pod2text: process exited with non-zero status (%d)" i
9364 | WSIGNALED i | WSTOPPED i ->
9365 failwithf "pod2text: process signalled or stopped by signal %d" i
9367 Hashtbl.add pod2text_memo key lines;
9368 pod2text_memo_updated ();
9371 (* Generate ruby bindings. *)
9372 and generate_ruby_c () =
9373 generate_header CStyle LGPLv2plus;
9381 #include \"guestfs.h\"
9383 #include \"extconf.h\"
9385 /* For Ruby < 1.9 */
9387 #define RARRAY_LEN(r) (RARRAY((r))->len)
9390 static VALUE m_guestfs; /* guestfs module */
9391 static VALUE c_guestfs; /* guestfs_h handle */
9392 static VALUE e_Error; /* used for all errors */
9394 static void ruby_guestfs_free (void *p)
9397 guestfs_close ((guestfs_h *) p);
9400 static VALUE ruby_guestfs_create (VALUE m)
9404 g = guestfs_create ();
9406 rb_raise (e_Error, \"failed to create guestfs handle\");
9408 /* Don't print error messages to stderr by default. */
9409 guestfs_set_error_handler (g, NULL, NULL);
9411 /* Wrap it, and make sure the close function is called when the
9414 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9417 static VALUE ruby_guestfs_close (VALUE gv)
9420 Data_Get_Struct (gv, guestfs_h, g);
9422 ruby_guestfs_free (g);
9423 DATA_PTR (gv) = NULL;
9431 fun (name, style, _, _, _, _, _) ->
9432 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9433 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9436 pr " guestfs_h *g;\n";
9437 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9439 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9445 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9446 pr " Check_Type (%sv, T_STRING);\n" n;
9447 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9449 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9450 pr " \"%s\", \"%s\");\n" n name
9452 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9453 | StringList n | DeviceList n ->
9454 pr " char **%s;\n" n;
9455 pr " Check_Type (%sv, T_ARRAY);\n" n;
9457 pr " int i, len;\n";
9458 pr " len = RARRAY_LEN (%sv);\n" n;
9459 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9461 pr " for (i = 0; i < len; ++i) {\n";
9462 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9463 pr " %s[i] = StringValueCStr (v);\n" n;
9465 pr " %s[len] = NULL;\n" n;
9468 pr " int %s = RTEST (%sv);\n" n n
9470 pr " int %s = NUM2INT (%sv);\n" n n
9472 pr " long long %s = NUM2LL (%sv);\n" n n
9477 match fst style with
9478 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9479 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9480 | RConstString _ | RConstOptString _ ->
9481 pr " const char *r;\n"; "NULL"
9482 | RString _ -> pr " char *r;\n"; "NULL"
9483 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9484 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9485 | RStructList (_, typ) ->
9486 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9489 pr " size_t size;\n";
9493 pr " r = guestfs_%s " name;
9494 generate_c_call_args ~handle:"g" style;
9499 | Pathname _ | Device _ | Dev_or_Path _ | String _
9500 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9501 | StringList n | DeviceList n ->
9502 pr " free (%s);\n" n
9505 pr " if (r == %s)\n" error_code;
9506 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9509 (match fst style with
9511 pr " return Qnil;\n"
9512 | RInt _ | RBool _ ->
9513 pr " return INT2NUM (r);\n"
9515 pr " return ULL2NUM (r);\n"
9517 pr " return rb_str_new2 (r);\n";
9518 | RConstOptString _ ->
9520 pr " return rb_str_new2 (r);\n";
9522 pr " return Qnil;\n";
9524 pr " VALUE rv = rb_str_new2 (r);\n";
9528 pr " int i, len = 0;\n";
9529 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9530 pr " VALUE rv = rb_ary_new2 (len);\n";
9531 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9532 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9533 pr " free (r[i]);\n";
9537 | RStruct (_, typ) ->
9538 let cols = cols_of_struct typ in
9539 generate_ruby_struct_code typ cols
9540 | RStructList (_, typ) ->
9541 let cols = cols_of_struct typ in
9542 generate_ruby_struct_list_code typ cols
9544 pr " VALUE rv = rb_hash_new ();\n";
9546 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9547 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9548 pr " free (r[i]);\n";
9549 pr " free (r[i+1]);\n";
9554 pr " VALUE rv = rb_str_new (r, size);\n";
9564 /* Initialize the module. */
9565 void Init__guestfs ()
9567 m_guestfs = rb_define_module (\"Guestfs\");
9568 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9569 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9571 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9572 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9575 (* Define the rest of the methods. *)
9577 fun (name, style, _, _, _, _, _) ->
9578 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9579 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9584 (* Ruby code to return a struct. *)
9585 and generate_ruby_struct_code typ cols =
9586 pr " VALUE rv = rb_hash_new ();\n";
9590 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9592 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9594 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9595 | name, (FBytes|FUInt64) ->
9596 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9598 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9600 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9602 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9603 | name, FOptPercent ->
9604 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9605 | name, FChar -> (* XXX wrong? *)
9606 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9608 pr " guestfs_free_%s (r);\n" typ;
9611 (* Ruby code to return a struct list. *)
9612 and generate_ruby_struct_list_code typ cols =
9613 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9615 pr " for (i = 0; i < r->len; ++i) {\n";
9616 pr " VALUE hv = rb_hash_new ();\n";
9620 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9622 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
9624 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9625 | name, (FBytes|FUInt64) ->
9626 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9628 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9630 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9632 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9633 | name, FOptPercent ->
9634 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9635 | name, FChar -> (* XXX wrong? *)
9636 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9638 pr " rb_ary_push (rv, hv);\n";
9640 pr " guestfs_free_%s_list (r);\n" typ;
9643 (* Generate Java bindings GuestFS.java file. *)
9644 and generate_java_java () =
9645 generate_header CStyle LGPLv2plus;
9648 package com.redhat.et.libguestfs;
9650 import java.util.HashMap;
9651 import com.redhat.et.libguestfs.LibGuestFSException;
9652 import com.redhat.et.libguestfs.PV;
9653 import com.redhat.et.libguestfs.VG;
9654 import com.redhat.et.libguestfs.LV;
9655 import com.redhat.et.libguestfs.Stat;
9656 import com.redhat.et.libguestfs.StatVFS;
9657 import com.redhat.et.libguestfs.IntBool;
9658 import com.redhat.et.libguestfs.Dirent;
9661 * The GuestFS object is a libguestfs handle.
9665 public class GuestFS {
9666 // Load the native code.
9668 System.loadLibrary (\"guestfs_jni\");
9672 * The native guestfs_h pointer.
9677 * Create a libguestfs handle.
9679 * @throws LibGuestFSException
9681 public GuestFS () throws LibGuestFSException
9685 private native long _create () throws LibGuestFSException;
9688 * Close a libguestfs handle.
9690 * You can also leave handles to be collected by the garbage
9691 * collector, but this method ensures that the resources used
9692 * by the handle are freed up immediately. If you call any
9693 * other methods after closing the handle, you will get an
9696 * @throws LibGuestFSException
9698 public void close () throws LibGuestFSException
9704 private native void _close (long g) throws LibGuestFSException;
9706 public void finalize () throws LibGuestFSException
9714 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9715 if not (List.mem NotInDocs flags); then (
9716 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9718 if List.mem ProtocolLimitWarning flags then
9719 doc ^ "\n\n" ^ protocol_limit_warning
9722 if List.mem DangerWillRobinson flags then
9723 doc ^ "\n\n" ^ danger_will_robinson
9726 match deprecation_notice flags with
9728 | Some txt -> doc ^ "\n\n" ^ txt in
9729 let doc = pod2text ~width:60 name doc in
9730 let doc = List.map ( (* RHBZ#501883 *)
9733 | nonempty -> nonempty
9735 let doc = String.concat "\n * " doc in
9738 pr " * %s\n" shortdesc;
9741 pr " * @throws LibGuestFSException\n";
9745 generate_java_prototype ~public:true ~semicolon:false name style;
9748 pr " if (g == 0)\n";
9749 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9752 if fst style <> RErr then pr "return ";
9754 generate_java_call_args ~handle:"g" (snd style);
9758 generate_java_prototype ~privat:true ~native:true name style;
9765 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9766 and generate_java_call_args ~handle args =
9768 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9771 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9772 ?(semicolon=true) name style =
9773 if privat then pr "private ";
9774 if public then pr "public ";
9775 if native then pr "native ";
9778 (match fst style with
9779 | RErr -> pr "void ";
9780 | RInt _ -> pr "int ";
9781 | RInt64 _ -> pr "long ";
9782 | RBool _ -> pr "boolean ";
9783 | RConstString _ | RConstOptString _ | RString _
9784 | RBufferOut _ -> pr "String ";
9785 | RStringList _ -> pr "String[] ";
9786 | RStruct (_, typ) ->
9787 let name = java_name_of_struct typ in
9789 | RStructList (_, typ) ->
9790 let name = java_name_of_struct typ in
9792 | RHashtable _ -> pr "HashMap<String,String> ";
9795 if native then pr "_%s " name else pr "%s " name;
9797 let needs_comma = ref false in
9806 if !needs_comma then pr ", ";
9807 needs_comma := true;
9811 | Device n | Dev_or_Path n
9817 | StringList n | DeviceList n ->
9828 pr " throws LibGuestFSException";
9829 if semicolon then pr ";"
9831 and generate_java_struct jtyp cols () =
9832 generate_header CStyle LGPLv2plus;
9835 package com.redhat.et.libguestfs;
9838 * Libguestfs %s structure.
9850 | name, FBuffer -> pr " public String %s;\n" name
9851 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9852 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9853 | name, FChar -> pr " public char %s;\n" name
9854 | name, FOptPercent ->
9855 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9856 pr " public float %s;\n" name
9861 and generate_java_c () =
9862 generate_header CStyle LGPLv2plus;
9869 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9870 #include \"guestfs.h\"
9872 /* Note that this function returns. The exception is not thrown
9873 * until after the wrapper function returns.
9876 throw_exception (JNIEnv *env, const char *msg)
9879 cl = (*env)->FindClass (env,
9880 \"com/redhat/et/libguestfs/LibGuestFSException\");
9881 (*env)->ThrowNew (env, cl, msg);
9884 JNIEXPORT jlong JNICALL
9885 Java_com_redhat_et_libguestfs_GuestFS__1create
9886 (JNIEnv *env, jobject obj)
9890 g = guestfs_create ();
9892 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9895 guestfs_set_error_handler (g, NULL, NULL);
9896 return (jlong) (long) g;
9899 JNIEXPORT void JNICALL
9900 Java_com_redhat_et_libguestfs_GuestFS__1close
9901 (JNIEnv *env, jobject obj, jlong jg)
9903 guestfs_h *g = (guestfs_h *) (long) jg;
9910 fun (name, style, _, _, _, _, _) ->
9912 (match fst style with
9913 | RErr -> pr "void ";
9914 | RInt _ -> pr "jint ";
9915 | RInt64 _ -> pr "jlong ";
9916 | RBool _ -> pr "jboolean ";
9917 | RConstString _ | RConstOptString _ | RString _
9918 | RBufferOut _ -> pr "jstring ";
9919 | RStruct _ | RHashtable _ ->
9921 | RStringList _ | RStructList _ ->
9925 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9926 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9928 pr " (JNIEnv *env, jobject obj, jlong jg";
9932 | Device n | Dev_or_Path n
9937 pr ", jstring j%s" n
9938 | StringList n | DeviceList n ->
9939 pr ", jobjectArray j%s" n
9941 pr ", jboolean j%s" n
9949 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9950 let error_code, no_ret =
9951 match fst style with
9952 | RErr -> pr " int r;\n"; "-1", ""
9954 | RInt _ -> pr " int r;\n"; "-1", "0"
9955 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9956 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9957 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9959 pr " jstring jr;\n";
9960 pr " char *r;\n"; "NULL", "NULL"
9962 pr " jobjectArray jr;\n";
9965 pr " jstring jstr;\n";
9966 pr " char **r;\n"; "NULL", "NULL"
9967 | RStruct (_, typ) ->
9968 pr " jobject jr;\n";
9970 pr " jfieldID fl;\n";
9971 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9972 | RStructList (_, typ) ->
9973 pr " jobjectArray jr;\n";
9975 pr " jfieldID fl;\n";
9976 pr " jobject jfl;\n";
9977 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9978 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9980 pr " jstring jr;\n";
9982 pr " size_t size;\n";
9987 | Device n | Dev_or_Path n
9992 pr " const char *%s;\n" n
9993 | StringList n | DeviceList n ->
9994 pr " int %s_len;\n" n;
9995 pr " const char **%s;\n" n
10000 pr " int64_t %s;\n" n
10004 (match fst style with
10005 | RStringList _ | RStructList _ -> true
10006 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10007 | RConstOptString _
10008 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10009 List.exists (function
10010 | StringList _ -> true
10011 | DeviceList _ -> true
10012 | _ -> false) (snd style) in
10018 (* Get the parameters. *)
10022 | Device n | Dev_or_Path n
10026 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10028 (* This is completely undocumented, but Java null becomes
10029 * a NULL parameter.
10031 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10032 | StringList n | DeviceList n ->
10033 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10034 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10035 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10036 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10038 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10040 pr " %s[%s_len] = NULL;\n" n n;
10044 pr " %s = j%s;\n" n n
10047 (* Make the call. *)
10048 pr " r = guestfs_%s " name;
10049 generate_c_call_args ~handle:"g" style;
10052 (* Release the parameters. *)
10056 | Device n | Dev_or_Path n
10060 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10062 pr " if (j%s)\n" n;
10063 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10064 | StringList n | DeviceList n ->
10065 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10066 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10068 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10070 pr " free (%s);\n" n
10076 (* Check for errors. *)
10077 pr " if (r == %s) {\n" error_code;
10078 pr " throw_exception (env, guestfs_last_error (g));\n";
10079 pr " return %s;\n" no_ret;
10082 (* Return value. *)
10083 (match fst style with
10085 | RInt _ -> pr " return (jint) r;\n"
10086 | RBool _ -> pr " return (jboolean) r;\n"
10087 | RInt64 _ -> pr " return (jlong) r;\n"
10088 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10089 | RConstOptString _ ->
10090 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10092 pr " jr = (*env)->NewStringUTF (env, r);\n";
10096 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10097 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10098 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10099 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10100 pr " for (i = 0; i < r_len; ++i) {\n";
10101 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10102 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10103 pr " free (r[i]);\n";
10107 | RStruct (_, typ) ->
10108 let jtyp = java_name_of_struct typ in
10109 let cols = cols_of_struct typ in
10110 generate_java_struct_return typ jtyp cols
10111 | RStructList (_, typ) ->
10112 let jtyp = java_name_of_struct typ in
10113 let cols = cols_of_struct typ in
10114 generate_java_struct_list_return typ jtyp cols
10117 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10118 pr " return NULL;\n"
10120 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10129 and generate_java_struct_return typ jtyp cols =
10130 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10131 pr " jr = (*env)->AllocObject (env, cl);\n";
10135 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10136 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10139 pr " char s[33];\n";
10140 pr " memcpy (s, r->%s, 32);\n" name;
10141 pr " s[32] = 0;\n";
10142 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10143 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10147 pr " int len = r->%s_len;\n" name;
10148 pr " char s[len+1];\n";
10149 pr " memcpy (s, r->%s, len);\n" name;
10150 pr " s[len] = 0;\n";
10151 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10152 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10154 | name, (FBytes|FUInt64|FInt64) ->
10155 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10156 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10157 | name, (FUInt32|FInt32) ->
10158 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10159 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10160 | name, FOptPercent ->
10161 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10162 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10164 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10165 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10170 and generate_java_struct_list_return typ jtyp cols =
10171 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10172 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10173 pr " for (i = 0; i < r->len; ++i) {\n";
10174 pr " jfl = (*env)->AllocObject (env, cl);\n";
10178 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10179 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10182 pr " char s[33];\n";
10183 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10184 pr " s[32] = 0;\n";
10185 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10186 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10190 pr " int len = r->val[i].%s_len;\n" name;
10191 pr " char s[len+1];\n";
10192 pr " memcpy (s, r->val[i].%s, len);\n" name;
10193 pr " s[len] = 0;\n";
10194 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10195 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10197 | name, (FBytes|FUInt64|FInt64) ->
10198 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10199 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10200 | name, (FUInt32|FInt32) ->
10201 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10202 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10203 | name, FOptPercent ->
10204 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10205 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10207 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10208 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10210 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10212 pr " guestfs_free_%s_list (r);\n" typ;
10215 and generate_java_makefile_inc () =
10216 generate_header HashStyle GPLv2plus;
10218 pr "java_built_sources = \\\n";
10221 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10223 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10225 and generate_haskell_hs () =
10226 generate_header HaskellStyle LGPLv2plus;
10228 (* XXX We only know how to generate partial FFI for Haskell
10229 * at the moment. Please help out!
10231 let can_generate style =
10235 | RInt64 _, _ -> true
10237 | RConstString _, _
10238 | RConstOptString _, _
10244 | RBufferOut _, _ -> false in
10247 {-# INCLUDE <guestfs.h> #-}
10248 {-# LANGUAGE ForeignFunctionInterface #-}
10253 (* List out the names of the actions we want to export. *)
10255 fun (name, style, _, _, _, _, _) ->
10256 if can_generate style then pr ",\n %s" name
10262 -- Unfortunately some symbols duplicate ones already present
10263 -- in Prelude. We don't know which, so we hard-code a list
10265 import Prelude hiding (truncate)
10269 import Foreign.C.Types
10271 import Control.Exception
10272 import Data.Typeable
10274 data GuestfsS = GuestfsS -- represents the opaque C struct
10275 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10276 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10278 -- XXX define properly later XXX
10282 data IntBool = IntBool
10284 data StatVFS = StatVFS
10285 data Hashtable = Hashtable
10287 foreign import ccall unsafe \"guestfs_create\" c_create
10289 foreign import ccall unsafe \"&guestfs_close\" c_close
10290 :: FunPtr (GuestfsP -> IO ())
10291 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10292 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10294 create :: IO GuestfsH
10297 c_set_error_handler p nullPtr nullPtr
10298 h <- newForeignPtr c_close p
10301 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10302 :: GuestfsP -> IO CString
10304 -- last_error :: GuestfsH -> IO (Maybe String)
10305 -- last_error h = do
10306 -- str <- withForeignPtr h (\\p -> c_last_error p)
10307 -- maybePeek peekCString str
10309 last_error :: GuestfsH -> IO (String)
10311 str <- withForeignPtr h (\\p -> c_last_error p)
10312 if (str == nullPtr)
10313 then return \"no error\"
10314 else peekCString str
10318 (* Generate wrappers for each foreign function. *)
10320 fun (name, style, _, _, _, _, _) ->
10321 if can_generate style then (
10322 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10324 generate_haskell_prototype ~handle:"GuestfsP" style;
10328 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10330 pr "%s %s = do\n" name
10331 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10333 (* Convert pointer arguments using with* functions. *)
10338 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10339 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10340 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10341 | Bool _ | Int _ | Int64 _ -> ()
10343 (* Convert integer arguments. *)
10347 | Bool n -> sprintf "(fromBool %s)" n
10348 | Int n -> sprintf "(fromIntegral %s)" n
10349 | Int64 n -> sprintf "(fromIntegral %s)" n
10350 | FileIn n | FileOut n
10351 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10353 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10354 (String.concat " " ("p" :: args));
10355 (match fst style with
10356 | RErr | RInt _ | RInt64 _ | RBool _ ->
10357 pr " if (r == -1)\n";
10359 pr " err <- last_error h\n";
10361 | RConstString _ | RConstOptString _ | RString _
10362 | RStringList _ | RStruct _
10363 | RStructList _ | RHashtable _ | RBufferOut _ ->
10364 pr " if (r == nullPtr)\n";
10366 pr " err <- last_error h\n";
10369 (match fst style with
10371 pr " else return ()\n"
10373 pr " else return (fromIntegral r)\n"
10375 pr " else return (fromIntegral r)\n"
10377 pr " else return (toBool r)\n"
10379 | RConstOptString _
10386 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10392 and generate_haskell_prototype ~handle ?(hs = false) style =
10393 pr "%s -> " handle;
10394 let string = if hs then "String" else "CString" in
10395 let int = if hs then "Int" else "CInt" in
10396 let bool = if hs then "Bool" else "CInt" in
10397 let int64 = if hs then "Integer" else "Int64" in
10401 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10402 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10403 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10404 | Bool _ -> pr "%s" bool
10405 | Int _ -> pr "%s" int
10406 | Int64 _ -> pr "%s" int
10407 | FileIn _ -> pr "%s" string
10408 | FileOut _ -> pr "%s" string
10413 (match fst style with
10414 | RErr -> if not hs then pr "CInt"
10415 | RInt _ -> pr "%s" int
10416 | RInt64 _ -> pr "%s" int64
10417 | RBool _ -> pr "%s" bool
10418 | RConstString _ -> pr "%s" string
10419 | RConstOptString _ -> pr "Maybe %s" string
10420 | RString _ -> pr "%s" string
10421 | RStringList _ -> pr "[%s]" string
10422 | RStruct (_, typ) ->
10423 let name = java_name_of_struct typ in
10425 | RStructList (_, typ) ->
10426 let name = java_name_of_struct typ in
10428 | RHashtable _ -> pr "Hashtable"
10429 | RBufferOut _ -> pr "%s" string
10433 and generate_csharp () =
10434 generate_header CPlusPlusStyle LGPLv2plus;
10436 (* XXX Make this configurable by the C# assembly users. *)
10437 let library = "libguestfs.so.0" in
10440 // These C# bindings are highly experimental at present.
10442 // Firstly they only work on Linux (ie. Mono). In order to get them
10443 // to work on Windows (ie. .Net) you would need to port the library
10444 // itself to Windows first.
10446 // The second issue is that some calls are known to be incorrect and
10447 // can cause Mono to segfault. Particularly: calls which pass or
10448 // return string[], or return any structure value. This is because
10449 // we haven't worked out the correct way to do this from C#.
10451 // The third issue is that when compiling you get a lot of warnings.
10452 // We are not sure whether the warnings are important or not.
10454 // Fourthly we do not routinely build or test these bindings as part
10455 // of the make && make check cycle, which means that regressions might
10458 // Suggestions and patches are welcome.
10462 // gmcs Libguestfs.cs
10463 // mono Libguestfs.exe
10465 // (You'll probably want to add a Test class / static main function
10466 // otherwise this won't do anything useful).
10470 using System.Runtime.InteropServices;
10471 using System.Runtime.Serialization;
10472 using System.Collections;
10476 class Error : System.ApplicationException
10478 public Error (string message) : base (message) {}
10479 protected Error (SerializationInfo info, StreamingContext context) {}
10486 [DllImport (\"%s\")]
10487 static extern IntPtr guestfs_create ();
10491 _handle = guestfs_create ();
10492 if (_handle == IntPtr.Zero)
10493 throw new Error (\"could not create guestfs handle\");
10496 [DllImport (\"%s\")]
10497 static extern void guestfs_close (IntPtr h);
10501 guestfs_close (_handle);
10504 [DllImport (\"%s\")]
10505 static extern string guestfs_last_error (IntPtr h);
10507 " library library library;
10509 (* Generate C# structure bindings. We prefix struct names with
10510 * underscore because C# cannot have conflicting struct names and
10511 * method names (eg. "class stat" and "stat").
10515 pr " [StructLayout (LayoutKind.Sequential)]\n";
10516 pr " public class _%s {\n" typ;
10519 | name, FChar -> pr " char %s;\n" name
10520 | name, FString -> pr " string %s;\n" name
10522 pr " uint %s_len;\n" name;
10523 pr " string %s;\n" name
10525 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10526 pr " string %s;\n" name
10527 | name, FUInt32 -> pr " uint %s;\n" name
10528 | name, FInt32 -> pr " int %s;\n" name
10529 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10530 | name, FInt64 -> pr " long %s;\n" name
10531 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10537 (* Generate C# function bindings. *)
10539 fun (name, style, _, _, _, shortdesc, _) ->
10540 let rec csharp_return_type () =
10541 match fst style with
10543 | RBool n -> "bool"
10545 | RInt64 n -> "long"
10547 | RConstOptString n
10549 | RBufferOut n -> "string"
10550 | RStruct (_,n) -> "_" ^ n
10551 | RHashtable n -> "Hashtable"
10552 | RStringList n -> "string[]"
10553 | RStructList (_,n) -> sprintf "_%s[]" n
10555 and c_return_type () =
10556 match fst style with
10560 | RInt64 _ -> "long"
10562 | RConstOptString _
10564 | RBufferOut _ -> "string"
10565 | RStruct (_,n) -> "_" ^ n
10567 | RStringList _ -> "string[]"
10568 | RStructList (_,n) -> sprintf "_%s[]" n
10570 and c_error_comparison () =
10571 match fst style with
10575 | RInt64 _ -> "== -1"
10577 | RConstOptString _
10583 | RStructList (_,_) -> "== null"
10585 and generate_extern_prototype () =
10586 pr " static extern %s guestfs_%s (IntPtr h"
10587 (c_return_type ()) name;
10590 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10591 | FileIn n | FileOut n ->
10592 pr ", [In] string %s" n
10593 | StringList n | DeviceList n ->
10594 pr ", [In] string[] %s" n
10604 and generate_public_prototype () =
10605 pr " public %s %s (" (csharp_return_type ()) name;
10606 let comma = ref false in
10608 if !comma then pr ", ";
10613 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10614 | FileIn n | FileOut n ->
10615 next (); pr "string %s" n
10616 | StringList n | DeviceList n ->
10617 next (); pr "string[] %s" n
10619 next (); pr "bool %s" n
10621 next (); pr "int %s" n
10623 next (); pr "long %s" n
10627 and generate_call () =
10628 pr "guestfs_%s (_handle" name;
10629 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10633 pr " [DllImport (\"%s\")]\n" library;
10634 generate_extern_prototype ();
10636 pr " /// <summary>\n";
10637 pr " /// %s\n" shortdesc;
10638 pr " /// </summary>\n";
10639 generate_public_prototype ();
10641 pr " %s r;\n" (c_return_type ());
10644 pr " if (r %s)\n" (c_error_comparison ());
10645 pr " throw new Error (guestfs_last_error (_handle));\n";
10646 (match fst style with
10649 pr " return r != 0 ? true : false;\n"
10651 pr " Hashtable rr = new Hashtable ();\n";
10652 pr " for (int i = 0; i < r.Length; i += 2)\n";
10653 pr " rr.Add (r[i], r[i+1]);\n";
10655 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10656 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10662 ) all_functions_sorted;
10668 and generate_bindtests () =
10669 generate_header CStyle LGPLv2plus;
10673 #include <stdlib.h>
10674 #include <inttypes.h>
10675 #include <string.h>
10677 #include \"guestfs.h\"
10678 #include \"guestfs-internal.h\"
10679 #include \"guestfs-internal-actions.h\"
10680 #include \"guestfs_protocol.h\"
10682 #define error guestfs_error
10683 #define safe_calloc guestfs_safe_calloc
10684 #define safe_malloc guestfs_safe_malloc
10687 print_strings (char *const *argv)
10692 for (argc = 0; argv[argc] != NULL; ++argc) {
10693 if (argc > 0) printf (\", \");
10694 printf (\"\\\"%%s\\\"\", argv[argc]);
10699 /* The test0 function prints its parameters to stdout. */
10703 match test_functions with
10704 | [] -> assert false
10705 | test0 :: tests -> test0, tests in
10708 let (name, style, _, _, _, _, _) = test0 in
10709 generate_prototype ~extern:false ~semicolon:false ~newline:true
10710 ~handle:"g" ~prefix:"guestfs__" name style;
10715 | Device n | Dev_or_Path n
10718 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10719 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10720 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10721 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10722 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10723 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10725 pr " /* Java changes stdout line buffering so we need this: */\n";
10726 pr " fflush (stdout);\n";
10732 fun (name, style, _, _, _, _, _) ->
10733 if String.sub name (String.length name - 3) 3 <> "err" then (
10734 pr "/* Test normal return. */\n";
10735 generate_prototype ~extern:false ~semicolon:false ~newline:true
10736 ~handle:"g" ~prefix:"guestfs__" name style;
10738 (match fst style with
10743 pr " sscanf (val, \"%%d\", &r);\n";
10746 pr " int64_t r;\n";
10747 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10750 pr " return STREQ (val, \"true\");\n"
10752 | RConstOptString _ ->
10753 (* Can't return the input string here. Return a static
10754 * string so we ensure we get a segfault if the caller
10755 * tries to free it.
10757 pr " return \"static string\";\n"
10759 pr " return strdup (val);\n"
10761 pr " char **strs;\n";
10763 pr " sscanf (val, \"%%d\", &n);\n";
10764 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10765 pr " for (i = 0; i < n; ++i) {\n";
10766 pr " strs[i] = safe_malloc (g, 16);\n";
10767 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10769 pr " strs[n] = NULL;\n";
10770 pr " return strs;\n"
10771 | RStruct (_, typ) ->
10772 pr " struct guestfs_%s *r;\n" typ;
10773 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10775 | RStructList (_, typ) ->
10776 pr " struct guestfs_%s_list *r;\n" typ;
10777 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10778 pr " sscanf (val, \"%%d\", &r->len);\n";
10779 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10782 pr " char **strs;\n";
10784 pr " sscanf (val, \"%%d\", &n);\n";
10785 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10786 pr " for (i = 0; i < n; ++i) {\n";
10787 pr " strs[i*2] = safe_malloc (g, 16);\n";
10788 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10789 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10790 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10792 pr " strs[n*2] = NULL;\n";
10793 pr " return strs;\n"
10795 pr " return strdup (val);\n"
10800 pr "/* Test error return. */\n";
10801 generate_prototype ~extern:false ~semicolon:false ~newline:true
10802 ~handle:"g" ~prefix:"guestfs__" name style;
10804 pr " error (g, \"error\");\n";
10805 (match fst style with
10806 | RErr | RInt _ | RInt64 _ | RBool _ ->
10808 | RConstString _ | RConstOptString _
10809 | RString _ | RStringList _ | RStruct _
10813 pr " return NULL;\n"
10820 and generate_ocaml_bindtests () =
10821 generate_header OCamlStyle GPLv2plus;
10825 let g = Guestfs.create () in
10829 String.concat " " (
10832 | CallString s -> "\"" ^ s ^ "\""
10833 | CallOptString None -> "None"
10834 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10835 | CallStringList xs ->
10836 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10837 | CallInt i when i >= 0 -> string_of_int i
10838 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10839 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10840 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10841 | CallBool b -> string_of_bool b
10846 generate_lang_bindtests (
10847 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10850 pr "print_endline \"EOF\"\n"
10852 and generate_perl_bindtests () =
10853 pr "#!/usr/bin/perl -w\n";
10854 generate_header HashStyle GPLv2plus;
10861 my $g = Sys::Guestfs->new ();
10865 String.concat ", " (
10868 | CallString s -> "\"" ^ s ^ "\""
10869 | CallOptString None -> "undef"
10870 | CallOptString (Some s) -> sprintf "\"%s\"" s
10871 | CallStringList xs ->
10872 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10873 | CallInt i -> string_of_int i
10874 | CallInt64 i -> Int64.to_string i
10875 | CallBool b -> if b then "1" else "0"
10880 generate_lang_bindtests (
10881 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10884 pr "print \"EOF\\n\"\n"
10886 and generate_python_bindtests () =
10887 generate_header HashStyle GPLv2plus;
10892 g = guestfs.GuestFS ()
10896 String.concat ", " (
10899 | CallString s -> "\"" ^ s ^ "\""
10900 | CallOptString None -> "None"
10901 | CallOptString (Some s) -> sprintf "\"%s\"" s
10902 | CallStringList xs ->
10903 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10904 | CallInt i -> string_of_int i
10905 | CallInt64 i -> Int64.to_string i
10906 | CallBool b -> if b then "1" else "0"
10911 generate_lang_bindtests (
10912 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10915 pr "print \"EOF\"\n"
10917 and generate_ruby_bindtests () =
10918 generate_header HashStyle GPLv2plus;
10923 g = Guestfs::create()
10927 String.concat ", " (
10930 | CallString s -> "\"" ^ s ^ "\""
10931 | CallOptString None -> "nil"
10932 | CallOptString (Some s) -> sprintf "\"%s\"" s
10933 | CallStringList xs ->
10934 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10935 | CallInt i -> string_of_int i
10936 | CallInt64 i -> Int64.to_string i
10937 | CallBool b -> string_of_bool b
10942 generate_lang_bindtests (
10943 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10946 pr "print \"EOF\\n\"\n"
10948 and generate_java_bindtests () =
10949 generate_header CStyle GPLv2plus;
10952 import com.redhat.et.libguestfs.*;
10954 public class Bindtests {
10955 public static void main (String[] argv)
10958 GuestFS g = new GuestFS ();
10962 String.concat ", " (
10965 | CallString s -> "\"" ^ s ^ "\""
10966 | CallOptString None -> "null"
10967 | CallOptString (Some s) -> sprintf "\"%s\"" s
10968 | CallStringList xs ->
10970 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10971 | CallInt i -> string_of_int i
10972 | CallInt64 i -> Int64.to_string i
10973 | CallBool b -> string_of_bool b
10978 generate_lang_bindtests (
10979 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
10983 System.out.println (\"EOF\");
10985 catch (Exception exn) {
10986 System.err.println (exn);
10993 and generate_haskell_bindtests () =
10994 generate_header HaskellStyle GPLv2plus;
10997 module Bindtests where
10998 import qualified Guestfs
11001 g <- Guestfs.create
11005 String.concat " " (
11008 | CallString s -> "\"" ^ s ^ "\""
11009 | CallOptString None -> "Nothing"
11010 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11011 | CallStringList xs ->
11012 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11013 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11014 | CallInt i -> string_of_int i
11015 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11016 | CallInt64 i -> Int64.to_string i
11017 | CallBool true -> "True"
11018 | CallBool false -> "False"
11023 generate_lang_bindtests (
11024 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11027 pr " putStrLn \"EOF\"\n"
11029 (* Language-independent bindings tests - we do it this way to
11030 * ensure there is parity in testing bindings across all languages.
11032 and generate_lang_bindtests call =
11033 call "test0" [CallString "abc"; CallOptString (Some "def");
11034 CallStringList []; CallBool false;
11035 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11036 call "test0" [CallString "abc"; CallOptString None;
11037 CallStringList []; CallBool false;
11038 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11039 call "test0" [CallString ""; CallOptString (Some "def");
11040 CallStringList []; CallBool false;
11041 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11042 call "test0" [CallString ""; CallOptString (Some "");
11043 CallStringList []; CallBool false;
11044 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11045 call "test0" [CallString "abc"; CallOptString (Some "def");
11046 CallStringList ["1"]; CallBool false;
11047 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11048 call "test0" [CallString "abc"; CallOptString (Some "def");
11049 CallStringList ["1"; "2"]; CallBool false;
11050 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11051 call "test0" [CallString "abc"; CallOptString (Some "def");
11052 CallStringList ["1"]; CallBool true;
11053 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11054 call "test0" [CallString "abc"; CallOptString (Some "def");
11055 CallStringList ["1"]; CallBool false;
11056 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11057 call "test0" [CallString "abc"; CallOptString (Some "def");
11058 CallStringList ["1"]; CallBool false;
11059 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11060 call "test0" [CallString "abc"; CallOptString (Some "def");
11061 CallStringList ["1"]; CallBool false;
11062 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11063 call "test0" [CallString "abc"; CallOptString (Some "def");
11064 CallStringList ["1"]; CallBool false;
11065 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11066 call "test0" [CallString "abc"; CallOptString (Some "def");
11067 CallStringList ["1"]; CallBool false;
11068 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11069 call "test0" [CallString "abc"; CallOptString (Some "def");
11070 CallStringList ["1"]; CallBool false;
11071 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11073 (* XXX Add here tests of the return and error functions. *)
11075 (* Code to generator bindings for virt-inspector. Currently only
11076 * implemented for OCaml code (for virt-p2v 2.0).
11078 let rng_input = "inspector/virt-inspector.rng"
11080 (* Read the input file and parse it into internal structures. This is
11081 * by no means a complete RELAX NG parser, but is just enough to be
11082 * able to parse the specific input file.
11085 | Element of string * rng list (* <element name=name/> *)
11086 | Attribute of string * rng list (* <attribute name=name/> *)
11087 | Interleave of rng list (* <interleave/> *)
11088 | ZeroOrMore of rng (* <zeroOrMore/> *)
11089 | OneOrMore of rng (* <oneOrMore/> *)
11090 | Optional of rng (* <optional/> *)
11091 | Choice of string list (* <choice><value/>*</choice> *)
11092 | Value of string (* <value>str</value> *)
11093 | Text (* <text/> *)
11095 let rec string_of_rng = function
11096 | Element (name, xs) ->
11097 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11098 | Attribute (name, xs) ->
11099 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11100 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11101 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11102 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11103 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11104 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11105 | Value value -> "Value \"" ^ value ^ "\""
11108 and string_of_rng_list xs =
11109 String.concat ", " (List.map string_of_rng xs)
11111 let rec parse_rng ?defines context = function
11113 | Xml.Element ("element", ["name", name], children) :: rest ->
11114 Element (name, parse_rng ?defines context children)
11115 :: parse_rng ?defines context rest
11116 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11117 Attribute (name, parse_rng ?defines context children)
11118 :: parse_rng ?defines context rest
11119 | Xml.Element ("interleave", [], children) :: rest ->
11120 Interleave (parse_rng ?defines context children)
11121 :: parse_rng ?defines context rest
11122 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11123 let rng = parse_rng ?defines context [child] in
11125 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11127 failwithf "%s: <zeroOrMore> contains more than one child element"
11130 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11131 let rng = parse_rng ?defines context [child] in
11133 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11135 failwithf "%s: <oneOrMore> contains more than one child element"
11138 | Xml.Element ("optional", [], [child]) :: rest ->
11139 let rng = parse_rng ?defines context [child] in
11141 | [child] -> Optional child :: parse_rng ?defines context rest
11143 failwithf "%s: <optional> contains more than one child element"
11146 | Xml.Element ("choice", [], children) :: rest ->
11147 let values = List.map (
11148 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11150 failwithf "%s: can't handle anything except <value> in <choice>"
11154 :: parse_rng ?defines context rest
11155 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11156 Value value :: parse_rng ?defines context rest
11157 | Xml.Element ("text", [], []) :: rest ->
11158 Text :: parse_rng ?defines context rest
11159 | Xml.Element ("ref", ["name", name], []) :: rest ->
11160 (* Look up the reference. Because of limitations in this parser,
11161 * we can't handle arbitrarily nested <ref> yet. You can only
11162 * use <ref> from inside <start>.
11164 (match defines with
11166 failwithf "%s: contains <ref>, but no refs are defined yet" context
11168 let rng = StringMap.find name map in
11169 rng @ parse_rng ?defines context rest
11172 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11175 let xml = Xml.parse_file rng_input in
11177 | Xml.Element ("grammar", _,
11178 Xml.Element ("start", _, gram) :: defines) ->
11179 (* The <define/> elements are referenced in the <start> section,
11180 * so build a map of those first.
11182 let defines = List.fold_left (
11184 function Xml.Element ("define", ["name", name], defn) ->
11185 StringMap.add name defn map
11187 failwithf "%s: expected <define name=name/>" rng_input
11188 ) StringMap.empty defines in
11189 let defines = StringMap.mapi parse_rng defines in
11191 (* Parse the <start> clause, passing the defines. *)
11192 parse_rng ~defines "<start>" gram
11194 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11197 let name_of_field = function
11198 | Element (name, _) | Attribute (name, _)
11199 | ZeroOrMore (Element (name, _))
11200 | OneOrMore (Element (name, _))
11201 | Optional (Element (name, _)) -> name
11202 | Optional (Attribute (name, _)) -> name
11203 | Text -> (* an unnamed field in an element *)
11206 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11208 (* At the moment this function only generates OCaml types. However we
11209 * should parameterize it later so it can generate types/structs in a
11210 * variety of languages.
11212 let generate_types xs =
11213 (* A simple type is one that can be printed out directly, eg.
11214 * "string option". A complex type is one which has a name and has
11215 * to be defined via another toplevel definition, eg. a struct.
11217 * generate_type generates code for either simple or complex types.
11218 * In the simple case, it returns the string ("string option"). In
11219 * the complex case, it returns the name ("mountpoint"). In the
11220 * complex case it has to print out the definition before returning,
11221 * so it should only be called when we are at the beginning of a
11222 * new line (BOL context).
11224 let rec generate_type = function
11225 | Text -> (* string *)
11227 | Choice values -> (* [`val1|`val2|...] *)
11228 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11229 | ZeroOrMore rng -> (* <rng> list *)
11230 let t, is_simple = generate_type rng in
11231 t ^ " list (* 0 or more *)", is_simple
11232 | OneOrMore rng -> (* <rng> list *)
11233 let t, is_simple = generate_type rng in
11234 t ^ " list (* 1 or more *)", is_simple
11235 (* virt-inspector hack: bool *)
11236 | Optional (Attribute (name, [Value "1"])) ->
11238 | Optional rng -> (* <rng> list *)
11239 let t, is_simple = generate_type rng in
11240 t ^ " option", is_simple
11241 (* type name = { fields ... } *)
11242 | Element (name, fields) when is_attrs_interleave fields ->
11243 generate_type_struct name (get_attrs_interleave fields)
11244 | Element (name, [field]) (* type name = field *)
11245 | Attribute (name, [field]) ->
11246 let t, is_simple = generate_type field in
11247 if is_simple then (t, true)
11249 pr "type %s = %s\n" name t;
11252 | Element (name, fields) -> (* type name = { fields ... } *)
11253 generate_type_struct name fields
11255 failwithf "generate_type failed at: %s" (string_of_rng rng)
11257 and is_attrs_interleave = function
11258 | [Interleave _] -> true
11259 | Attribute _ :: fields -> is_attrs_interleave fields
11260 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11263 and get_attrs_interleave = function
11264 | [Interleave fields] -> fields
11265 | ((Attribute _) as field) :: fields
11266 | ((Optional (Attribute _)) as field) :: fields ->
11267 field :: get_attrs_interleave fields
11268 | _ -> assert false
11270 and generate_types xs =
11271 List.iter (fun x -> ignore (generate_type x)) xs
11273 and generate_type_struct name fields =
11274 (* Calculate the types of the fields first. We have to do this
11275 * before printing anything so we are still in BOL context.
11277 let types = List.map fst (List.map generate_type fields) in
11279 (* Special case of a struct containing just a string and another
11280 * field. Turn it into an assoc list.
11283 | ["string"; other] ->
11284 let fname1, fname2 =
11286 | [f1; f2] -> name_of_field f1, name_of_field f2
11287 | _ -> assert false in
11288 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11292 pr "type %s = {\n" name;
11294 fun (field, ftype) ->
11295 let fname = name_of_field field in
11296 pr " %s_%s : %s;\n" name fname ftype
11297 ) (List.combine fields types);
11299 (* Return the name of this type, and
11300 * false because it's not a simple type.
11307 let generate_parsers xs =
11308 (* As for generate_type above, generate_parser makes a parser for
11309 * some type, and returns the name of the parser it has generated.
11310 * Because it (may) need to print something, it should always be
11311 * called in BOL context.
11313 let rec generate_parser = function
11314 | Text -> (* string *)
11315 "string_child_or_empty"
11316 | Choice values -> (* [`val1|`val2|...] *)
11317 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11319 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11320 | ZeroOrMore rng -> (* <rng> list *)
11321 let pa = generate_parser rng in
11322 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11323 | OneOrMore rng -> (* <rng> list *)
11324 let pa = generate_parser rng in
11325 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11326 (* virt-inspector hack: bool *)
11327 | Optional (Attribute (name, [Value "1"])) ->
11328 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11329 | Optional rng -> (* <rng> list *)
11330 let pa = generate_parser rng in
11331 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11332 (* type name = { fields ... } *)
11333 | Element (name, fields) when is_attrs_interleave fields ->
11334 generate_parser_struct name (get_attrs_interleave fields)
11335 | Element (name, [field]) -> (* type name = field *)
11336 let pa = generate_parser field in
11337 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11338 pr "let %s =\n" parser_name;
11340 pr "let parse_%s = %s\n" name parser_name;
11342 | Attribute (name, [field]) ->
11343 let pa = generate_parser field in
11344 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11345 pr "let %s =\n" parser_name;
11347 pr "let parse_%s = %s\n" name parser_name;
11349 | Element (name, fields) -> (* type name = { fields ... } *)
11350 generate_parser_struct name ([], fields)
11352 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11354 and is_attrs_interleave = function
11355 | [Interleave _] -> true
11356 | Attribute _ :: fields -> is_attrs_interleave fields
11357 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11360 and get_attrs_interleave = function
11361 | [Interleave fields] -> [], fields
11362 | ((Attribute _) as field) :: fields
11363 | ((Optional (Attribute _)) as field) :: fields ->
11364 let attrs, interleaves = get_attrs_interleave fields in
11365 (field :: attrs), interleaves
11366 | _ -> assert false
11368 and generate_parsers xs =
11369 List.iter (fun x -> ignore (generate_parser x)) xs
11371 and generate_parser_struct name (attrs, interleaves) =
11372 (* Generate parsers for the fields first. We have to do this
11373 * before printing anything so we are still in BOL context.
11375 let fields = attrs @ interleaves in
11376 let pas = List.map generate_parser fields in
11378 (* Generate an intermediate tuple from all the fields first.
11379 * If the type is just a string + another field, then we will
11380 * return this directly, otherwise it is turned into a record.
11382 * RELAX NG note: This code treats <interleave> and plain lists of
11383 * fields the same. In other words, it doesn't bother enforcing
11384 * any ordering of fields in the XML.
11386 pr "let parse_%s x =\n" name;
11387 pr " let t = (\n ";
11388 let comma = ref false in
11391 if !comma then pr ",\n ";
11394 | Optional (Attribute (fname, [field])), pa ->
11396 | Optional (Element (fname, [field])), pa ->
11397 pr "%s (optional_child %S x)" pa fname
11398 | Attribute (fname, [Text]), _ ->
11399 pr "attribute %S x" fname
11400 | (ZeroOrMore _ | OneOrMore _), pa ->
11405 let fname = name_of_field field in
11406 pr "%s (child %S x)" pa fname
11407 ) (List.combine fields pas);
11411 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11415 pr " (Obj.magic t : %s)\n" name
11419 | (Optional (Attribute (fname, [field])), pa) ->
11420 pr " %s_%s =\n" name fname;
11422 | (Optional (Element (fname, [field])), pa) ->
11423 pr " %s_%s =\n" name fname;
11424 pr " (let x = optional_child %S x in\n" fname;
11427 let fname = name_of_field field in
11428 pr " %s_%s =\n" name fname;
11429 pr " (let x = child %S x in\n" fname;
11431 ) (List.combine fields pas);
11435 sprintf "parse_%s" name
11438 generate_parsers xs
11440 (* Generate ocaml/guestfs_inspector.mli. *)
11441 let generate_ocaml_inspector_mli () =
11442 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11445 (** This is an OCaml language binding to the external [virt-inspector]
11448 For more information, please read the man page [virt-inspector(1)].
11453 generate_types grammar;
11454 pr "(** The nested information returned from the {!inspect} function. *)\n";
11458 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11459 (** To inspect a libvirt domain called [name], pass a singleton
11460 list: [inspect [name]]. When using libvirt only, you may
11461 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11463 To inspect a disk image or images, pass a list of the filenames
11464 of the disk images: [inspect filenames]
11466 This function inspects the given guest or disk images and
11467 returns a list of operating system(s) found and a large amount
11468 of information about them. In the vast majority of cases,
11469 a virtual machine only contains a single operating system.
11471 If the optional [~xml] parameter is given, then this function
11472 skips running the external virt-inspector program and just
11473 parses the given XML directly (which is expected to be XML
11474 produced from a previous run of virt-inspector). The list of
11475 names and connect URI are ignored in this case.
11477 This function can throw a wide variety of exceptions, for example
11478 if the external virt-inspector program cannot be found, or if
11479 it doesn't generate valid XML.
11483 (* Generate ocaml/guestfs_inspector.ml. *)
11484 let generate_ocaml_inspector_ml () =
11485 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11490 generate_types grammar;
11494 (* Misc functions which are used by the parser code below. *)
11495 let first_child = function
11496 | Xml.Element (_, _, c::_) -> c
11497 | Xml.Element (name, _, []) ->
11498 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11499 | Xml.PCData str ->
11500 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11502 let string_child_or_empty = function
11503 | Xml.Element (_, _, [Xml.PCData s]) -> s
11504 | Xml.Element (_, _, []) -> \"\"
11505 | Xml.Element (x, _, _) ->
11506 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11508 | Xml.PCData str ->
11509 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11511 let optional_child name xml =
11512 let children = Xml.children xml in
11514 Some (List.find (function
11515 | Xml.Element (n, _, _) when n = name -> true
11516 | _ -> false) children)
11520 let child name xml =
11521 match optional_child name xml with
11524 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11526 let attribute name xml =
11527 try Xml.attrib xml name
11528 with Xml.No_attribute _ ->
11529 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11533 generate_parsers grammar;
11537 (* Run external virt-inspector, then use parser to parse the XML. *)
11538 let inspect ?connect ?xml names =
11542 if names = [] then invalid_arg \"inspect: no names given\";
11543 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11544 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11546 let cmd = List.map Filename.quote cmd in
11547 let cmd = String.concat \" \" cmd in
11548 let chan = open_process_in cmd in
11549 let xml = Xml.parse_in chan in
11550 (match close_process_in chan with
11552 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11553 | WSIGNALED i | WSTOPPED i ->
11554 failwith (\"external virt-inspector command died or stopped on sig \" ^
11559 Xml.parse_string doc in
11560 parse_operatingsystems xml
11563 (* This is used to generate the src/MAX_PROC_NR file which
11564 * contains the maximum procedure number, a surrogate for the
11565 * ABI version number. See src/Makefile.am for the details.
11567 and generate_max_proc_nr () =
11568 let proc_nrs = List.map (
11569 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11570 ) daemon_functions in
11572 let max_proc_nr = List.fold_left max 0 proc_nrs in
11574 pr "%d\n" max_proc_nr
11576 let output_to filename k =
11577 let filename_new = filename ^ ".new" in
11578 chan := open_out filename_new;
11581 chan := Pervasives.stdout;
11583 (* Is the new file different from the current file? *)
11584 if Sys.file_exists filename && files_equal filename filename_new then
11585 unlink filename_new (* same, so skip it *)
11587 (* different, overwrite old one *)
11588 (try chmod filename 0o644 with Unix_error _ -> ());
11589 rename filename_new filename;
11590 chmod filename 0o444;
11591 printf "written %s\n%!" filename;
11594 let perror msg = function
11595 | Unix_error (err, _, _) ->
11596 eprintf "%s: %s\n" msg (error_message err)
11598 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11600 (* Main program. *)
11603 try openfile "HACKING" [O_RDWR] 0
11605 | Unix_error (ENOENT, _, _) ->
11607 You are probably running this from the wrong directory.
11608 Run it from the top source directory using the command
11613 perror "open: HACKING" exn;
11616 (* Acquire a lock so parallel builds won't try to run the generator
11617 * twice at the same time. Subsequent builds will wait for the first
11618 * one to finish. Note the lock is released implicitly when the
11621 (try lockf lock_fd F_LOCK 1
11623 perror "lock: HACKING" exn;
11626 check_functions ();
11628 output_to "src/guestfs_protocol.x" generate_xdr;
11629 output_to "src/guestfs-structs.h" generate_structs_h;
11630 output_to "src/guestfs-actions.h" generate_actions_h;
11631 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11632 output_to "src/guestfs-actions.c" generate_client_actions;
11633 output_to "src/guestfs-bindtests.c" generate_bindtests;
11634 output_to "src/guestfs-structs.pod" generate_structs_pod;
11635 output_to "src/guestfs-actions.pod" generate_actions_pod;
11636 output_to "src/guestfs-availability.pod" generate_availability_pod;
11637 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11638 output_to "src/libguestfs.syms" generate_linker_script;
11639 output_to "daemon/actions.h" generate_daemon_actions_h;
11640 output_to "daemon/stubs.c" generate_daemon_actions;
11641 output_to "daemon/names.c" generate_daemon_names;
11642 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11643 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11644 output_to "capitests/tests.c" generate_tests;
11645 output_to "fish/cmds.c" generate_fish_cmds;
11646 output_to "fish/completion.c" generate_fish_completion;
11647 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11648 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11649 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11650 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11651 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11652 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11653 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11654 output_to "perl/Guestfs.xs" generate_perl_xs;
11655 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11656 output_to "perl/bindtests.pl" generate_perl_bindtests;
11657 output_to "python/guestfs-py.c" generate_python_c;
11658 output_to "python/guestfs.py" generate_python_py;
11659 output_to "python/bindtests.py" generate_python_bindtests;
11660 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11661 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11662 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11666 let cols = cols_of_struct typ in
11667 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11668 output_to filename (generate_java_struct jtyp cols);
11671 output_to "java/Makefile.inc" generate_java_makefile_inc;
11672 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11673 output_to "java/Bindtests.java" generate_java_bindtests;
11674 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11675 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11676 output_to "csharp/Libguestfs.cs" generate_csharp;
11678 (* Always generate this file last, and unconditionally. It's used
11679 * by the Makefile to know when we must re-run the generator.
11681 let chan = open_out "src/stamp-generator" in
11682 fprintf chan "1\n";
11685 printf "generated %d lines of code\n" !lines